前言
又来认识 CSS 新东西了。今日前端早读课文案由 @Zhang Jiqi 分享,公号:vivo 互联网技术授权。
正文从这起始~~
本文重点讲述了 CSS 中的级联层(CSS@layer),讨论了级联以及级联层的创建、嵌套、排序和浏览器支持状况。级联层能够用于避免样式冲突,加强代码可读性和可守护性。 1、什么是级联层 (Cascade Layers)?1.1 级联层的官方定义咱们参看 Cascading and Inheritance Level 5(13 January 2022) 中 6.4 节所述:
级联层供给了一种结构化的方式来组织和平衡单个起源中的问题。单个级联层内的规则级联在一块,不与层外的样式规则交错。
研发者能够创建层来表现元素默认值、第三方库、主题、组件、覆盖和其他样式问题,并且能够以显式方式重新排序层级,而无需更改每一个层内的选取器或特异性,或依赖源次序来处理跨层的冲突。
单纯看官方定义和概括可能比较晦涩,下面咱们会结合案例来讲清楚。 1.2 级联层为认识决什么问题?简而言之:级联层的显现便是为了使 CSS 研发者能够更简单直接地掌控级联。
咱们来假设平常研发中的一个场景,从场景去理解级联层在处理什么问题。
如下图:
咱们原来的 display 文案是红色,当咱们引入了一个第三方组件库,第三方库中有以下样式。 /* 研发者样式 */ .item { color: red; } /* 第三方库 */ #app .item { color: green; border: 5px solid green; font-size: 1.3em; padding: 0.5em; width: 120px; }
就会引起 display 文案变成绿色。
咱们想要将 display 文案的颜色由绿色改成红色通常的手段是增多选取器特异性(优先级)。例如在研发页面中对研发者样式进行修改: /* 研发者样式 */ #app div.item { color: red; } /* 第三方库 */ #app .item { color: green; border: 5px solid green; font-size: 1.3em; padding: 0.5em; width: 120px; }
或借助级联中出场次序对优先级的影响在用户页面中重写 /* 第三方库 */ #app .item { color: green; border: 5px solid green; font-size: 1.3em; padding: 0.5em; width: 120px; } /* 研发者样式 */ #app .item { color: red; }
效果如下:
再举个例子:
例如有可能第三方组件写了 a { color: blue; }
那项目研发中因为引入这个第三方组件 就会引起样式污染,由于第三方库的样式常常都在项目设置的通用样式例如 common.css 后加载。
倘若后面想在代码中覆盖某些属性,运用高特异性选取器的语句就可能会引起问题。而后由于有问题就会选取更高特异性的择器的语句或运用!important,这会使代码变得冗长亦可能会带来副功效。低特异性选取器的语句很容易被后面出此刻代码中的语句覆盖。在自己的代码之后加载第三方 CSS 时尤其会显现这种问题。
因此级联层便是为认识决以上场景显现的,级联层在级联中的的位置是在内联样式和选取器特异性之间。当有些 css 声明便是设置要低优先级且不受选取器特异性影响那样运用级联层再合适不外。
运用级联层处理第1个平常研发场景痛点的 css 代码如下: /* 排序层 */ @layer reset, lib; /* 通用样式 */ @layer reset { #app .item { color: black; width: 100px; padding: 1em; } } /* 第三方库样式 */ /*咱们将第三方库的样式所有放到lib层*/ /*这儿通常运用@import导入的方式*/ /*为了示例简单咱们简化了操作*/ @layer lib { #app .item { color: green; border:5px solid green; font-size: 1.3em; width: 130px; } } /* 研发者样式 */ .item { color: red; }
为了晓得为何上面的 css 代码能处理冲突问题,更好地理解级联层的功效,理解有些现象背面的根因,认识级联层和级联的关系,咱们继续往下看。 2、理解级联层的前提 —— 级联 (cascade)2.1 什么是级联?CSS 中有两个重要的基本规则,一个是继承,一个是级联。
继承
指的是类似 color,font-family,font-size,line-height 等属性父元素设置后,子元素会继承的特性。
级联
能够简单理解为是 CSS 用来处理要应用于元素的详细样式的算法。亦便是基于有些优先级排序输出给给定元素上属性值一个级联值。级联值是级联的结果。 2.2 当前级联的排序标准咱们参看 Cascading and Inheritance Level 5(13 January 2022) 中 6.1 节,
相比于 Cascading and Inheritance Level 4(14 January 2016) 中的定义有显著变化。
最重要的变化便是增多了级联层。由此级联排序变成:
起源和重要性(Origin and Importance)
上下文(Context)
样式属性(Element-Attached Styles)
层(Layers)
特异性(Specificity)
出场次序(又名源代码次序)(Order of Appearance)
浏览器在确定最后元素样式呈现的时候,会依据这些准则根据优先权从高到低排序,并且会一个一个的检测,直到确定最后样式。 2.3 级联起源(Cascading Origins)2.3.1 三个核心起源
css 中每一个样式规则有三个核心起源,它决定了它进入级联的位置,理解起源优先级是理解级联的关键。
用户代理源自(浏览器内置样式)
用户源自(浏览器的用户设置 )
作者源自(Web 研发者)
2.3.2 起源的优先级
Css 声明的起源取决于它来自哪里,重要性在于它是不是用!important 声明。
各样起源的优先级按降序摆列:
过渡
重要的用户代理
重要用户
重要作者
动画
普通作者
普通用户
普通用户代理
越靠前源自的声明优先级越高。过渡和动画咱们能够暂时忽略。 2.4 熟练又陌生的!important一般做为研发者,!important 会被咱们视为一种增多特异性的办法,用以覆盖内联样式或特异性较高的选取器。
然则 !important 设计出来的初衷是做为整体级联中的一个特性,来平衡研发者、用户设置和浏览器内置之间对 css 优先级的影响能力。
默认状况下三者的优先级是:作者源自 > 用户源自 > 用户代理源自(能够参看上文起源优先级中 6-8 的排序)。然则当 css 声明添加 !important 之后会使它们的优先次序颠倒(参看上文起源优先级中 2-4 的排序)。
倘若站在浏览器和用户的方向看 !important 供给了在必要时重获优先级掌控权的能力,而非只是简单的增多特异性。
举个例子:
浏览器默认样式表包括咱们研发者没法覆盖的重要样式。
浏览器对拥有 hidden 类型的 input 输入框设置了默认的展示属性并且将其声明为重要。 input[type=hidden i] { display: none !important; }
看下面两张图例:
第1张能够看出咱们对拥有 hidden 类型的 input 输入框的展示属性设置成为了表示并且声明为重要
第二张是样式最后计算结果:隐匿
从上面的浏览器表现能够看到咱们做为研发者在作者样式表中设置的规则没能覆盖用户代理样式表中的相同规则。
这验证了上面说的:在级联中 !important 会颠倒三大核心起源默认优先次序。
验证的过程中还发掘了一个 chrome 掌控台这边的 bug,看上面的第1张图例:没生效的规则不划删除线,生效的反而划删除线了。
再看一个官方文档的例子加强一下理解:
font-size 的值最后是‘12pt ’。由于作者样式表中添加!important 的规则优先权高于用户样式表中普通规则。
text-indent 的值最后是‘1em’。由于虽然两个样式表都标注了 !important,然则标注 !important 用户声明优先级大于标注 !important 作者声明。 2.5 一张图带你理解级联下图能够帮忙咱们直观的理解级联以及级联层在级联中的位置:
照片源自:css-tricks
咱们会发掘平时操作最多的选取器特异性(selector specificity)只是级联中的一小部分。亦容易地理解了为何内联样式优先级天然高。同期咱们会发掘!important 在级联中有特殊地位。他穿插在级联规则的各个周期并能颠倒优先级。 3、级联层 (CSS@layer) 运用探索3.1 @layer 是什么?咱们来看 MDN 上的定义:
The @layer CSS at-rule is used to declare a cascade layer and can also be used to define the order of precedence in case of multiple cascade layers.
亦便是说 @layer 这个 at-rule(AT 规则) 用于声明级联层(cascade layer),亦能用于定义多个级联层的优先级。
At-rules 是什么?
At-rules 指的是导 CSS 怎样表现的 CSS 语句。它们以 at 符号 @ (U+0040 COMMERCIAL AT) 开头,后跟一个标识符,包含下一个分号 ; ( U+003B SEMICOLON) 或下一个 CSS 块之前的所有内容。
咱们研发平常的 at-rule 有 @charset、@media、@font-face 、@keyframes 等。 3.2 @layer 的句法规则@layer 的句法如下: @layer layer-name {rules} @layer layer-name; @layer layer-name, layer-name, layer-name; @layer {rules}3.3 怎样创建级联层能够经过多种方式创建级联层。
第1种办法是:创建命名的级联层,其中包括该层的 CSS 规则,如下所示: @layer green { .item { color: green; border: 5px solid green; font-size: 1.3em; padding:0.5em; width: 120px; } } @layer special { .item { color: rebeccapurple; } }
第二种办法是:创建一个命名的级联层而不分配任何样式。这能够是单层,如下所示: @layer green;
能够一次定义多个层,如下: @layer green, special一次定义多个层有什么好处呢?
由于声明层的初始次序决定了层的优先级。与声明同样,倘若在多个层中找到声明,最后定义的层声明将最后生效。看下面代码: @layer green,special; @layer green { #app .item { color: green; border: 5px solid green; font-size: 1.3em; padding: 0.5em; width: 120px; } } @layer special { .item { color: rebeccapurple; } }
效果如下图:
special 层中 item 样式规则将被应用即使它的特异性小于 green 层中的规则。这是由于一旦层次序定义完成,就会忽略选取器特异性。
一样亦会忽略显现的次序:
咱们声明层名叫作并设置它们的次序后,能够经过重新声明名叫作来将 CSS 规则添加到图层。而后将样式附加到层,并且层次序不会更改。例如如下代码虽然 @layer green 重新声明了并在文件后方然则因为次序一起始已然设置因此字体颜色还是紫色: @layer green,special; @layer special { .item { color: rebeccapurple; } } @layer green { .item { color: green; border: 5px solid green; font-size: 1.3em; padding: 0.5em; width: 120px; } }
效果如下:
忽略选取器特异性和代码显现次序能够让咱们创建更简单的 CSS 选取器,并使代码优雅,由于不必保证选取器拥有足够高的特异性来覆盖其他 css 规则,只需要保证它出此刻后面的层中。
第三种办法是:创建一个无名叫作的级联层。例如: @layer { .item { color: black; } }
这将创建一个匿名级联层,该层功能与命名层相同。然则运用匿名层有如下缺点:
可读性较差:匿名层无名叫作,会引起样式表很难阅读和理解。尤其是在大型项目中,可能会显现样式持续增多,难以跟踪和管理的问题。
难以扩展:倘若稍后想要更改特定样式或组合,亦会很难找到特定的代码块。
不可复用性:匿名层中的样式不可在其他地区重复运用或引用。这般会使样式表更难以管理和守护。
平时咱们尽可能避免运用匿名层。但当咱们是样式库的作者,并想将某些 css 代码不被运用者修改能够借助匿名层做到这一点。
第四种办法是:运用 @import。CSS 原生支持 @import 导入其他 CSS 文件。 @import url(index.css) layer(index);
同期,亦支持匿名引入,例如: @import url(index.css) layer;
咱们在运用 @import 时候需要放在除 @charset 之外的样式规则前,否则没法导入。
可能的第五种方式仍在讨论中:经过元素上的属性。请参阅 [css-cascade] Provide an attribute for assigning ato a cascade layer #5853。 3.4 层的嵌套规则图层能够嵌套。例如: @layer base { p { max-width: 70ch; } } @layer framework { @layer base { p { margin-block: 0.75em; } } @layertheme { p { color: #222; } } }
生成的层能够暗示为一棵树:
1.base
framework
base
2.theme
或能够用扁平列表暗示
1.base
2.framework.base 3.framework.theme
要将样式附加到嵌套层,您需要运用以下全名来引用它: @layer framework { @layer default { p { margin-block: 0.75em; } } @layer theme { p { color: #222; } } } @layer framework.theme { /* 这些样式会被添加到framework层里面的theme层 */ blockquote { color:rebeccapurple; } }
看效果:
3.5 层的排序规则级联层根据它们声明的次序排序。第1层优先级最低,最后一层优先级最高。然则,未分层的样式拥有最高优先级: /* 未分层 */a { color: green; } @layer layer-1 { a { color: red; } } @layer layer-2 { a { color: orange; } } @layer layer-3 { a { color: yellow; } }
优先级次序如下:
1. 未分层样式
2.layer-3
3.layer-2 4.layer-1
看下图示例:
层能够在一个地区被定义图层(以创立图层次序),而后在任何地区添加样式 /* 定义在一个地区 */ @layer my-layer; /* 其他样式*/
... /* 在某个地区添加样式 */ @layer my-layer { a { color: red; } }3.6 加上 !important 之后的排序规则 /* 未分层 */ a { color: green !important; } @layer layer-1 { a { color: red !important; } } @layer layer-2 { a { color: orange !important; } } @layer layer-3 { a { color: yellow !important; } }
任何加上重要声明的样式都以相反的次序应用
优先级次序如下:
1.!important layer-1
2.!important layer-2
3.!important layer-3 4.!important 未分层样式
看下图示例:
这儿咱们看到对应规则在 chrome 浏览器的表示是正确的。然则在研发者掌控台中的样式一栏规则表示有问题。应该是 chrome 浏览器研发者掌控台的 bug。 3.7 嵌套层的排序规则 @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; } } /* 未嵌套 */ a { color: blue; } } /* 未分层 样式 */ a { color: black; }
优先级次序如下:
1. 未分层 样式
2.layer-3
-layer-3 未嵌套
-layer-3 sub-layer-2
-layer-3 sub-layer-1
3.layer-2 4.layer-1
3.8 媒介查找对层排序的影响以下层次序将取决于匹配的媒介要求:
例如: @media (min-width: 600px) { @layer layout { .item { font-size: x-large; } } } @media (prefers-color-scheme: dark) { @layer theme { .item { color: red; } } }
倘若两个媒介查找的规则中匹配一个那样对应的级联层生效。倘若两者都匹配,那样图层次序将为 layout, theme 都生效。倘若两个都不匹配则不定义层。下图是两者都匹配的场景。
4、此刻就能运用级联层吗?4.1 日前浏览器支持程度照片源自:developer.mozilla.org
日前所有现代浏览器均已然支持 @layer 规则。所有浏览器厂商都支持的特性将来必定比较实用。 4.2 W3C 鼓励能够做为平常运用
CSS 的标准化流程由 W3C Cascading Style Sheets Working Group (CSSWG)——W3C 层叠样式列表小组以及独立 CSS 专家构成。W3C 本身并不制定标准,而是做为一个论坛式的平台,接收来自小构成员的提交,并经过会议来商讨制定标准,所有的提交以及讨论都是公开透明的,能够在 W3C 网站上看到会议的记录,能够简单分为 4 个大周期:
工作草案 (WD)
候选人举荐 (CR)
提议的意见 (PR)
W3C 举荐 (REC)
下图能够帮忙理解:
照片源自:w3.org
W3C 经过状态码表示规范的成熟度。成熟度从低到高排序如下图。
照片源自:w3.org
再看下图:包括 layer 概念的标准讨论已然到达 CR 周期。
照片源自:w3.org
W3C 鼓励从 CR 周期的标准 起始能够做为平常运用。 5、总结最后,咱们回到经过级联层怎样处理 “引入了一个第三方组件库引起样式覆盖 “的问题上。
css 代码如下: /* 排序层 */ @layer reset, lib; /* 通用样式 */ @layer reset { #app .item { color: black; width: 100px; padding: 1em; } } /* 第三方库样式 */ /*咱们将第三方库的样式所有放到lib层,这儿通常运用@import导入的方式,为了示例简单咱们简化了操作*/ @layer lib { #app .item { color: green; border: 5px solid green; font-size: 1.3em; width: 130px; } } /* 研发者样式 */ .item { color: red; }
咱们将第三方库的样式所有放到 lib 层,将需要重置的有些样式放到 reset 层,自己研发的样式不放入层中(当然你亦能够放入到一层而后排序在最后)。由此咱们实现了样式的分层处理了第三方组件库引起样式覆盖的问题,况且做到研发者样式简单不冗长。
效果如下:
级联层(CSS@layer)已然历概念提出到到浏览器全面支持的周期。亦许在不久的将来大众都会广泛运用它,期望本文能给大众带来必定帮忙。 参考资料:CSS Cascading and Inheritance Level 5
A Complete Guide to CSS Cascade Layers
The Future of CSS: Cascade Layers (CSS @layer)
CSS 必学基本:理解 CSS 中的级联规则
详解日后定会大规模运用的 CSS @layer 规则
W3C Process Document
Cascade Layers Explainer
关于本文
作者:@Zhang Jiqi 源自:https://mp.weixin.qq.com/s/4M-RvnTq8rJuKDC3VZOONQ
这期前端早读课 对你有帮忙,帮”
赞
“一下, 期待下一期,帮”
在看” 一下 。
|