• 作用域 CSS 回来了


    几年前,消失的作用域 CSS,如今它回来了,而且比以前的版本要好得多。

    更好的是,W3C规范基本稳定,现在Chrome中已经有一个工作原型。我们只需要社区稍微关注一下,引诱其他浏览器构建它们的实现,并完成这项工作。

    这是什么思路?

    作用域为CSS带来了两个关键点:

    1. 更好地控制哪些选择器针对哪些元素(即更好地操作级联)。

    2. 一组样式可以基于DOM中的位置覆盖另一组样式。

    局部样式允许你在页面上的单个组件内包含一组样式。你可以使用.title选择器,它只在Card组件内工作,并使用另一个.title选择器,它只在 Accordion 中工作。你可以阻止一个组件的选择器针对子组件中的元素,或者如果需要,也可以允许它们到达。

    你不再需要BEM风格的类名。

    此外,近度在级联中变成了一等公民。如果两个组件针对同一个元素(具有相同的特异性),内部组件的样式将覆盖外部组件的样式。

    它是如何工作的?

    一切都始于@scope规则和一个选择器,如下:

    1. @scope (.card) {
    2.   /* 将以下样式局限于`.card`内部 */
    3.   :scope {
    4.     padding: 1rem;
    5.     background-color: white;
    6.   }
    7.   .title {
    8.     font-size: 1.2rem;
    9.     font-family: Georgia, serif;
    10.   }
    11. }

    这些样式都限制在.card元素中。:scope是一个特殊的伪类,针对.card元素本身,.title针对标题内部的标题。

    @scope规则本身不增加这些选择器的特异性,所以它们都是(0, 1, 0)。是的,特异性仍然很重要,但这是好事™️。稍后再说。

    此时,你可以使用普通的后代选择器来实现这一点。但当你在范围内应用内部边界或在页面上重叠多个范围时,新的、以前不可能的选项开始出现。让我们看看它们是怎么做的...

    内部范围边界

    假设你预计将其他组件放入你的Cards中,所以你不希望.title 选择器针对除属于Card的那个标题之外的任何东西。为此,你在范围上设置了一个内部边界,如下:

    1. @scope (.card) to (.slot) {
    2.   /* 限定的样式只在`.card`内部,但不在`.slot`内部 */
    3.   :scope {
    4.     padding: 1rem;
    5.     background-color: white;
    6.   }
    7.   .title {
    8.     font-size: 1.2rem;
    9.     font-family: Georgia, serif;
    10.   }
    11. }

    把这里的 to 关键字看作 直到:这个范围是从.card.slot定义的。现在,没有一个局限的选择器会针对Card的.slot元素内部的任何东西。所以你可以这样构建你的卡片:

    1. "card">
    2.   "title">Moon lander
    3.   "slot">
    4.     
    5.   

范围的影响受到了限制,使其不针对.slot内的任何东西。这样,你可以嵌套两个范围,每个范围都可以使用相同的通用标题类名,而不会发生冲突。实际上,你可能根本不再需要类名了:

  1. @scope (.card) to (.slot) {
  2.   h3 {
  3.     font-size: 1.2rem;
  4.     font-family: Georgia, serif;
  5.   }
  6. }
  7. @scope (.accordion) to (.slot) {
  8.   h3 {
  9.     font-family: Helvetica, sans-serif;
  10.     text-transform: uppercase;
  11.     letter-spacing: 0.01em;
  12.   }
  13. }

你可以在 Card 内部放一个 Accordion,或者在 Accordion 内部放一个Card,它们各自的样式不会发生冲突。

这被俗称为 甜甜圈范围,因为范围中有一个洞。(如果内部边界选择器针对多个元素,它也可以有多个洞。)

Miriam Suzanne 建议使用这种方式是持续使用data-*属性和属性选择器作为你的范围:

  1. @scope ([data-scope='media']) to (:scope [data-scope]) {
  2.   /* 限定的样式在这里 */
  3. }

近度优先 Proximity precedence

另一个方面是近度的概念:来自内部范围的样式将覆盖来自外部范围的样式。想象你有这样两个范围:

  1. @scope (.green) {
  2.   p {
  3.     color: green;
  4.   }
  5. }
  6. @scope (.blue) {
  7.   p {
  8.     color: blue;
  9.   }
  10. }

将以下内容应用于HTML。这里没有内部范围约束,所以两个p选择器都针对这里的内部段落。在这种情况下,内部范围总是优先:

  1. "green">
  2.   

    我是绿色的

  3.   "blue">
  4.     

    我是蓝色的

  5.   
  • "blue">
  •   

    我是蓝色的

  •   "green">
  •     

    但我是绿色的

  •   
  • 注意这目前只在Chrome中有效,需要在chrome://flags中启用实验性Web平台功能标志。

    你可以在DevTools中检查,看到每个范围是如何根据其最近的接近性来覆盖另一个的:

    28bc86d499a7f84d525b808b0c88c940.png

    ac3f6718baed42ed2abedb3da4d26b74.png

    这里的问题是,选择器的特异性仍然是优先的,所以如果外部范围以比内部更高的特异性针对一个元素,外部范围的样式将会应用。

    这样,当两个范围针对同一个元素时,你可以控制哪一个优先。而不是总是让内部范围赢,你可以调整选择器的特异性,使得更高特异性的选择器优先,不管它属于哪个范围。

    当你不希望这种行为时,你有几种方法可以防止它。你可以使用级联层来使一个组件——或者一个组件的某些部分——优先于另一个。或者,你可以应用一个内部范围约束到外部范围,以防止它发生。在尝试了一段时间的范围后,我觉得这是一个正确的平衡。它给了你最大的控制权,而不是让你受制于级联的一套严格的规则。

    这是一个游戏的转折点

    如果你开发过大型应用,并且不得不依赖 CSS-in-JS 库来防止类名冲突,作用域 CSS是个很好的选择。如果你使用了复杂的BEM类名系统,并努力使所有的选择器特异性保持一致,想想这可以带来的自由。如果你曾经使用过shadow DOM来隔离样式,但觉得它过于重手,这是一个更好的方法(当然,shadow DOM仍然有它的用途)。

    以下只是我会尝试的一些想法:

    1. 定义一个组件的部分,有一个内部边界,部分没有,所以它的“chrome”样式(即包装器、切换按钮等)不影响其子内容,但它可以影响文本内的外观。

    2. 在不同的级联层上定义一个组件的部分,这样它可以影响其包含的范围,但仍然容易在更高的层次上覆盖。

    3. 嵌套的颜色主题。

    4. 在博客文章中更容易地防止样式冲突。

    5. 容器查询—我们能通过混合和匹配来提出什么?

    我们需要更多的浏览器支持

    到目前为止,Chrome 似乎已经支持了—他们已经有了第一个工作原型几个月了。它可能稍微落后于规范的最新变化,所以如果你玩一下,要留意一些即将到来的小变化。

    欢迎长按图片加刷碗智为好友,定时分享 Vue React Ts 等。

    72fd58cf7d07baa39ebef60c6f354751.png

    最后:

    vue2与vue3技巧合集

    VueUse源码解读

  • 相关阅读:
    【C++】简述STL——string类的使用
    物理机服务器应该注意的事
    sourcetree提交代码出现闪退报错(已解决)
    Leetcode151. 反转字符串中的单词
    AUTOSAR汽车电子嵌入式编程精讲300篇-车载网络 CAN 总线报文异常检测
    分享 | 计算机组成与设计学习资料+CPU设计源码+实验报告
    java毕业设计哈尔滨文旅信息网站mybatis+源码+调试部署+系统+数据库+lw
    Dubbo面试题及答案整理,Dubbo面试题大全带答案(2021最新版)
    Spring boot接收zip包并获取其中excel文件的方法
    【不是问题的问题】为什么复位中断服务程序里面直接调用的main函数,难道所有程序都在复位中断里面执行的?
  • 原文地址:https://blog.csdn.net/qq449245884/article/details/133366094