整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

CSS新特性@layer(层叠样式表)

CSS新特性@layer(层叠样式表)

往 css 优先级中存在的问题

如果我们的页面上存在非常多的样式,譬如有我们开发页面的时候的自定义样式,也有引入的组件库样式。这时候样式将会非常混乱难以管理。

当我们想覆盖一些本身非我们书写的样式时候,往往不得不通过使用优先级权重更高的样式名,去覆盖那些样式。

同时,当样式优先级感到难以控制时,开发者习惯滥用 !important 去解决,这又循环导致了后续更混乱的样式结构。

基于让 CSS 得到更好的控制和管理的背景,CSS @layer 应运而生。

何为 CSS @layer?

CSS Cascade Layers,也叫做CSS级联层,是Cascading and Inheritance Level5 规范中新增了一个新的 CSS 特性。

@layer声明了一个 级联层, 同一层内的规则将级联在一起, 这给予了开发者对层叠机制的更多控制。语法也非常简单,看这样一个例子:

@layer utilities {

  /* 创建一个名为 utilities 的级联层 */

}

这样,我们就创建一个名为 utilities 的 @layer 级联层。

@layer语法

@layer规则可以通过三种方式其一来创建级联层。第一种方法如上方代码所示,它创建了一个块级的@规则,其中包含作用于该层内部的CSS规则。

@layer utilities {

  .padding-sm {

    padding: .5rem;

  }




  .padding-lg {

    padding: .8rem;

  }

}

一个级联层同样可以通过 @import 来创建,规则存在于被引入的样式表内:

@import(utilities.css) layer(utilities);

你也可以创建带命名的级联层,但不指定任何样式。例如,单一的命名层:

@layer utilities

或者,多个命名层也可以被同时定义。例如:

@layer theme, layout, utilities

这一做法很有用,因为层最初被指定的顺序决定了它是否有父级层。对于声明而言,如果同一声明在多个级联层中被指定,最后一层中的将优先于其他层。

因此,在上面的例子中,如果 theme 层和 utilities 层中存在冲突的规则,那么 utilities 层中的将优先被应用。

即使 utilities 层中规则的 优先级低于 theme 层中的,该规则仍会被应用。一旦级联层顺序建立之后,优先级和出现顺序都会被忽略。

这将使创建CSS选择器变得更加简单,因为你不需要确保每一个选择器都有足够高的优先级来覆盖其他冲突的规则,你只需要确保它们出现在一个顺序更靠后的级联层中。

:在已经声明级联层的名字后,它们的顺序随即被确立,你可以重复声明某级联层的名字来向其添加CSS规则。这些样式将被附加到该层的末尾,且级联层之间的顺序不会改变。

其他不属于任何一级联层的样式将被集中到同一匿名层,并置于所有层的前部,这意味着任何级联层内定义的规则都将覆盖外部声明的规则。

嵌套层

级联层允许嵌套,例如:

@layer framework {

  @layer layout {




  }

}

向 layout 层内部的 framework 层附加规则,只需用 . 连接这两层。

@layer framework.layout {

  p {

    margin-block: 1rem;

  }

}

匿名层

如果创建了一个级联层但并未指定名字,例如:

@layer {

  p {

    margin-block: 1rem;

  }

}

那么则称为创建了一个匿名层。除创建后无法向其添加规则外,该层和其他命名层功能一致。

标准语法

@layer [ <layer-name># | <layer-name>?  {

  <stylesheet>

} ]

@layer如何使用

创建级联层

级联层可以通过多种方式声明:

1、使用@layer 块规则,并立即为其分配样式:

@layer reset {

  * { /* Poor Man's Reset */

    margin: 0;

    padding: 0;

  }

}

2、使用规则@layer 语句,没有指定任何样式:

@layer reset;

3、将@import 与layer关键字或layer()函数一起使用

@import(reset.css) layer(reset);

以上每一个都创建了一个名为 的级联层reset。

管理级联层

级联层会按它们声明的顺序排序。

在下面的例子中,我们建立四个级联层:reset,base,theme,和utilities。

@layer reset { /* 创建级联层 “reset” */

  * {

    margin: 0;

    padding: 0;

  }

}




@layer base { /* 创建级联层 “base” */

  …

}




@layer theme { /* 创建级联层 “theme” */

  …

}




@layer utilities { /* 创建级联层 “utilities” */

  …

}

按照它们的声明顺序,层顺序变为:

reset
base
theme
utilities

重复使用级联层名称时,样式将附加到现有级联层。级联层的顺序保持不变,因为只有第一次的出现已经确定顺序:

@layer reset { /* 创建第一个级联层 “reset” */

  …

}




@layer base { /* 创建第二个级联层 “base” */

  …

}




@layer theme { /* 创建第三个级联层 “theme” */

  …

}




@layer utilities { /* 创建第四个级联层 “utilities” */

  …

}




@layer base { /* 会将样式添加至级联层“base” */

  …

}

重新使用级联层名称时层顺序保持不变的使@layer 语法变得更加方便和严谨。使用它,可以预先建立图层顺序,然后将所有 CSS 附加到它:

@layer reset;     /* 创建第一个级联层 “reset” */

@layer base;      /* 创建第二个级联层 “base” */

@layer theme;     /* 创建第三个级联层“theme” */

@layer utilities; /* 创建第四个级联层 “utilities” */




@layer reset { /* 添加样式至级联层 “reset” */

  …

}




@layer theme { /* 添加样式至级联层  “theme” */

  …

}




@layer base { /* 添加样式至级联层  “base” */

  …

}




@layer theme { /* 添加样式至级联层  “theme” */

  …

}

当然你可以用更短的语法来声明级联层,

@layer reset, base, theme, utilities;

从上面可以看出,多个级联层被声明时,最后一个级联层的声明会获胜。像这样,

@import(reset.css) layer(reset); /* 第一个级联层 */




@layer base { /* 第二个级联层 */

  form input {

    font-size: inherit; 

  }

}




@layer theme { /*第三个级联层 */

  input {

    font-size: 2rem;

  }

}

按以往CSS级联来进行分析的话,form input(多层级)的优先级会大于input,但是由于级联层所起的作用,@layer theme的input会取胜。

级联层嵌套

级联层支持嵌套使用,如下:

@layer base { /* 第一个级联层*/

  p { max-width: 70ch; }

}




@layer framework { /* 第二个级联层 */

  @layer base { /* 第二级联层的嵌套子级联层1 */

    p { margin-block: 0.75em; }

  }




  @layer theme { /* 第二级联层的嵌套子级联层2 */

    p { color: #222; }

  }

}

在这个例子中有两个级联外层:

base
framework

该framework层本身也包含两层:
base
theme

如果要将样式附加到嵌套级联层,需要使用以下全名来引用它,

@layer framework {

  @layer default {

     p { margin-block: 0.75em; }

  }




  @layer theme {

    p { color: #222; }

  }

}




@layer framework.theme {

  /* 这些样式会被添加到@layer framework层里面的theme层 */

  blockquote { color: rebeccapurple; }

}

@media与@layer

@media (min-width: 30em) {

  @layer layout {

    .title { font-size: x-large; }

  }

}




@media (prefers-color-scheme: dark) {

  @layer theme {

    .title { color: white; }

  }

}

如果第一个@media (min-width: 30em)匹配(基于视口尺寸),则layout级联层层将在图层顺序中排在第一位。如果只有@media (prefers-color-scheme: dark)匹配,theme则将是第一层。

如果两者匹配,则图层顺序将为layout, theme。如果没有匹配,则不定义层。

ayer是一个开源免费的弹出层组件,简单易用、美观,功能强大能够满足你对弹出层的几乎所有需求,每一种模式都有自己的特色,调用简单实用性强,可轻松实现Alert、Confirm、Prompt、普通提示、页面区块、iframe、tips等几乎所有的弹出模式。此组件知名度高,在此仅介绍给不知道的新人,谢谢支持。

1、下载及初始化

http://layer.layui.com/

layer是一个独立的组件,能够在不引入layui的情况下单独引入layer,下载文件后放到项目任意位置,在页面输入如下代码引入jQuery和layerjs即可。需要注意的是jQuery必须引入1.8及以上版本。

在页面body中添加一个按钮,为按钮添加id属性<button id="test1">运行</button>,运行如下代码脚本,点击按钮即可。

2、不同模式弹层的演示

layer调用不同内置方法即可弹出不同模式的弹层,内置多个配置属性,可以配置标题、内容、皮肤、宽高、弹出位置、按钮(包括关闭按钮、自定义按钮、排序等)、自动关闭时间、遮盖、动画、是否允许拉伸等;多种状态监听事件;通过不同功能组合,就能够实现你想要的需求。下面简单展示一下不同模式的弹层。

①基础层

②询问层

③页面层

④Tips层

⑤加载层

⑥prompt层

⑦tab层

⑧相册层

⑨边缘弹出

⑩iframe层

API文档:

http://www.layui.com/doc/modules/layer.html


layer弹层小巧简单,但功能确一点也不简单,使用方便、美观,layer兼容所有现代浏览器及IE6+,能够轻松应对各种使用场景,这个组件强烈推举给大家。写这篇文章只为让更多人知道layer,写得不好的地方,请各位大神轻喷,再次感谢。

@layer又名级联层,是 css2022 推出的新特性,目的是用来解决样式被覆盖,使用混乱的场景。
同一层内的规则将级联在一起, 这给予了开发者对层叠机制的更多控制,让 CSS 样式按照我们定义好的级联顺序展示,起到控制不同样式间的优先级的作用。

语法

@layer a {
    div {
        background-color: red;
    }
}
创建了一个名字为a的级联层

我们也可以先定义级联层,之后再补充规则

@layer a,b,c;
@layer a {
	div {
		background-color: red;
	}
}

@layer b {
	#box {
		background-color: blue;
	}
}

@layer c {
	div {
		background-color: green;
	}
}

级联层的执行顺序将会按照定义的时候的先后顺序执行,所以,最终会执行 c 的级联层,得到一个蓝色的 div,即使级联层 b 是一个 id 选择器,仍然是最后一个级联层会生效

此时的级联层的顺序是@layer c > @layer b > @layer a

由此,我们可以大致得出一个结论:可以利用级联层将 css 进行模块的划分,按照先后顺序,更好的控制样式。

怎么引用

引用的方式分为三种

  • 内部引入

直接创建一个 @layer 规则,其中包含作用于该层内部的 CSS 规则:

  • @import 引入
@import(index.css) layer(a);


- 命名方式

创建带命名的级联层,但不指定任何样式。样式随后可在 CSS 内任意位置添加

@layer a;

@layer a {
    div {
        color: red;
    }
}

非 @layer 包裹层与 @layer 层内样式优先级

没有被 @layer 包裹的样式和被 @layer 包裹的样式相比,那个优先级更高呢。

@layer A {
	div {
		background: red;
	}
}
@layer B {
	div {
		background: orange;
	}
}
@layer C {
	div {
		background: yellow;
	}
}
div {
	background: green;
}

最终为绿色,这里会有一个非常重要的结论,非 @layer 包裹的样式,拥有比 @layer 包裹样式更高的优先级,因此,上述规则的排序是:未被 @layer 包裹的样式 > @layer C > @layer B > @layer A

级联层的规则

级联层可以像上面的案例一样,简单命名,也可以设置匿名使用方式和嵌套使用方式 ### 匿名 允许创建一个不带名字的 @layer:

@layer {
    p {
        margin: 1rem;
    }
}

这里,创建了一个匿名层。匿名层的两个重要特性:

  • 创建后无法向其再添加规则
  • 该层和其他命名层功能一致,优先级也遵循后定义的匿名层,比其他已定义的 @layer 层,优先级更高
@layer a,b,c;
@layer {
    div {
        background: orange;
    }
}
@layer a {
    div {
        background-color: red;
    }
}

@layer b {
    #box {
        background-color: green;
    }
}
@layer c {
    div {
        background-color: blue;
    }
}

最终展示匿名层的样式,此时的优先级的顺序为 匿名层@layer > @layer c > @layer b > @layer a > @layer a

嵌套层

嵌套层的意思就是在 @layer 内部,我们可以再嵌套使用 @layer 级联层

@layer A {
    @layer B {
        ...;
    }
}

上述代码等价于

@layer A.B {
    ...;
}

那么这里的样式谁优先呢

@layer A {
    div {
        background: blue;
    }
?
    @layer B {
        div {
            background: red;
        }
    }
}

最终为蓝色, 对于单个 @layer 内的嵌套关系,样式优先级为 @layer A > @layer A.B

!important 对 CSS @layer 的影响

div {
    background: black;
}
@layer A {
    div {
        background: blue !important;
    }
}
@layer C {
    div {
        background: green;
    }
}

最终会展示!important的样式,也就是说!important的规则更加优先。

那么,接下来这个场景呢?

div {
    background: black !important;
}
@layer A {
    div {
        background: blue !important;
    }
}
@layer C {
    div {
        background: green;
    }
}

在上述代码中,非级联层和级联层 A 中各添加了一个!important, 结果为蓝色。

这是一个非常重要的特性,在比较正常(非 !important)规则时,越是级联(排序较后的 @layer 规则),优先级越低;反之,在比较 !important 规则时,越是级联靠后的(排序较后的 @layer 规则),优先级越高。

!important在比较的时候遵循下面的规则

  • !important 样式高于非 !important 样式
  • 在比较 !important 规则时,优先级顺序与正常规则相反,在正常状态下优先级越低的,在 !important 下优先级越高。