zoukankan      html  css  js  c++  java
  • CSS方法论完全总结

           软件开发领域所有的工程问题,归根结底衍生自一个问题:代码量大了怎么办?

           对于 CSS 而言,因代码量增大导致的核心问题是命名冲突。

           解决命名冲突的方法论是模块化,围绕此方法论,演化出种种模块化方案。

    一、命名的模块化

           基本思路是确保全局空间下一级域名不冲突,那么子域名就被限定在了独立的局部作用域中,从而保证命名的唯一性。

           根据域名的划分方式,出现了不同的命名方案:

       BEM:Block-Element-Modifier,比较笼统,没有过多限制规定

       SUIT CSS

       1、将命名对象划分为组件(component)和功能(Utility)。组件直接命名,功能额外加前缀,比如专门给js调用的类名可加上js前缀:js-button

       2、规定了连字符的用法。普通隔断用单个连字符,描述性词汇用两个连字符:

       .nav-button { }

       .nav-button--primary { }

       沿着这个思路,其实还可以把下划线引进来,用来设置其它规则。

       3、状态切换用is-state型的相邻类名(adjoining class)

       .button { }

       .button.is-clicked { }

       <button class=”button is-clicked”></button>

       OOCSS

       简单的说就是抽象公共类,把复用度高的样式抽取出来,例如:

       .mt20 { margin-top: 20px }

       .tc { text-align: center }

       .abs { position: absolute }

       .clearfix:after { content: ‘’; display: block; clear: both; height: 0 }

       这种方案的思路是通过提高复用性,减少命名的需要,因为有的样式直接用公共类名就能实现,不需要额外命名。

       它的缺点是滥用就可能付出代价,比如有10个组件用同一个普通类名,那么修改样式只需要改一处CSS即可,但是在10个组件上用同一个公共类名比如mt20,意味着把mt20改成mt15,你需要改10处的class。所以公共样式少用公共类,不要图省事儿。

             案例:https://github.com/tailwindcss/tailwindcss

       SMACSS

       针对数量庞大的类名,SMACSS 提出了一个分类的方案:

       1、Base:基础的样式规则

       2、Layout:用于布局的样式规则

       3、Module:可复用的模块样式规则

       4、State:状态样式

       5、Theme:UI样式

       针对不同分类,可以使用不同的前缀来划分命名空间,就不多赘述了。

       ITCSS

       此方案更像是 CSS 整体架构方案,与 SMACSS 横向分类不同,它综合了以上各种方法,提出了一个纵向分层模型:

       1、Settings:简单的说就是在SCSS中预设好变量

       2、Tools:简单的说就是在SCSS中预设好mixins和functions

       3、Generic:简单的说就是reset.css或normalize.css

       4、Elements:对元素的基本格式化,如h1 { font-size: 20px }

       5、Objects:使用OOCSS抽象公共类

       6、Components:UI组件的样式

       7、Trumps:辅助性、功能性的特殊样式,例如动画

     

    二、CSS in JS

           在大型项目中通过命名来避免冲突,是一件颇费脑力的事情,既需要记住所有规则,还需要判断你的命名是否符合规则。更深刻的问题是,这似乎不像是程序员解决问题的方式,命名这样的低级劳动也值得如此费劲?

       于是 React 提出了 CSS in JS 的思路,React 是这样考虑的:在 JS 以及所有程序语言的最佳实践里,都会避免使用全局变量,而在 CSS 里,不管用什么命名方式,满屏幕都是全局变量,怎样才能避免使用全局变量呢?办法是采用内联样式,根本不用 CSS 选择器。

       var styles = {

         button: { ‘50px’, height: ‘30px’ , backgroundColor: ‘#ff4444’}

       }

       <div style = { styles.button }>

       我们不能简单的用“开历史倒车”这样的论调来判断一种技术方案,而应结合应用场景,在成本和收益上权衡。具体的说就是这种方案所解决的问题与其带来的问题相比,是否更划算。

       来源:https://speakerdeck.com/vjeux/react-css-in-js

           大型 CSS 存在的问题有:

           1、全局的命名空间容易污染、冲突

           2、依赖管理复杂

           3、无用代码难以清除

           4、长命名导致代码体积无法进一步压缩

           5、不利于和 JS 共享常量

           6、不确定的解析结果(CSS 中存在层叠,如果层叠系数高的代码加载更慢,会导致最终解析的样式发生突变)

       7、不能解耦(改一处 CSS,所有使用该 CSS 的 UI 样式都会受影响)

       用JS + inline style 解决了上述所有问题,当然也带来了其它副作用,比如难以调试、不能用 CSS 预处理器、不能实现 Media Query 和伪元素等,而且如果你不用 React……

     

    三、CSS Module

      CSS Module 可以看做是 CSS in JS 思路的另一条路线,就是使用JS编译原生的CSS文件,使其具备模块化的能力。

      CSS Module 根据 CSS 文件划分模块,模块内部的类名都会使用哈希算法编译成独一无二的名称,因此不会出现模块之间命名冲突的问题。

      当然,必须使用构建工具如 webpack,才能使用 CSS Module 提供的功能。

       CSS Module 要求每个元素只能携带一个类名,不能用多个类名,那么要使用组合样式怎么办?解决方案是在 CSS 中使用 component,这个其实在预处理器中已经有类似的实现:

       .common { }

       .normal {

         composes: common  // 继承common所有的样式

       }

       composes不仅可以引用本文件的类名,还可以引用其它文件的类名:

       .normal {

         composes: common;

         composes: primary from "../shared/colors.css";

       }

       另外,使用:global(.className)语法可以定义全局类名,结合 PostCSS 可以使用变量,具体请参见阮一峰的教程:

       http://www.ruanyifeng.com/blog/2016/06/css_modules.html

    四、PostCSS

       PostCSS是近年来非常热门的一种编译工具,Vue 官方提供的脚手架 Vue-cli 默认采用的 CSS 处理工具就是 PostCSS。PostCSS 和预处理器 Less、Sass 不同,预处理器仅仅是提供了一套语法糖,而 PostCSS 是一个全面的处理工具,通过丰富的插件,可以实现用于处理 CSS 的几乎所有的功能:类名编译、auto-prefixer、压缩、预处理器功能、属性简写……

           PostCSS并不是唯一,前端界历来奉行的宗旨是“生命不息,折腾不止”,关于CSS in JS的方案,大家感受一下:

    五、Atomic CSS

       代码量与复用性呈反比例关系,因此写 CSS 有两个极端:一是单独为每个元素写一份样式,完全不复用,这样每个元素只需要一个 class,而 CSS 代码是最多的;二是把每一条样式单独写在一个 class 中,确保整个样式表没有一条重复的样式,这样复用性是最高的,代码也最少,但是每个元素就需要一堆的 class。

       通常我们会在两个极端中取折中方案,确保适度的复用性和适度的代码规模,如何把握这个“度”,正是体现方案优劣和架构功力的地方。然而 Atomic 选择了走第二种极端的方式,即使用原子化的样式,最小化 CSS 代码,并且 Atomic 解决命名冲突的方式也非常激进:你完全不用考虑命名,因为根本不需要命名。

       <div class="Bgc(#ccc) C(#fff) P(20px) W(100px)">

       编译出的 CSS 是这样的:

       .Bgc(#ccc) {background-color: #ccc}

       .C(#fff) {color: #fff}

       .P(20px) {padding: 20px}

           .W(100px) { 100px}

           这种思路可谓另辟蹊径,独树一帜。当然优缺点都很明显:CSS 代码最小化了,而 HTML 膨胀了;虽然不用考虑命名,但是要记一堆新规则。

    六、小结

           命名方案很适合中小型项目。在大型项目中,命名方案仍然具有指导作用,但是仅凭命名方案是不够的。

       新的思路有两种:一是抛弃 CSS,二是补强 CSS 的能力。

       React 采用的是第一种思路,能用 JS 解决的都用 JS 解决。

       第二种思路大多采用编译工具。虽然编译的方案各不相同,但是要解决的核心问题是一致的,就是命名冲突。最直接的策略是将名称编译为独一无二的名称,CSS module 和 PostCSS 都采取该策略。Atomic 提出了一种新颖的思路,即将样式表彻底原子化,类名与样式规则一一映射,直接使用类名编写样式,完全消灭了命名的需要。

       每一种方案都各有所长,也各有所短。从来没有最好的方案,只有最不坏的方案。如果一种方案在特定场景、特定约束条件下找不到更好的替代,那么无论它的缺点有多么明显,都可以认为是“最优”方案。

    补充(20170219)

       上述种种方案都基于同一个前提:CSS 本身没有作用域。如果有了呢?事实上 CSS4 已经加入了作用域的设计:

       感觉棒棒哒!

  • 相关阅读:
    java处理jqueryGantt甘特图数据的task.depends依赖规则方法
    中国行政区划表,包括34个省、直辖市的所有数据 mysql数据
    使用mybatis的resultMap进行复杂查询
    intel 酷睿core系列cpu的类型:U M H HQ MQ
    mybatis问题。foreach循环遍历数组报错情况,及其解决方法
    Android开发 DownloadManager详解
    Android开发 WorkManager详解
    Android开发 在不使用ItemTouchHelper的情况下实现ItemView的左右滑动
    AndroidStudio ViewBinding详解
    Android开发 滚轮View第三方框架
  • 原文地址:https://www.cnblogs.com/kidney/p/6197037.html
Copyright © 2011-2022 走看看