Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSS 方案演进史 #1

Open
leeword opened this issue Mar 5, 2021 · 0 comments
Open

CSS 方案演进史 #1

leeword opened this issue Mar 5, 2021 · 0 comments
Labels

Comments

@leeword
Copy link
Owner

leeword commented Mar 5, 2021

image

OOCSS

面向对象的 CSS ,独立于应用逻辑书写,鼓励 htmlcss 分离和代码的复用

OOCSS遵循两个原则:

  • 独立的结构和样式
  • 独立的容器和内容

具体实现上可以是拆分为基类和修饰类,将尽可能多的公共属性抽象到基础类,然后将每个变体的样式归类为修饰符类。

<div class="container">
  <div class="row">
    <div class="col-4">
    	<button type="button" class="btn btn-success hidden">Success</button>
    </div>
    <div class="col-8">
    	<button type="button" class="btn btn-primary">Primary</button>
    </div>
  </div>
</div>
优点:
  • css 复用率高,扩展性好;
  • 具备良好的可读性和可维护性;
  • 代码量比较少,天然 Atomic CSS
缺点:
  • 多人协作模式下,class选择器容易冲突,没有解决命名空间的问题
  • 基础类库开发周期时间偏长

SMACSS

通过结构化命名,将类名模组分组,达到可扩展的目的。与OOCSS相比,SMACSS 更像是一套模板指导 CSS 的书写。

<div id="section">
  <div class="l-flex">
    <div class="l-col l-col-4">
    	<button type="button" class="btn-success is-hidden">Success</button>
    </div>
    <div class="l-col l-col-8">
      <!-- 扩展btn样式,创建子模块 -->
    	<button type="button" class="btn-primary">Primary</button>
    </div>
  </div>
</div>
分类:
  • Base:重置元素的基本样式,保证元素在任意浏览器中,视觉样式具有一致性。实现如:reset.css、normalize.css;
  • Layout:布局规则将页面分块,将一个或多个模块组合在一起,命名以 l- 开头;
  • Module:模块是设计中可重用的模块化部分,也是SMACSS里最重要的一部分,不强制以 m- 开头;
  • State:状态规则是描述我们的模块或布局在特定状态下的外观的方式。比如Tab是否选中,命名一般以 is- 开头;
  • Theme:主题规则与状态规则相似,它们描述了模块或布局的外观;

优缺点:同 OOCSS

BEM

Block__Element--Modifier
使用 BlockElementModifier 描述页面结构

  • Block 即为区块,可以独立存在;
  • Element 可以理解为元素,它依附于 Block 存在,与 Block 使用 __连接;
  • Modifier 用于描述 BlockElement 的外观或状态,与他们使用 -- 连接;
<form class="form form--theme-xmas form--simple">
  <input class="form__input" type="text" />
  <input class="form__submit form__submit--disabled" type="submit" />
</form>
优点:
  • 制定了一套易与理解的CSS编码规范;
  • 可读性高,通过class的命名,可以得知元素的结构;
  • 很大程度解决了命名冲突的问题;
缺点:
  • 重新定义 BlockElement 的含义,容易造成混淆;
  • 需要与页面结构并行维护一套CSS 逻辑;
  • 命名过长,产出的 size 偏大;

Shadow DOM

Web components 标准的一部分,将封装的 Showdow DOM 附加到元素并控制其关联的功能。
Shadow DOM 中定义的 CSS 样式只会在 ShadowRoot 下生效,很好的实现了代码的隔离。

// js
let tmp1 = document.createElement('template');
tmp1.innerHTML = `
	<style>
    .btn {
      display: inline-block;
      font-weight: 400;
      line-height: 1.5;
      text-align: center;
      text-decoration: none;
      vertical-align: middle;
      user-select: none;
      border: 1px solid transparent;
      padding: .375rem .75rem;
      font-size: 1rem;
      border-radius: .25rem;
      transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;
    }
    .btn-primary {
      color: #fff;
      background-color: #0d6efd;
      border-color: #0d6efd;
    }
	</style>
	<button type="button" class="btn btn-primary">I'm in shadow dom!</button>
	<slot></slot>
`;

customElements.define('x-button', class extends HTMLElement {
  constructor() {
    super();
    
    let shadowRoot = this.attachShadow({ mode: 'open' });
    shadowRoot.appendChild(tmp1.content.cloneNode(true));
  }
});

// html
<x-button></x-button>

image

优点:
  • 面向未来的原生组件写法
  • 与页面的其他代码天然隔离
  • 可增强现有 HTML 标签,创建可重用的新标签(Custom Element)
缺点:
  • 对平台实现有强依赖,浏览器支持度一般
  • 目前只能使用 link 标签引入外部样式(存在绘制闪烁的问题),其他形式的外部样式(例如全局的CSS重置)无法渗透进 shadowDOM 内部(已有提案解决)

CSS-in-JS

借助 js 语言的灵活性,使用 js 样式化组件,在组件的运行时,将CSS 附加到 DOM 当中。

import React from 'react';
import styled, { css } from 'styled-components';

const Button = styled.button`
	display: inline-block;
  font-weight: 400;
  line-height: 1.5;
  text-align: center;
  text-decoration: none;
  vertical-align: middle;
  user-select: none;
  border: 1px solid transparent;
  padding: .375rem .75rem;
  font-size: 1rem;
  border-radius: .25rem;
  transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;
  ${props => props.primary && css`
    color: #fff;
    background-color: #0d6efd;
    border-color: #0d6efd;
  `}
`

// OR
// A new component based on Button, but with some override styles
const PrimaryButton = styled(Button)`
	color: #fff;
  background-color: #0d6efd;
  border-color: #0d6efd;
`;

export default ShowButton() {
  return (
    <div>
      <Button>Normal</Button>
      <Button primary>Primary</Button>
      <PrimaryButton>Primary</PrimaryButton>
    </div>
  )
}
优点:
  • 很轻松的实现cssjs 变量共享,易于维护;
  • 代码中只存在 javaScript,具有跨平台优势;
  • 不需借助编译工具,即可提取 Critical CSS
缺点:
  • 风格比较激进
  • 有一定学习理解门槛
  • 没有统一的标准约束

CSS modules

利用 webpack 之类的工具,编译阶段将类名加上随机的 hash 值,以回避命名冲突的问题

CSS Houdini

开放css底层api,开发者可通过接口自行扩展css

文章介绍了几种前端发展中出现的css方案,其实在解决的下面提及的几个问题:

  • 作用域(全局 -> 组件)
  • 模块化与代码复用(提高可维护性)
  • CSS Atomic 化(更小的代码尺寸)
  • 提取 Critical CSS(更快的首屏加载体验)
  • 跨平台(Write once,run every where)

方案可能会过时,但其中折射隐含的思想,会以新的形式流传进化,它值得每个前端开发人员深入学习与思考。总而言之,技术没有银弹,实际开发中亦需要不断权衡利弊,明确使用场景,选择合适的方法维护项目。

参考链接:

https://caniuse.com/
http://oocss.org/
http://smacss.com/
https://github.com/Polymer/polymer
https://www.cssinjsplayground.com/
https://styled-components.com/
https://github.com/webpack-contrib/css-loader#modules
https://github.com/WICG/webcomponents/blob/gh-pages/proposals/css-modules-v1-explainer.md
https://developer.mozilla.org/zh-CN/docs/Web/Houdini
https://www.smashingmagazine.com/2016/03/houdini-maybe-the-most-exciting-development-in-css-youve-never-heard-of/

@leeword leeword added the css label Mar 5, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant