这篇文章发布于 2024年03月31日,星期日,20:06,归类于 CSS相关。 阅读 6163 次, 今日 6 次 9 条评论
by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=11144 鑫空间-鑫生活
本文欢迎分享与聚合,全文转载就不必了,尊重版权,圈子就这么大,若急用可以联系授权。
一、居然还有个CSS嵌套
年前有介绍CSS @scope规则,可以实现CSS的选择器内外嵌套,简化选择器的书写:
@scope(nav) { ul { list-style: none; padding: 0;margin: 0; } li { display: inline-block; } a { display: block; padding: 6px 12px; text-decoration: none; background: skyblue; } }
最近发现,几乎同一时间,现代浏览器还支持了专门用来嵌套书写的CSS Nesting语法,借鉴自Sass/Less/Stylus等预编译语言。
使用示意:
nav { ul { list-style: none; padding: 0; margin: 0; } li { display: inline-block; } a { display: block; padding: 6px 12px; text-decoration: none; background: skyblue; } }
可以看到和@scope(nav)的语法极为相似,所实现的效果也是一样的,假设有如下所示的HTML代码:
<nav> <ul> <li><a href="">链接1</a></li> <li><a href="">链接2</a></li> <li><a href="">链接3</a></li> </ul> </nav> <p><a>我呢?</a></p>
可以看到,nav元素内的链接有背景色等样式,外部的a元素则依然是默认样式。
并且两种写法的选择器的优先级也是一样的。
以a元素为说明对象,两种写法的选择器优先级均等同于 nav a
。
这就让我陷入了深深的沉思……为什么要弄两套规则如此相似的东西呢?
二、@scope和Nesting的不同
在我看来,CSS Nesting就是纯粹的语法糖,也就是就是纯粹的语法上的变化,本身并不具备任何新的特性。
@scope则不一样,@scope规则中想要生效的选择器,一定属于@scope的子元素,带有“局部上下文”的性质在里面。
我们可以通过一个例子感受下两者的不同。
假设有两个无需列表<ul>
元素:
<ul> <li>列表1</li> <li>列表2</li> <li>列表3</li> </ul> <ul> <li>列表2-1</li> <li>列表2-2</li> <li>列表2-3</li> </ul>
那么,@scope规则中使用:scope伪类(表示ul元素自身)和兄弟选择器,是无法匹配后面的ul元素的。
@scope(ul) { :scope + ul { color: red; font-weight: bold; } }
此时,所有的列表文字样式都是默认状态,如下图所示:
但若是换成CSS嵌套写法(使用&
符号表示祖先选择器):
ul { & + ul { color: red; font-weight: bold; } }
则可以看到后面一个<ul>
列表的文字均是红色加粗:
由于CSS Nesting语法中的&
符号就是纯粹的选择器替代,因此,上面的CSS写作这样效果也是一样的:
ul { & + & { color: red; font-weight: bold; } }
区别2:完整CSS规则和随意嵌套
如果使用@scope语法,那么,规则中的每一行代码,都应该属于一个完整的规则,而不能是某一条单独的CSS声明。
例如,下面的写法会让整段CSS规则无效:
@scope(ul) { border: 1px solid; li { color: red; font-weight: bold; } }
但是CSS原生的嵌套语法都没有此顾虑,直接上:
ul { border: 1px solid; li { color: red; } }
可以得到如下截图所示效果,列表有边框,文字是红色:
三、不同规则见的相互嵌套?
首先,CSS @scope范围和CSS Nesting嵌套是可以同时使用的,例如:
@scope(body) { ul { border: 1px solid; li { color: red; } } }
同样可以让列表出现边框,内容颜色是红色。
两种特性都支持和其他@规则互相嵌套。
CSS @scope范围可以嵌套其他@scope范围,例如下面的写法是合法的:
@scope(body) { ul { border: 1px solid; } @scope(li) { :scope { color: red; } } }
也支持和@media媒体查询一起使用,例如:
@scope(ul) { :scope { border: 1px solid; } @media(width < 640px) { li { color: red; } } }
和这段代码:
ul { & { border: 1px solid; } @media(width < 640px) { li { color: red; } } }
均可以在窄屏下让列表文字颜色红色,如下图所示:
四、究竟什么时候用哪个?
什么时候用范围,什么使用用嵌套呢?
我琢磨了下,似乎绝大多数场景两者是可以随意替换的。
思来想去,总感觉最大的区别反而是语义上的区别。
你如果仅仅是想让书写更加简洁,代码更加装逼,使用嵌套。
如果是单独的某个组件的开发,使用范围。
这么一想,心里舒服多了。
好了,就扯这么多吧,如果你有其他想法,欢迎评论交流。
???
本文为原创文章,欢迎分享,勿全文转载,如果实在喜欢,可收藏,永不过期,且会及时更新知识点及修正错误,阅读体验也更好。
本文地址:https://www.zhangxinxu.com/wordpress/?p=11144
(本篇完)
- CSS transition-behavior让display none也有动画效果 (0.586)
- CSS @scope他来了 (0.414)
- DOM元素querySelectorAll可能让你意外的特性表现 (0.324)
- 巧用:is()或:where()伪类让scoped的style依然全局匹配 (0.324)
- CSS必学基础:理解CSS中的级联规则 (0.122)
- 详解日后定会大规模使用的CSS @layer 规则 (0.122)
- 博闻强识:了解CSS中的@ AT规则 (0.090)
- 5分钟快速了解下CSS4 color-adjust属性 (0.090)
- CSS any-hover any-pointer media查询与交互体验提升 (0.090)
- 我是如何通过CSS向JS传参的 (0.090)
- CSS :not()伪类选择器已支持复杂参数 (RANDOM - 0.032)
很明显啊,scope是scoped css,css无法穿透,而嵌套则可以穿透
区别2没看懂,“都应该属于一个完整的规则,而不能是某一条单独的CSS声明。”这句话怎么理解?
CSS术语中,规则包含花括号,包含多个CSS声明,而CSS声明指的是类似display:block这样的语句。
错字:无需列表
@scope还有一个用法,那就是
@scope {
img {
border: 5px solid black;
background-color: goldenrod;
}
}
可以直接写style到某个元素里,scope只对当前元素下的元素生效,不会影响到外面去()
感觉是取代了之前用shadow dom做的hack,现在不需要shadow dom也可以实现可复用组件了
我感觉不同还可以包含 @scope 支持 @scope (scope root) to (scope limit) 这种语法,这种通过 Nesting 语法来实现,就麻烦一些
可以用css nesting尝鲜了,scope目前Firefox不支持
没什么用。还不如直接写原来的不嵌套语法。浏览器兼容性更好。
建议本篇再补充下 CSS Nesting 的兼容性。
查了下似乎Nesting的兼容性更好点,Firefox支持,而Firefox还不支持@scope