CSS基础

47 阅读4分钟

一、cascade layers 指南

cascade layers:级联层,它能一次解决三个痛点:

  • !importent 和各种 选择器特异性(#id > .class > 标签选择器)样式顺序带来的代码臃肿和样式的不可预测。
  • 引入第三方UI库时,比如 element-plus,当我们想要修改elment-plus的某些组件的官方默认样式时,往往不生效或者在浏览器里检查样式琢磨半天。
  • 多人协作时,难以统一管理不同模块的样式优先级。

cascade layers如何做到?

在没有使用cascade layers对css代码管理前,所有的css样式都处于一个平面,谁的样式生效,全看料堆得够不够多,而cascade layers的作用就是对css代码做 不同维度的划分。作用于同一个组件的样式,高维度即高优先级级联层的样式会对低优先级级联层的样式有绝对的覆盖。

@layer style1, style2;

@layer style1 {
  a {
    color: red;
  }
}

@layer style2 {
  a {
    color: blue;
  }
}

这里@layer style1, style2定义了两个层style1和style2,声明层的顺序从左到右优先级越高,可以理解为style1处于一维,style2处于二维,因此style2里的样式如果和style1重复,那么style2会覆盖style1。

因此我们可以利用分层思维来管理css代码,让css样式的可预测性更加明显。

这里有一个优先级反转的点:当在cascade layer里使用!importent时,低优先层的样式加上!importent后,该样式会比高优先层的样式添加上!importent后优先级更高,这样的目的是为了保证低优先层的某些重要样式会生效。

比如我们这有style1, style2, style3三个从左到右定义的cascade layer,在相同样式上添加了importent后的layers优先级关系是(从上到下优先级更低):

  1. !importent style1
  2. !importent style2
  3. !importent style3
  4. style3
  5. styel2
  6. style1

图层顺序

cascade layer 让css的样式处于不同的图层,有过板绘经验的都知道图层的重要性。当同一个区域一个图层给它黄色,另一个图层给它红色,如果黄色的图层在红色图层之上,那么黄色会覆盖掉红色。除非红色使用!importent,低图层添加了!importent后优先级会反转。

@layer layer-1 { a { color: red; } }
@layer layer-2 { a { color: orange; } }
@layer layer-3 { a { color: yellow; } }
/* un-layered */ a { color: green; }

这里图层优先顺序由上到下是:

  1. un-latered
  2. layer-3
  3. layer-2
  4. layer-1

在cascade layer之外的样式优先级更高。

@layer layer-1 { a { color: red !important; } } 
@layer layer-2 { a { color: orange !important; } }
@layer layer-3 { a { color: yellow !important; } } 
/* un-layered */ a { color: green !important; }

这时的图层优先顺序由上到下是:

  1. !important layer-1 (most powerful)
  2. !important layer-2
  3. !important layer-3
  4. !important un-layered styles
  5. normal un-layered styles
  6. normal layer-3
  7. normal layer-2
  8. normal layer-1 (least powerful)

图层树

@layer layer-1 { a { color: red; } } 
@layer layer-2 { a { color: orange; } } 
@layer layer-3 { 
  @layer sub-layer-1 { a { color: yellow; } } 
  @layer sub-layer-2 { a { color: green; } } 
  /* un-nested */ a { color: blue; } 
} 
/* un-layered */ a { color: indigo; }
  1. un-layered styles (most powerful)
  2. layer-3
    1. layer-3 un-nested
    2. layer-3 sub-layer-2
    3. layer-3 sub-layer-1
  3. layer-2
  4. layer-1 (least powerful)

声明cascade layer并添加样式

@layer style1, style2;

@layer style1 {
  * { box-sizing: border-box; }
  img { display: block; }
}

@layer style2 {
  @layer one, tow;
  [hidden] { display: none; }
  
  @layer one {/*styles...*/}
  @layer two {/*styles...*/}
}

@layer style2.three, style2.four;

@layer style.one {/*styles...*/}
@layer style.two {/*styles...*/}
@layer style.three {/*styles...*/}
@layer style.four {/*styles...*/}

@import url('example.css') layer(style1);

cascade layer的使用场景

任何场景下都可使用,最好养成‘添加图层’的习惯。特别是css代码量大,结构复杂时或者是引入了第三方的css样式库比如Bootstrap,将Bootstrap引入低优先级层,方便后续修改。

有一套公式图层集可以非常标准地管理自己地css代码:

@layer reset,
       default,
       themes,
       patterns,
       layouts,
       components,
       utilities;
  • 一些标准化样式写在reset里
  • 一些排版和可读性样式写在default里
  • 明亮和暗黑主题样式写在themes里
  • 可复用和可能出现在多个组件里的样式写在patterns里
  • 布局和结构类样式写在layouts里
  • 单个组件样式写在components里
  • 可覆盖的实用工具类写在utilities里

在此基础上,每个图层内部就可以自行设置子图层方便管理比如components里:

@layer components { 
  @layer defaults, structures, themes, utilities; 
}

这里有一个细节,可以单独将设置为!importent的样式添加到同一个子图层里比如xx.importent。

Vue.js里的疑惑
  1. cascade layer是全局性的,不受scoped约束,在包含scoped的组件内定义的cascade layer可以全局使用,同理,全局定义的cascade layer也可以在每个组件里添加样式。