css框架/方案

226 阅读4分钟

一、背景

css是前端人员的一种必备的技能,原生css不像编程语言一样可以通过复用等方式,往往会出现编写很多重复代码,以及选择器类名等是全局通用的,当所需要开发的项目比较小时,在类名的命名上可能是没有什么影响,但是当开发的项目有了一定的范围之后,将会遇上命名困难,样式冲突等问题,以及在css的维护上将会极其困难,可以说css代码像一座山一样,越堆越多。 为了解决这些困难,前端领域出现了一些各种各样的框架和方案。

二、关于css问题的框架和解决方案

目前列出的有如下解决方案: BEM、css module、css in js、Atomic css

三、关于以上四种css解决方案的讲解概括

1、BEM

BEM就是三个单词的缩写:Block(模块)、Element(元素)、Modifier(修饰符)
好的css取名规则可以让代码更容易阅读和维护
Block一个独立的实体,代表了更高级别的组件(block);
Element元素,抽象的说,就是block的后代,也就是子模块,用于形成一个完整的block整体(block__element);
Modife修饰符,block与element上的标志,用于来表示形容他们的属性、状态、行为等等(block--modifer)。
  命名方式 .模块名__元素名--修饰器名

优势: a、识别度高、结构清晰,element 和 modifier 与 block 之间的从属关系,可以从名称上就一目了然的区分
      b、隔离性好,每一个区块之间都有是一个独立的空间,减少与其他元素的污染。
      c、良好的扩展性,因为modifier修饰符的存在,我们需要去添加别的样式的时候,只需要创建一个新的修饰符就行,例如 .btn-active, .btn-hidden

2、css module

CSS Modules 允许我们像 import 一个 JS Module 一样去 import 一个 CSS Module。每一个 CSS 文件都是一个独立的模块
CSS Module只是加入了局部作用域和模块依赖,可以保证某个组件的样式,不会影响到其他组件。

随着项目的越来越大,越来越难以维护,就容易导致命名的混乱。
css module可以保证我们类名的唯一性,解决css 全局污染、层次结构不清晰、代码难以复用等问题。
CSS Modules 在打包时会自动将 idclass 混淆成全局唯一的 hash 值,从而避免发生命名冲突问题。
CSS Modules 特性:
  • 作用域:模块中的名称默认都属于本地作用域,定义在 :local 中的名称也属于本地作用域,定义在 :global 中的名称属于全局作用域,全局名称不会被编译成哈希字符串。
  • 命名:对于本地类名称,CSS Modules 建议使用 camelCase 方式来命名,这样会使 JS 文件更干净,即 styles.className。 但是你仍然可以固执己见地使用 styles['class-name'],允许但不提倡。
  • 组合:使用 composes 属性来继承另一个选择器的样式,这与 Sass 的 @extend 规则类似。
  • 变量:使用 @value 来定义变量,不过需要安装 PostCSS 和 postcss-modules-values 插件。
    /* style.css */ 
    :global(.card) { padding: 20px; } 
    .article { background-color: #fff; }
    .title { font-size: 18px; }
// App.js 
import React from 'react' 
import styles from './style.css' 
export default function App() { 
    return ( <article className={styles.article}> 
        <h2 className={styles.title}>Hello World</h2> 
        <div className="card">Lorem ipsum dolor sit amet.</div> 
       </article> ) 
 }
<style> 
    .card { padding: 20px; } 
    .style__article--ht21N { background-color: #fff; } 
    .style__title--3JCJR { font-size: 18px; } 
 </style> 
 <article class="style__article--ht21N">
     <h2 class="style__title--3JCJR">Hello World</h2> 
     <div class="card">
         test
     </div> 
 </article>

css module的使用方式

//在 webpack 中使用 CSS Modules(开启 [css-loader] 的 modules 特性)

// webpack.config.js -> module.rules 
{
    test: /\.(c|sa|sc)ss$/i, 
    exclude: /node_modules/, 
    use: [ 
        'style-loader', 
        { 
            loader: 'css-loader',
            options: { 
                importLoaders: 2, // 开启 CSS Modules 
                modules: true, // 借助 CSS Modules,可以很方便地自动生成 BEM 风格的命名
                localIdentName: '[path][name]__[local]--[hash:base64:5]',
               }, 
         }, 
         'postcss-loader', 
         'sass-loader', 
       ],
  },
// 在 PostCSS 中使用 CSS Modules,需要泳道postcss-modules的插件

// postcss.config.js 
module.exports = { 
    plugins: { 
        'postcss-modules': { 
            generateScopedName: '[path][name]__[local]--[hash:base64:5]', 
         }, 
     }, 
 }

、css in js

以前我们编写前端页面的方式一般都是一个文件写js代码加dom结构,一个文件写css,在js文件里引入css代码的文件,
css in js 的方式让我们可以实现在一个文件里,既包含了js代码,又包含了Dom, 还包含了css.

传统的方式 js + dom
css in js 的方式 js + dom + css
    // styles.js 
    import styled, { css } from 'styled-components'
    
    // 创建一个名为 Container 的样式组件 (一个 section 标签, 并带有一些样式) 
    export const Container = styled.section` 
            padding: 10px;
            width: 100%;
            height: 100vh;
            background: #000;
        `
    //按照常规去使用该组件
    export Index = () => {
        return <Container><Container/>
    }

    列举一些流行的css in js 库
    styled-components 是目前最流行的 CSS-in-JS 库,
    emotion
    Styled System
    styled-jsx
    JSS

4、Atomic css

Atomic 意思是原子的意思
Atomic CSS是CSS架构的一种方法, 它的好处是写出基于视觉功能的小的, 单用途CSS类.

使用Atomic CSS, 为每个可重用的属性创建单独的CSS类.
例如, margin-top: 1px; 
就可以创建一个类似于mt-1的CSS类, 或者width: 200px; 对应的CSS类为w-200.
目前使用到的一个类似于该方案的css框架 ,tailwind。

优点:使用这种方式可以最大程度地减少CSS代码数量

缺点:css类名没有语义化,使开发人员无法通过class类名看懂该css功能作用