现代CSS:使用 CSS @scope 替代 BEM
日常 Web 开发中,前端工程师经常遇见或者最有挑战的事情之一就是 CSS 命名约定了。随着 Block Element Modifier (BEM) 规范的流行,开发者者开始习惯以可维护的模式组织样式。
好消息!近期发布的 Chrome 118 版本已经实现对 CSS @scope 的支持,以允许在样式表中对样式进行区块级作用域,进一步提高 BEM 的优势。这使样式更易于维护,同时提供对影响任何前端应用程序的 CSS 层叠的更严格的控制。
在本文中,我们将探讨如何在 Chrome 中使用 @scope 功能,以及如何在前端项目中使用它来替代 BEM。
主要内容如下:
CSS @scope 介绍 BEM 介绍 使用 CSS @scope 重构 BEM
1.CSS @scope 介绍
对于 CSS 样式隔离,CSS 作用域大家都不陌生,主流的方案包括 CSS Modules、CSS in JS、Shadow DOM、Vue Scoped Styles 等,这些方案都有各自的优缺点,但是都不是原生的 CSS 方案,使用和版本升级需要一些学习成本。
Chrome 118 版本中,已经实现对 CSS @scope 的支持,@scope 特性可以为CSS样式创建区块级作用域,这使开发人员对CSS样式更有控制权,我们现在可以直接在 CSS 文件中具体定义视图部分的作用域。
@scope 语法规则:
@scope [(<scope-start>)]? [to (<scope-end>)]? {
<rule-list>
}
@scope兼容性:
@scope 示例:
请看下面的 HTML 示例:
<main class="container">
<section class="section section-one">
<h2>First</h2>
<p>first section paragraph text</p>
</section>
<section class="section section-two">
<h2>Second</h2>
<p>second section paragraph text</p>
</section>
</main>
在此 HTML 中,我们可以使用以下方法对 .section-two
样式区域中的元素进行样式设置:
.container {
max-width: 600px;
margin: 0 auto;
.section {
display: flex;
flex-direction: column;
border: 1px solid #ccc;
border-radius: 5px;
margin-bottom: 10px;
& h2 {
font-size: 16px;
line-height: 36px;
text-align: center;
background-color: #ccc;
margin: 0;
}
& p {
font-size: 24px;
text-align: center;
}
}
}
@scope (.section-two) {
p {
color: #f00;
}
}
效果如下:
使用 @scope,还可以创建一个 "甜甜圈" 作用域,为一组样式及其中的元素定义起始和结束部分。使用上述相同的 HTML,"甜甜圈"作用域可以定义从 .container
的起始区域到 .section-two
样式区域的样式,将上面的 @scope 样式做如下替换:
@scope (.container) to (.section-two) {
p {
color: #00f;
}
}
效果如下:
令人愉快的是,它的功能与使用 BEM 规范非常相似,但代码量更少。
2.BEM 介绍
BEM 是一种简单的命名约定,可使前端代码更易于阅读、理解、使用和扩展。它既稳健又清晰。
我们都知道,HTML 文档如果没有良好的结构会有多混乱。如果再加上一个糟糕的 CSS 类命名规范,你的代码库就会变得难以理解、漏洞百出,甚至难以扩展。
遵循 BEM 命名规范,不仅能简化 CSS 文件的结构,还能简化 HTML 文档的结构。我们可以使用独立的代码块和 CSS 选择器,以组件驱动的方式进行思考,从而使我们的代码具有可重用性和模块性。
要使用 BEM,我们只需遵循其命名规则即可!
B 代表块(block)。区块是一个独立的实体。例如卡片组件 E 代表元素(Element)。元素是区块的一部分,在语义上与区块相关联,本身没有任何意义。 M 代表修改器(Modifier)。它只是一个标记,可以修改元素或块的外观或行为
看下面的 HTML 示例:
<main class="container">
<section class="container__section-one">
<h2 class="container__section-one--title">First</h2>
<p class="container__section-one--first-line">first section paragraph text</p>
</section>
<section class="container__section-two">
<h2 class="container__section-two--title">Second</h2>
<p class="container__section-two--first-line">second section paragraph text</p>
</section>
</main>
BEM 的扩展性很好,尤其是在使用 SASS 对样式进行分组,并使用 "&" 运算符创建类似样式的情况下:
.container {
&__section-one {
&--title {
/* rule */
}
&--first-line {
/* rule */
}
}
}
使用 BEM 的痛点在于,在大型项目中,会产生非常大的 CSS 或者 SASS 文件,而这些文件会带来难以估量的维护和管理成本。下面我们将探讨使用 @scope 替代 BEM 样式,使样式定义更小、更易于管理。
3.使用 CSS @scope 重构 BEM
要展示使用 @scope 的优势,最好的方法是在使用 React 等主流框架或库的应用程序中使用。为了简单演示,我们还是使用上面的示例,将 section-one
区块的标题样式使用 @scope 重写:
/* replaced */
/* container__section-one--title {
color: #f00;
} */
/* donut scope */
@scope (.container) to (.section-two) {
h2 {
color: #f00;
}
}
这样做的另一个好处是,HTML 结构更简洁,单行字数更小,更容易阅读。改为 @scope 后的 HTML 代码:
<main class="container">
<section class="section-one">
<h2>First</h2>
<p>first section paragraph text</p>
</section>
<section class="section-two">
<h2>Second</h2>
<p>second section paragraph text</p>
</section>
</main>
4.@scope 的其他优点
除了将 BEM 重构为 @scope 的优点外,使用 @scope 还可以更好地控制 CSS 级联。CSS 级联是一种算法,它定义了网络浏览器如何处理组成 HTML 页面上元素的样式条件。
在处理任何前端项目时,当样式产生奇怪的结果时,开发人员可能不得不适应级联产生的副作用。使用 @scope,可以通过对元素进行严格的范围限定来控制级联的副作用。
<style>
div {
padding: 10px;
border-radius: 5px;
}
.light {
background: #ccc;
& a {
color: #f00;
}
}
.dark {
background: #333;
& a {
color: #00f;
}
}
</style>
<div class="light">
<p><a href="#">First Level</a></p>
<div class="dark">
<p><a href="#">Second Level</a></p>
<div class="light">
<p><a href="#">Third Level</a></p>
</div>
</div>
</div>
效果如下:
我们发现第二次的 .light
颜色并没有生效,因为 .light
和 .dark
的权重是一样的,无法实现覆盖。使用 @scope 改进后:
<style>
div {
padding: 10px;
border-radius: 5px;
}
@scope (.light) {
:scope {
background-color: #ccc;
}
a {
color: #f00;
}
}
@scope (.dark) {
:scope {
background-color: #333;
}
a {
color: #00f;
}
}
</style>
效果如下:
总结
在这篇文章中,我们探讨了如何将 BEM 风格的应用程序重构为使用 Chrome 浏览器新推出的 @scope 功能。我们介绍了 @scope 的工作原理,然后将一个简单的示例从 BEM 重构为 @scope。
新的 @scope 功能可能对前端开发人员来说是一个巨大的胜利,被所有现代浏览器所支持,这可能需要一些时间。但在此之前,它绝对是一个有趣的功能,并且对于样式化前端项目非常有帮助。如果你手上有内部或者系统类项目,快快动手试用起来吧。
如果本文对你有帮助,欢迎一键三连,转转转!
大家都在看