CSS中最常见的混乱原因之一是在书写风格时面临特殊性。例如,更改某个元素的显示值永远不会起作用,因为级联中的另一个元素由于具有更高的特定性而覆盖它。或者当另一个元素出现时!重要的是,当代码库不断增长,而我们没有以防止(或减少)此类问题的方式组织CSS时,通常会发生这种情况。
为了克服层叠和特殊性问题的困扰,我们需要注意在哪里编写特定的CSS块。在小项目中,这是可以的,但对于大项目来说,这是一项耗时的任务。因此,我们开始看到不同的方法来帮助我们更好地组织CSS,从而减少级联问题。我想到的前三个是边界元法(Block,Element,Modifier),乔纳森·斯努克(Jonathan Snook)的Smacss和哈利·罗伯茨(Harry Roberts)的倒三角形CSS。
在本文中,我们将探索级联层是如何工作的,它们将如何帮助我们更加自信地编写CSS,以及用例和示例。
级联层解决的主要问题是提供一种有保证的方式来编写CSS,而不必担心特定性和源代码顺序。让我们举个例子来说明这个问题。
我们有一个有两种风格的按钮,默认的和幽灵的。在HTML中,我们将如何使用它们:
在这种情况下,上述方法非常有效。但是,如果我们需要第三个按钮的变体,但我们不能在之后立即编写它呢。按钮声明?
这个按钮在后面。按钮——facebook。因此,它将覆盖它。在这种情况下,我们可以通过增加特定性来解决这个问题。点击facebook,比如:
两种解决方案都不是那么好。最好的办法是把它们写在正确的地方,就在后面。按钮声明。如果没有CSS预处理器(比如Sass)的帮助,将CSS文件划分为部分和组件,那么要做到这一点并不容易。
Cascade layers是一个新的CSS特性,它将帮助我们开发人员在为大型项目编写CSS时获得更多控制。根据规范作者Miriam Suzanne的说法:
级联层允许作者管理其内部级联逻辑,而不完全依赖于特定性启发或源顺序。
首先要做的是定义一个图层。为此,我们在图层名后面写@。
我定义了一个叫做组件的层。在该层中,我需要添加默认的按钮样式。
@图层组件{.按钮{颜色:#fff;背景色:#d73a7c;}@图层变化{.button--ghost{背景色:透明;颜色:#474747;边框:2px实心#e0e0;}
下面是图层的可视化。有类似于Photoshop的图层,因为CSS中最后定义的图层将是视觉系统中图层列表的第一个。
在我们的示例中,变体层是最后定义的一层,因此它比组件层具有更高的优先级。
还有另一种方法可以组织哪一层覆盖另一层,即立即定义层。
回到我们的例子。最初的问题是,我们需要创建按钮的另一个变体,但我们将其添加到了一个使变体按钮具有较少特异性的位置。通过级联层,我们可以在变体层中添加CSS。
@层组成、变化@图层组件{.按钮{颜色:#fff;背景色:#d73a7c;}@图层变化{.button--ghost{背景色:透明;颜色:#474747;边框:2px实心#e0;}。按钮--facebook{背景颜色:var(--brand fb);}
这样,我们就可以确保组件的变化总是优先于基本样式。让我们以直观的方式探索上面的解释。
在“层”面板中,请注意每个按钮如何位于一个层中。顺序根据顶部的@layer定义确定。
更改图层顺序时,“组件”图层将覆盖其中一个。因此,默认按钮样式将获胜。
在层叠层中,浏览器将来自相同@layer定义的样式组合在一起,并根据它们的顺序立即读取它们。
@层组成、变化@图层组件{.button{..}@图层变体{.button--ghost{..}/*500行之后*/@layer variations{.button--facebook{..}
浏览器将添加。按钮——facebook就在那之后。按钮——变体层中的幽灵。以下是更清晰的视觉效果:
这是一个新的CSS特性需要考虑的最重要的问题。正如我可以使用的,在撰写本文时,Firefox、Chrome、Safari TP都支持它。
我们可以用它们来增强功能吗?不,我们不能。除非我们使用Javascript polyfill(目前还没有)。
考虑下面的图,线条越粗,级联中样式的优先级越高。
风格规则的起源和重要性是两个不同(但相关)的东西,所以我将在下面逐一解释。
样式规则的来源可以按优先级降序来自以下之一:
这意味着开发人员编写的CSS将始终赢得用户和浏览器样式。
如果用户试图更改浏览器的默认字体大小,上述CSS规则将覆盖用户的首选项(因为开发人员的样式胜过用户的样式)。
这是一个糟糕的可访问性实践。请不要在现实生活中这样做。我添加它只是为了解释风格的起源。
关于浏览器样式,它们适用于用户代理样式表。例如,默认值<;按钮>;不同浏览器的样式不同。我们可以覆盖默认样式,你猜到了,因为开发者的样式胜过浏览器的样式。
如果你检查默认按钮,你会注意到用户代理样式表,它显示了按钮的所有默认样式。
所有这些都是正常的规则。这意味着他们没有!重要的关键词。如果它在那里,那么顺序将是:
如果一个元素具有内联样式,那么它在同等重要性的同级元素中具有最高的特异性。
在下面的示例中,<;按钮>;颜色将为#fff,因为内联样式优先。
哦,你好!这是cascade的新客人。级联层的优先级高于选择器的特殊性。在下面的示例中,您能猜出自定义层中p元素的字体大小吗?
@层底,定制@层基{#页面.散文p{font size:1rem;}@图层自定义{p{font size:2rem;}
字体大小为2rem。在级联层中,无论元素的特殊性如何,如果元素在下一层中被重写,它都将被忽略。
在图层之后,浏览器会查看CSS规则,并根据其选择器特性决定哪一个优于另一个。
下面是一个简单的例子。新闻稿中的按钮比。按钮因此,第一条规则将被覆盖。
最后,外观的顺序起作用。当两个元素具有相同的特性时,它们在CSS文档中的顺序将决定哪一个元素获胜。
上述两条规则具有相同的特殊性。后者获胜是因为它在第一条规则之后。
现在,您已经了解了层在级联中的位置,让我们进入一些用例。
我试着看看当前的项目,看看层叠层将在哪里发光,我想出了以下用法。
对于我正在从事的一个项目来说,使用层叠层对UI进行主题化将是一个完美的解决方案。它解决的问题是,作为一名开发人员,我可以在不改变CSS或以某种方式重新排序的情况下切换主题。
我有不同的层次,最后一个是主题。图层主题可以包含多个图层(是的,层叠图层支持嵌套)。
请注意,在顶部,我定义了@layer custom,默认值。默认主题将覆盖自定义主题。
@层基础、元素、对象、组件、页面、主题@图层主题{@layer custom,default;@layer default{:root{--color primary:#1877f2;}@图层自定义{:根{--主颜色:#d73a7c;}}
如果你想切换主题,你可以在@layer themes中重新排列第一个定义中的层。
@层基础、元素、对象、组件、页面、主题@图层主题{/*自定义处于活动状态*/@layer default,自定义;@layer default{:根{--color primary:#1877f2;}@图层自定义{:根{--主颜色:#d73a7c;}}
.flickity页面点{底部:20px!重要;}。flickity页面点。dot{背景:#fff!重要;不透明度:0.35!重要;}。flickity页面点。点已选中{不透明度:1!重要;}
通过级联层,我们可以在组件层之前添加第三方CSS。我们可以导入一个外部CSS文件并将其分配给一个层。
@层基础、供应商、组件@图层基础{/*基础样式*/}/*导入。css文件,并将其分配到一个层*/@import url(flickity.css)层(供应商)@图层组件{.flickity页面点{bottom:20px;}。dot{背景:#fff;不透明度:0.35;}。点已选中{opacity:1;}
假设我们有一个列表组件,我们需要一个列表边距较小的变体。
由于:not伪选择器为元素提供了更多的特殊性,因此在不重用:not的情况下无法重写该元素。考虑以下事项:
/*这个赢了*/。列表项:not(:last child){margin bottom:2rem;outline:solid 1px#222;}。列表项--压缩{margin bottom:1rem;}
这个list__项——compact不会覆盖。列出__项,因为后者由于使用:not而具有更高的特异性。为了让它发挥作用,我们需要做以下几点:
考虑下面的层,其中@层列表包含基础层和覆盖层。在overrides中,我编写了variation类,由于overrides是最后一层,所以它按预期工作。
@图层列表{@layer base,overrides;@layer base{.list__项:not(:last child){margin bottom:2rem;}@图层覆盖{.list__item--compact{margin bottom:1rem;}}
在这个例子中,我们有一个主要社交提要项的操作列表(比如评论),每个评论都有一个列表。
提要项中的图标大小为24px。在注释组件中,大小较小。
@层饲料,评论@层馈送{.feed item.c图标{宽度:24px;高度:24px;}@图层注释{.comment__图标{宽度:18px;高度:18px;}
注意。饲料项目。c-icon比c-icon更具特异性。注释图标,但这就是使用层叠层的好处!
我们已经习惯了添加!重要的是实用CSS类,以确保它们始终应用于元素。通过级联层,我们可以将实用程序放置在去年。
考虑下面的例子。我们有一个带有实用程序类p-0的页眉。我们要将填充重置为0。
@层库、供应商、组件、UTIL@层组件{@layer-page-header{.c-page-header{padding:1rem 2rem;}}}@层utils{.px-0{左填充:0;右填充:0;}
如果有CSS样式没有指定给一个层,那么我们将被添加到一个隐式的最终层。
.按钮{边框:2px实心浅灰色;}@基层、构件@图层基础{/*基础样式*/}@layer components{.button{border:0;}
在本例中。按钮规则的定义没有@层,但对于浏览器,这将把规则放在隐式层中。
@基层、构件@图层基础{/*基础样式*/}@layer components{.button{border:0;}}/*隐式层*/@layer{.button{border:2px solid lightgrey;}
层叠层是一个令人兴奋的CSS特性,正如您在示例中看到的,它非常有用。对我来说,唯一的限制是,我们不能将其单独用作CSS的增强功能。这可能会降低网络社区中层的采用速度。