- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
作者:vivo 互联网前端团队 - Zhang Jiqi 。
本文主要讲述了CSS中的级联层(CSS@layer),讨论了级联以及级联层的创建、嵌套、排序和浏览器支持情况。级联层可以用于避免样式冲突,提高代码可读性和可维护性.
我们参看 Cascading and Inheritance Level 5(13 January 2022) 中6.4节所述:
级联层提供了一种结构化的方式来组织和平衡单个起源中的问题。单个级联层内的规则级联在一起,不与层外的样式规则交错.
开发者可以创建层来表现元素默认值、第三方库、主题、组件、覆盖和其他样式问题,并且能够以显式方式重新排序层级,而无需更改每个层内的选择器或特异性,或依赖源顺序来解决跨层的冲突.
单纯看官方定义和概括可能比较晦涩,下面我们会结合案例来说清楚.
简而言之: 级联层的出现就是为了使 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声明就是设置要低优先级且不受选择器特异性影响那么使用级联层再合适不过.
运用级联层解决第一个日常开发场景痛点的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代码能解决冲突问题,更好地理解级联层的作用,理解一些现象背后的根因,了解级联层和级联的关系,我们继续往下看.
CSS中有两个重要的基础规则,一个是继承,一个是级联.
继承 。
指的是类似 color,font-family,font-size,line-height 等属性父元素设置后,子元素会继承的特性.
级联 。
可以简单理解为是CSS 用来解决要应用于元素的具体样式的算法。也就是基于一些优先级排序输出给给定元素上属性值一个级联值。级联值是级联的结果.
我们参看 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) 。
浏览器在确定最终元素样式呈现的时候,会依据这些准则按照优先权从高到低排序,并且会一个一个的检查,直到确定最终样式.
css中每个样式规则有三个核心起源,它决定了它进入级联的位置,理解起源优先级是理解级联的关键.
用户代理来源(浏览器内置样式) 。
用户来源(浏览器的用户设置 ) 。
作者来源(Web开发者) 。
Css声明的 起源 取决于它来自哪里, 重要性 在于它是否用!important声明.
各种起源的优先级按降序排列:
过渡 。
重要的用户代理 。
重要用户 。
重要作者 。
动画 。
普通作者 。
普通用户 。
普通用户代理 。
越靠前来源的声明优先级越高。过渡和动画我们可以暂时忽略.
通常作为开发者,!important会被我们视为一种增加特异性的方法,用以覆盖内联样式或特异性较高的选择器.
但是!important设计出来的初衷是作为整体级联中的一个特性,来平衡开发者、用户设置和浏览器内置之间对css优先级的影响能力.
默认情况下三者的优先级是: 作者来源> 用户来源>用户代理来源 (可以参看上文起源优先级中6-8的排序)。但是当css声明添加!important之后会使它们的优先顺序颠倒(参看上文起源优先级中2-4的排序).
如果站在浏览器和用户的角度看!important提供了在必要时重获优先级控制权的能力,而非只是简单的增加特异性.
举个例子:
浏览器默认样式表包含我们开发者无法覆盖的重要样式.
浏览器对具有'hidden'类型的input输入框设置了默认的展示属性并且将其声明为重要.
input[type=hidden i] { display: none !important; }
看下面两张图例:
第一张可以看出我们对具有'hidden'类型的input输入框的展示属性设置成了显示并且声明为重要 。
。
第二张是样式最终计算结果:隐藏 。
从上面的浏览器表现可以看到我们作为开发者在作者样式表中设置的规则没能覆盖用户代理样式表中的相同规则.
这验证了上面说的: 在级联中!important会颠倒三大核心起源默认优先顺序 .
验证的过程中还发现了一个chrome控制台这边的bug,看上面的第一张图例:没生效的规则不划删除线,生效的反而划删除线了.
再看一个官方文档的例子加强一下理解:
图片来源:w3.org 。
。
font-size的值最终是‘12pt ’ .
因为作者样式表中添加!important的规则优先权高于用户样式表中普通规则.
text-indent的值最终是‘1em’ .
因为虽然两个样式表都标注了!important,但是标注!important用户声明优先级大于标注!important作者声明.
下图可以帮助我们直观的理解级联以及级联层在级联中的位置:
图片来源: css-tricks 。
我们会发现平时操作最多的选择器特异性(selector specificity)只是级联中的一小部分。也轻松地理解了为什么内联样式优先级天然高。同时我们会发现!important在级联中有特殊地位。他穿插在级联规则的各个阶段并能颠倒优先级.
我们来看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 等.
@layer的句法如下:
@layer layer-name {rules}
@layer layer-name;
@layer layer-name, layer-name, layer-name;
@layer {rules}
可以通过多种方式创建级联层.
第一种方法是 :创建命名的级联层,其中包含该层的 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 .
图层可以嵌套。例如:
@layer base {
p { max-width: 70ch; }
}
@layer framework {
@layer base {
p { margin-block: 0.75em; }
}
@layer theme {
p { color: #222; }
}
}
生成的层可以表示为一棵树:
1.base 。
framework 。
base 。
2.theme 。
或可以用扁平列表表示 。
base 。
framework.base 。
framework.theme 。
要将样式附加到嵌套层,您需要使用以下全名来引用它:
@layer framework {
@layer default {
p { margin-block: 0.75em; }
}
@layer theme {
p { color: #222; }
}
}
@layer framework.theme {
/* 这些样式会被添加到framework层里面的theme层 */
blockquote { color: rebeccapurple; }
}
看效果:
级联层按照它们声明的顺序排序。第一层优先级最低,最后一层优先级最高。但是, 未分层的样式具有最高优先级:
/* 未分层 */a { color: green; }
@layer layer-1 { a { color: red; } }
@layer layer-2 { a { color: orange; } }
@layer layer-3 { a { color: yellow; } }
优先级顺序如下:
未分层样式 。
layer-3 。
layer-2 。
layer-1 。
看下图示例:
层可以在一个地方被定义图层(以建立图层顺序),然后在任何地方添加样式 。
/* 定义在一个地方 */
@layer my-layer;
/* 其他样式*/
...
/* 在某个地方添加样式 */
@layer my-layer { a { color: red; } }
/* 未分层 */ 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; } }
任何加上重要声明的样式都以相反的顺序应用 。
优先级顺序如下:
!important layer-1 。
!important layer-2 。
!important layer-3 。
!important 未分层样式 。
看下图示例:
这里我们看到对应规则在chrome浏览器的显示是正确的。但是在开发者控制台中的样式一栏规则显示有问题。应该是chrome浏览器开发者控制台的bug.
@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; }
优先级顺序如下:
未分层 样式 。
layer-3 。
-layer-3 未嵌套 。
-layer-3 sub-layer-2 。
-layer-3 sub-layer-1 。
layer-2 。
layer-1 。
以下 层顺序将取决于匹配的媒体条件 :
例如:
@media (min-width: 600px) {
@layer layout {
.item {
font-size: x-large;
}
}
}
@media (prefers-color-scheme: dark) {
@layer theme {
.item {
color: red;
}
}
}
如果两个媒体查询的规则中匹配一个那么对应的级联层生效。如果两者都匹配,那么图层顺序将为layout, theme都生效。如果两个都不匹配则不定义层。下图是两者都匹配的场景.
。
图片来源: developer.mozilla.org 。
目前所有现代浏览器均已经支持 @layer 规则。所有浏览器厂商都支持的特性未来一定比较实用.
SS 的标准化流程由 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阶段的标准 开始可以作为日常使用.
最后,我们回到通过级联层如何解决“引入了一个第三方组件库导致样式覆盖“的问题上.
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 。
最后此篇关于前端开发如何更好的避免样式冲突?级联层(CSS@layer)的文章就讲到这里了,如果你想了解更多关于前端开发如何更好的避免样式冲突?级联层(CSS@layer)的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
1. HTML 结构 1.1 HTML 文件基本结构 第一个html程序 hello world! html 标签是整个 h
文件上传三种方案:1. form表单上传,2. iframe,3. FormData,base64上传文件,二进制流上传文件,二进制流下载文件。异步上传,大文件上传--切片:拆分上传请求断点续传显示上
1. HTML 结构 1.1 HTML 文件基本结构 第一个html程序 hello world! html 标签是整个 h
uniapp作为开发移动端的前端框架,目前国内是非常流行的,使用HbuilderX开发工具基于uniapp框架开发的系统可以方便的转换为小程序、APP等移动端程序,大大降低了移动开发的成本。网络
今天我们来复盘一下前端中css伪元素的知识以及如何用css伪元素来减轻javascript的压力,做出一些脑洞大开的图形。 预备知识 伪元素 伪元素是一个附加至选择器末的
今天给大家分享一些实用的JS代码片段,有需要的朋友欢迎收藏! 1、获取浏览器的版 functiongetBrowser(){ varUserAgent=navigator.us
1 . Wappalyzer 全球用户数:1,000,000+ Wappalyzer可以帮助我们了解目标网站的构建方式。工作当中存在大量此类情况,客户需要我们参照某些网站
在管理后台中我们会使用大量的表格表单组件, 导入导出各种报表, 有些场景还需要对报表数据进行可视化分析, 动态生成可视化图表, 笔者将基于以上场景, 总结一些实用的 Table 组件开发技巧,
3D动画效果现在越来越普及,已经被广泛的应用到了各个平台,比如阿里云,华为云,webpack官网等。它可以更接近于真实的展示我们的产品和介绍,带来极强的视觉冲击感。所以说,为了让自己更加优秀,c
QShop商城-快速开始-前端 工具准备 NodeJs 前端环境为NodeJs,下载地址:http://nodejs.cn/download/current/ 。 默认会用版
1. 初始JavaScript 1.1 什么是 JavaScript JavaScript (简称 JS) 是世界上最流行的编程语言之一 是一个脚本语言, 通过解释器运行 主要在客户端(浏览器)上运行
1. WebAPI 背景知识 1.1 什么是 WebAPI JS 分成三个大的部分: ECMAScript: 基础语法部分 DOM API: 操作页面结构 BOM API: 操作浏览器 WebAPI
1. WebAPI 背景知识 1.1 什么是 WebAPI JS 分成三个大的部分: ECMAScript: 基础语法部分 DOM API: 操作页面结构 BOM API: 操作浏览器 WebAPI
1. 初始JavaScript 1.1 什么是 JavaScript JavaScript (简称 JS) 是世界上最流行的编程语言之一 是一个脚本语言, 通过解释器运行 主要在客户端(浏览器)上运行
有没有办法从页面访问 tomcat 服务器日志?如果有一些方法或实现可以做到这一点...... 最佳答案 PSI Probe可以列出您的 Tomcat 日志文件并显示它们的内容。您可以采用相同的方法,
我想知道是否有一些很好的免费网站性能分析工具,特别是前端。这主要是关于Javascript的。 现有工具(例如 Google Pagespeed)的问题在于它不适用于我的应用程序。在进入我的应用程序之
我曾经遇到一个 MySQL 前端应用程序,它在父行中显示外部链接行,例如,如果 Client 表有一个指向 Suburb 表的外键: (来源:vb123.com) 您知道可以执行此操作的任何前端吗?
我正在建立一个带有管理区域的网上商店来管理产品。在管理区域中,所有产品都是可见的,但在网上商店中,只有数据库表中标记为 active = 1 的产品是可见的。 我正在使用 Silex 并将存储库注册为
有可能在 C# 中制作 GUI,但在 C 或 C++ 中制作实际程序。 比如说我想制作一个聊天应用程序。我希望界面在 C# 中。但我想用 C 编写所有实际代码。这可能吗? 我找到了 http://ww
对于我自己的教育,我很好奇编译器使用哪个 C++ 前端和后端。您能告诉我以下技术在哪里使用以及它们有哪些标志/优势(如果有的话)? Open64 - 它是后端、前端还是两者兼而有之?哪些编译器使用它?
我是一名优秀的程序员,十分优秀!