原子 CSS 日益普及

Avatar of Ollie Williams
Ollie Williams

DigitalOcean 为您旅程的每个阶段提供云产品。 立即开始使用 200 美元的免费信用额度!

即使您认为自己是 CSS 专家,在大型项目中也可能遇到过难以处理的复杂、迷宫般的样式表,而且它不断增长。 有些样式表就像一个混乱的、纠缠在一起的继承网络。

意大利面条怪兽

级联非常强大。 微小的变化会产生巨大的影响,这使得难以了解直接的后果。 重构、更改和删除 CSS 被认为是冒险的,并且以恐惧的态度进行,因为很难知道它在所有地方都被使用。

在使用新工具时,一件事通常很难说明,即 **何时,确切地说** 您开始使用它? 答案很少(如果有的话)是 *立即* 并且 *在所有情况下*。

在我的有限经验中,其中一种情况是在具有大型代码库的大型团队中。 **感觉是 CSS 会变得过大,团队成员开始害怕它,CSS 也就变成了一个“只追加”的工具,尽管这有点调侃,但却很准确。**

这时候就出现了这样一种工具,它承诺交付更少的 CSS 代码,并且通过一种方式(在经过学习曲线后)让每个人不再害怕它……我能理解这种吸引力。

Chris Coyier

原子 CSS 让一切变得简单

我不再需要考虑如何组织我的 CSS。 我不必考虑如何命名我的“组件”,在哪里划定一个组件与另一个组件之间的界限,什么应该放在哪里,最重要的是,当新的需求出现时如何重构这些东西。

Callum Jefferies,在使用 BEM 很久后尝试 Tachyons CSS 的一些感想

原子 CSS 提供了一种简单、直观、易懂的方法。 类是不可变的——它们不会改变。 这使得 CSS 的应用可预测且可靠,因为类将始终执行*完全*相同的事情。 在 HTML 文件中添加或删除实用程序类的范围是明确的,让您确信不会破坏其他内容。 这可以减少认知负荷和心理负担。

命名组件是出了名的困难。 确定既有意义又足够模糊以便重复使用的类名既费时又费脑。

计算机科学中只有两件难事:缓存失效和命名事物。

– Phil Karlton

找到合适的抽象很难。 相比之下,命名实用程序类非常简单。

/* naming utility classes */
.relative {
  position: relative;
}
.mt10 {
  margin-top: 10px;
}
.pb10 {
  padding-bottom: 10px;
}

原子类不言自明。 它们的意图和效果是显而易见的。 虽然用无数个类来填充 HTML 看起来很杂乱,但 HTML 比一道深不可测、庞大无比、难以理解的交织在一起的样式墙更容易理解。

在一个能力混合的团队中,可能包括对 CSS 兴趣和知识有限的后端开发人员,人们不太可能搞乱样式表。

取自 ryanair.com - 一堆 CSS 都在做一件事。

处理风格变化

实用程序类 非常适合处理小的风格变化。 虽然设计系统和模式库如今很流行,但这种方法所认识到的是,会不断出现新的需求和变化。 关于组件可重用性的所有讨论通常在传递给您的设计模拟中没有得到体现。 虽然视觉和品牌一致性很好,但大型网站上的各种上下文环境使得某种程度的变化是不可避免且合理的。

Medium 开发团队放弃了 BEM 修饰符,如 其博客中所述

如果我们想要一个组件在只有一个小的方面与另一个组件不同,该怎么办? 如果您采用了 BEM 命名约定,修饰符类可能就会失控——无数个修饰符,通常只做一件事情。 以边距为例。 组件的边距不太可能在一个组件中保持一致。 所需的间距不仅取决于组件,还取决于它在页面上的位置以及它与其周围元素的关系。 很多时候,设计会包含相似但*不完全相同*的 UI 元素,而使用传统的 CSS 处理起来非常麻烦。

很多人不喜欢它

Aaron Gustafson,A List Apart 的主编,Web 标准项目的前任经理,微软员工。
Mozilla 工程师 Soledad Penades
来自 CSS Zen Garden 的创建者

原子 CSS 与内联样式有何不同?

这是原子 CSS 的批评者经常问的问题。 内联样式长期以来被认为是一种不好的做法,自从 Web 的早期以来就很少使用。 *批评者将原子 CSS 等同于内联样式并不完全错误,因为它们都存在相同的重大痛点。* 以下是一个例子:如果我们想将所有带有 .black 类的元素改为海军蓝,该怎么办? 我们可以这样做

.black {
  color: navy;
}

这显然是一个*糟糕*的主意。

现在的文本编辑器非常复杂。 这样做感觉有点危险,但使用查找和替换将所有 .black 类更改为新的 .navy 类将非常简单。 真正的问题是当您只想将.black类的*某些实例*更改为.navy类时。

在传统的 CSS 方法中,调整组件的样式就像更新 CSS 文件中单个类中的单个值一样简单。 使用原子 CSS,这将变成一项繁琐的任务,需要搜索每个 HTML 文件,更新该组件的每个实例。 无论代码编辑器变得多么先进,都无法避免这种情况。 即使您将标记分离到可重复使用的模板中,这也是一个主要的缺点。 **也许这种手动劳动对于这种方法的简单性是值得的。 使用不同的类更新 HTML 文件可能很繁琐,但并不难。**(虽然有时我会在手动更新时遗漏某些组件的相关实例,从而暂时引入风格不一致。)如果设计发生变化,您很可能会需要手动编辑整个 HTML 中的类。

虽然原子 CSS 与内联样式具有相同的重大缺点,但它们并不是向过去倒退。 实用程序类在很多方面都比内联样式更好。

原子 CSS 与内联样式

原子类允许抽象,内联样式则不允许

使用原子类,可以创建内联样式无法实现的抽象。

<p style="font-family: helvetica; color: rgb(20, 20, 20)">
  Inline styles suck.
</p>
<p class="helvetica rgb202020">
  Badly written CSS isn't very different.
</p>
<p class="sans-serif color-dark">
  Utility classes allow for abstraction.
</p>

上面显示的前两个示例,如果设计发生变化,将需要手动查找和替换才能更新样式。 第三个示例中的样式可以在样式表中的一个地方进行调整。

工具

Sass、Less、PostCSS、Autoprefixer……CSS 社区创建了许多内联样式所不具备的有用工具。

简洁

与编写冗长的内联样式相比,原子类可以是声明的简洁缩写。它减少了输入量:mt0 vs margin-top: 0, flex vs display: flex,等等。

特异性

这是一个有争议的观点。如果一个类或内联样式只做一件事情,很可能你想要它做那件事。有些人甚至提倡对所有实用类使用!important来确保它们覆盖其他所有内容。同样,内联样式的支持者将其无法被覆盖(除!important外)视为一个卖点——这意味着你可以确定该样式将被应用。然而,一个类本身就足够具体,可以覆盖任何基本样式。原子类相对于内联样式的较低特异性是一件好事。它允许更多的灵活性。我们都习惯在 JavaScript 中更改类以更改样式。内联样式使这变得更加困难。

样式表中的类可以做内联样式不能做的事情

内联样式不支持媒体查询、伪选择器、@supports 或 CSS 动画。也许你想要对不同的元素而不是只对一个组件应用一个悬停效果。

.circle {
  border-radius: 50%;
}

.hover-radius0:hover {
  border-radius: 0;
}

简单的可重用媒体查询规则也可以变成一个实用类。常见的是对小、中、大屏幕尺寸使用类名前缀。以下是一个仅在中、大屏幕尺寸上应用的 flexbox 类示例

@media (min-width: 600px) {
  .md-flex {
    display: flex;
  }
}

这在内联样式中是不可能的。

也许你想要一个可重用的伪内容图标或标签?

.with-icon::after {
  content: 'some icon goes here!';
}

限制选择可能是一件好事

内联样式可以是任何东西。这种自由很容易导致设计混乱和不一致。通过预定义所有内容的类,原子 CSS 可以确保一定程度的样式一致性。原子 CSS 提供了一组经过精心策划的预定义选项,而不是从无限数量的选项中即兴发挥颜色和值。开发人员从这组有限的单用途实用类中进行选择。这种限制既可以消除不断增长的样式表的问题,又能保持视觉一致性。

box-shadow为例。内联样式对于偏移量、扩散、颜色、不透明度和模糊半径将有几乎无限的选项。

<div style="box-shadow: 2px 2px 2px rgba(10, 10, 250, .4)">stuff</div>

使用原子方法,CSS 作者可以定义首选样式,然后简单地应用它,而无需考虑样式不一致的可能性。

<div class="box-shadow">stuff</div>

原子 CSS 不是非此即彼

毫无疑问,像 Tachyons 这样的实用类框架越来越受欢迎。但是,CSS 方法并不是相互排斥的。在很多情况下,实用类并不是最佳选择

  • 如果你需要在媒体查询中更改特定组件的许多样式。
  • 如果你想用 JavaScript 更改多个样式,将其抽象成一个类更容易。

实用类可以与其他方法共存。最好是在全局定义基本样式和合理的默认值。如果你不断重复相同的长字符串实用类,很可能这些样式应该抽象成一个类。你可以混合使用组件类,但只有在你知道它们会被重用时才这样做。

采用组件优先的 CSS 方法意味着你即使没有重复使用也会为事物创建组件。这种过早的抽象是样式表中许多膨胀和复杂性的根源。

Adam Wathan

单位越小,可重用性越高。

Thierry Koblentz

看看 Bootstrap 的最新版本,现在提供了一整套实用类,同时仍然包含其传统的组件。越来越多的流行框架正在采用这种混合方法。