整合营销服务商

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

免费咨询热线:

如何在vue中继续使用layer.js,亲测好用



ayer.js是一个方便的弹出层插件,切图网专注于PSD2HTML等前端切图多年,后转向Vue开发。在vue开发过程中引入layer.js的时候遇到了麻烦。原因是layer.js不支持import导入,这时就需要修改一下它的源码。在看过它的源码后,发现需要修改的地方只有两处,

源码中已经暴露了一个全局变量layer,故只需在脚本末尾处添加

export default layer;

这表示将这个全局变量导出。

然后在文件中找到下面的代码注释掉,这段代码是为layer添加样式的,但使用的路径不对,故没有太大帮助。

document.head.appendChild(function() {
    var link = doc.createElement('link');
    link.href = path + 'need/layer.css?2.0';
    link.type = 'text/css';
    link.rel = 'styleSheet'link.id = 'layermcss';
    return link;
} ());

接下来把layer.js和layer.css分别放入static/js和static/css中,在需要的地方,比如组件内部或者全局注册,因为项目多处都会用到,所以采用全局注册,在main.js中

import layer from '../static/js/layer.js'

layer.css也使用全局注册,它可以放在index.html中通过link引入,也可以放在App.vue中

<!--index.html-->
<link rel="stylesheet" href="./static/css/layer.css" />
<!--或者-->
<!--App.vue-->
<style>
@import "../static/css/layer.css";
</style>

接下来就能在各个组件中使用layer.open等方法了。

这种方式应该可以适用于各种不支持import导入的脚本,即非npm提供的module。

往 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。如果没有匹配,则不定义层。

近在Weekly邮件推送中查阅到这样的一条信息:

Chromium 团队宣布他们将随 Chromium 99(预计在明年 3 月发布)一起发布CSS Cascade Layers

会发现这条信息里面出现了一个CSS的新名词CSS Cascade Layers,出于好奇以及对新知识的渴望(说得我自己都信了,哈哈),于是查阅起CSS Cascade Layers的相关资料,试图搞懂它。

前置知识

at-rule规则

at-rule规则, CSS Conditional Rules Module Level 3新增的规则,是一条语句,它为CSS提供了执行或如何执行的指令,常见的at-rule规则有:

@import,允许用户从其他样式表导入样式规则

@font-face,允许我们引用自定义的字体

@keyframes,声明一个动画

@media,是条件CSS中的一种,其条件是一个媒体查询

@supports,测试用户代理是否支持CSS属性/值对

@viewport,用来控制移动设备上的viewport设置

Cascading and Inheritance Level

级联(层叠)与继承经过多年的发展迭代,目前已有多个版本(CSS2.2、Level3、Level4 和 Level5

何为级联(层叠)?

层叠本质就是定义了如何合并来自多个源的属性值的算法,简单来说,CSS规则的顺序很重要。当两条同级别的规则应用到一个元素的时候,写在后面的就是实际使用的规则。

h1 { 
    color: red; 
}
h1 { 
    color: blue; 
}

两条规则优先级相同,所以顺序在最后的生效,h1color:blue'胜出',显示蓝色。

只有CSS声明,就是属性名值对,会参与层叠计算。这表示包含CSS声明以外实体的@规则不参与层叠计算,如包含描述符的@font-face,@规则(at-rule规则)是做为一个整体参与层叠计算。

css属性一般来自于哪几个源?

1、用户代理样式表:浏览器的基本的样式表,用于给所有网页设置默认样式。
2、用户样式表:网页的作者可以定义文档的样式。大多数情况下此类型样式表会定义网站的主题。
3、浏览器的用户使用自定义样式表定制使用体验。

层叠(级联)算法如何过滤来自不同源的css规则?

相互冲突的声明按以下顺序适用,后一种声明将覆盖前一种声明:

1、用户代理样式表中的声明(浏览器的默认样式)。
2、用户样式表中的常规声明(用户设置的自定义样式,就如同我们的reset.css)。
3、作者样式表中的常规声明(开发人员设置的样式)。
4、作者样式表中的!important声明
5、用户样式表中的!important 声明

过滤来自不同源的css规则后,确定同源优先级高低,决定谁“优胜”

  !important > 内联style > #id > .class > 标签

了解级联算法有助于帮助我们理解浏览器是如何解决样式规则冲突,也就是浏览器决定哪个样式规则运用到元素上,更多相关css级联的了解:

何为继承?

当元素的一个继承属性没有指定值时,则取父元素的同属性的计算值 。只有文档根元素取该属性定义的默认值,类似的属性有colorfont-size等 。

CSS是由Cascading Style Sheets三个词的首字母缩写,很多人将其称为层叠样式表或者级联样式表.

@layer

CSS Cascade Layers,也叫做CSS级联层,是Cascading and Inheritance Level5 规范中新增了一个新的 CSS 特性,对应的CSS属性写法@layer,即一个新的 @ 规则,也就是大家所说的at-rule 规则。

为啥会出现@layer?

通过上面我们对级联介绍,我们已经看到了顺序对于层叠的重要性,同权重的css属性后者会“优胜”前者,权重不同会根据CSS声明来源和优先级算法来判断谁“优胜”。!important的CSS规则自动将它跳到层叠算法的前面,能够覆盖普通规则的层叠。

也就是说我们一般会使用选择器权重和顺序作为控制级联的方法,但是这样却会时常碰到:

使用较高权重的选择器来防止你的代码被后面的代码(或别人的代码)覆盖。但这也会引起另一个不良的现象,可能会在代码中新增很多带有 !important 的样式规则,这本身就会引起更多的问题,比如 !important 在 CSS 样式表中随处可见,需要覆盖的时候难以被覆盖

使用较低权重的选择器又很容易被后面的代码(或别人的代码)覆盖。比如你在引入第三方代码库或组件时,自己的代码可能被覆盖。

这两个现象也是编写CSS代码,特别是在一个大型项目或多人协作的项目中常出现。也给很多CSS开发者带来很多困扰。

虽然社区有很多第三方方案,如CSS-in-JSCSS ModulesCSS Scoped等来协助解决级联所带来的问题,但由于源码顺序(打包产物)仍然起着决定性的作用,顺序带来的覆盖和冲突依旧未真正的解决,而且选择器权重仍然比层的顺序(源码顺序)更重要

这样的背景促进了@layer的出现,要真正的解决级联带来的这些问题。

@layer的出现,也要求我们对以往css级联有个新的了解,

可以看出CSS的级联层一般位于“Style 属性”(Style Attribute)和 CSS 选择器权重(Specificity)之间。

使用CSS级联层,可以通过@layer at-rule将 CSS 分成多个层。

与 CSS属性来源 在用户样式表和作者样式表风格之间提供权衡的方式相同,Cascade Layers 提供了一种结构化的方式来组织和权衡单个 来源 内的关注点

如何使用

创建级联层

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

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 themeinput会取胜。

级联层嵌套

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

@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。如果没有匹配,则不定义层。

结语

随着 Cascade Layers 的出现,我们的开发人员将拥有更多的工具来控制 CascadeCascade Layers 的真正力量来自它在 Cascade 中的独特位置:Style 属性(Style Attribute)CSS 选择器权重(Specificity)之间。因此,我们不需要担心其他层中使用的 CSS 的选择器特异性,也不需要担心我们将 CSS 加载到这些层中的顺序.

了解到这里,是不是觉得@layer相当地cool,迫不及待地想去使用了,我们看一下caniuse @layer的兼容情况,

很遗憾,支持程度惨不忍睹,想真正使用可能还要再等等,对于明年三月份 Chromium 99,发布我们拭目以待。

当然现在如果想尝鲜,对于社区也有给出一些办法,

大家也可以试一试,感谢阅读!