面试官灵魂发问:你是如何组织管理你的 CSS 代码的? 

答:先写类名, 然后写样式。 

卒,享年18. 


借由这个面试题目, 我们来了解 css 管理方式一共有几种。 

首先写列个大纲: 

  1. 佛性选手, 复制粘贴一把梭. 
  2. 命名空间
  3. 命名空间 + BEM 规范
  4. CSS module 
  5. css in js 


方案一.  命名空间 + BEM 规范

原理:强行增加一个最外层的命名空间将底部样式包裹起来。

A.less

.componentA {
.title {
color: red;
}

.des {
...
}
}

B.less

.componentB {
.title {
color: red;
}

.des {
...
}
}

样式名遵循 BEM 规范, 让维护者可以从类名就分辨出 dom 上的嵌套情况。方便维护, 如下代码:

.componentA {
&__title {
font-size: 14px;
}
}
<div class="componentA">
<h1 class="componentA__title">组件A的title</h1>
</div>

该方案适用于组件库的编写。作为一个规范的 BEM ,使用者更容易使用。但是如果在一个庞大的业务中, 如果我们只用 BEM + 命名空间来控制样式不重叠, 就有点力不从心了。你不可能每开始一个需求, 就查一下目前有多少命名空间。维护变得很困难。所以, 基于这种方案之下, 又延伸了 2种 CSS 管理方案

  • 方案二:CSS in JS
  • 方案三:CSS Modules


方案二.  CSS in JS

使用 js 语言写 css ,目前比较受欢迎的:   styled-components. 语法如下:

import React from 'react';
import styled from 'styled-components';
const Title = styled.h1`
font-size: 1.5em;
text-align: center;
color: palevioletred;
`;
<Title>
Hello World, this is my first styled component!
</Title>

emmm, 仁者见仁, 智者见智。如果喜欢这种方式,可以尝试使用。作者没有采用这种方案, 比较喜欢 js 跟 css 隔离的感觉。没有实践没有发言权, 所以就不赘述了.


方案三.  CSS Modules 

原理:利用 webpack 等构建工具自动将类名换成局部。详细配置: https://webpack.docschina.org/loaders/css-loader/比如, 配置样式名规则: 

{

    loader: 'css-loader',

    options: {

          importLoaders: 2,

          modules: isModules,

          localIdentName: '[name]__[local]__[hash:base64:5]'

    }

}


代码如下: 


import React from 'react';

import style from './App.css';


export default () => {

 return (

   <h1 className={style.title}>

     Hello World

   </h1>

 );

};

在 app.css 中

.title {

   color: red;

}

可是这种方法有很多限制, 如下: 

  • 无论何时构造类名,都必须使用styles对象。
  • 混合CSS模块和全局CSS类是很麻烦的。
  • 对未定义的CSS模块的引用解析为未定义,没有警告。


基于上面的问题,  react 有一个插件  react-css-modules . 它可以让你直接写 styleName 或者 className 来区分是本地类名还是全局类名. 且通通解决上面的问题. 


<div styleName="lock-item" className="lock-global">

    老师列表

</div>

编译后的 CSS,classname 根据配置的规则生成了对应的名字。

面试官:你怎么优雅写 CSS?_类名

可以看到, className 的并不会根据 webpack 的 配置生成对应的类名, styleName 则会. 在书写样式时, 也可方便的使用 :global 和 :local 来区分是全局.  :local 是默认注入的, 因此只需要对全局样式标明即可. 

.lock-item {

   line-height: 24px;

   margin-bottom: 8px;

}

:global .lock-global {

   color: red;

}

在 babel-plugin-react-css-modules  中配置如下: 

面试官:你怎么优雅写 CSS?_命名空间_02


至此, 我们总结一下上面的内容: 


1、 命名空间方案 编写组件库使用 BEM 规范 + 命名空间方案来. 这样第三方在调用的时候, 有规范可言, 且不会随着打包每次的样式名都发生改变. 

2、css in js / css module 方案大型业务场景中使用 css modules 或者 css in js。毕竟让工具来解决问题才是最彻底的解决问题。我们不可能去 diff 每一个地方, 控制大家样式名不冲突.




面试官:你怎么优雅写 CSS?_命名空间_03



好, 看完上面的内容, 大概可以回答一下面试官的灵魂发问了. 时间回溯, 重来一遍. 



面试官:你是如何组织管理你的 CSS 代码的? 答:分场景. 一. 在编写公共组件库的时候, 使用 BEM + 命名空间 ……  二. …… 面试官:  那 css module 中, 你们如何处理引入的第三方库样式? 答: css module 中有可以开启 module 和关闭module的选项. 对于第三方库样式, 关闭 module 选项即可. 配置如下: 

面试官:你怎么优雅写 CSS?_类名_04

面试官:  如果有一个场景, 基于 antd 封装了一个自己公司风格的组件样式库. 怎么确保在 antd 样式后加载? 答: 因为 css-loader 实际上只是会解析生成对应的类名, 最后我们还得根据 style-loader 插入 html 中, 那这里可以控制它插入的顺序. 根据文档的配置信息, 控制 css 的插入顺序. 即可控制先后加载顺序. 

面试官:你怎么优雅写 CSS?_类名_05



借助面试这个场景, 来巩固下知识. 系统地学习下 优雅管理 CSS 的各种方式.  希望对你有帮助~




最后




扫描二维码

关注前端加加

我在这里等你呦~

面试官:你怎么优雅写 CSS?_css_06



- 欢迎关注「前端加加」,认真学前端,做个有专业的技术人...



原创不易,如果觉得有点用,希望可以随手发,拜谢各位老铁。