围绕“我们是否还需要 CSS?”的争论

Avatar of Chris Coyier
Chris Coyier

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 $200 免费积分!

这最近成为了一个热门话题。它在我最近参加的一些会议和聚会上被讨论过。我看到了关于它的幻灯片。我知道有些人根本没有在生产中使用任何 CSS。相当疯狂,对吧?

我认为我们可以在这里围着篝火坐下来,尽可能理性地谈论它,涵盖所有相关要点。

我们显然仍然需要样式

没有人说我们不需要样式。我们仍然需要对东西进行样式化,正在讨论的是我们如何以及在何处进行样式化。我刚参加了 BrooklynJS 的一个小组讨论,Jed Schmidt

CSS 最糟糕的地方是“层叠”和“样式表”

有什么人反对 CSS 吗?

这些是反对 CSS 的主要论点

  • 一切都是全局的。 选择器与 DOM 中的所有内容匹配。您需要命名策略来对抗这种情况并保持效率(这些策略很难实施并且容易破坏)。
  • CSS 会随着时间的推移而增长。 优秀的团队中的聪明人承认他们害怕自己的 CSS。您不能简单地删除东西,因为很难知道这样做是否绝对安全。因此,他们不会删除,他们只会添加。我看到了一张图表,它显示了五年内生产 CSS 的大小,尽管公司专注于性能,但大小却稳步增长。
  • 您可以在编程语言中更动态地使用样式。 论点是这样的:“我们已经在用预处理器来增强 CSS 了,不如再进一步”。例如(如果您真的想让这个有争议性),您可以根据 User-Agent 字符串或模块的当前宽度来设置样式。

那么,CSS 的替代方案是什么?

替代方案是内联样式。因此,而不是

我们正在谈论

我还没有听说过有人争论说您应该将这些样式直接应用于您编写的 HTML。这个想法是您通过 JavaScript 将样式应用于元素。

React 推动了许多这样的想法

React 是一个 JavaScript 库,它帮助网站处理视图问题。它主要由 Facebook 开发,非常流行,并且正在获得动力。它拥有自己的会议,甚至发展成为一个用于构建原生应用程序的框架。

它的核心概念之一是“虚拟 DOM”。您直接在 JavaScript 中构建您打算使用的 HTML。乍一看似乎很奇怪,但这种 HTML 和 JavaScript 之间的耦合一直存在,它吸引人们从一开始就将它们一起编写。我最近引用了 Keith J Grant 的话,我再次引用了它

这种耦合是真实的,而且是不可避免的。我们必须将事件监听器绑定到页面上的元素。我们必须从 JavaScript 中更新页面上的元素。我们的代码必须与 DOM 元素进行双向实时交互。

… React 的口号是停止假装 DOM 和控制它的 JavaScript 是独立的关注点。

React 具有内置的管理内联样式的功能。他们称之为它们本来面目:内联样式。以下是一个基本示例

查看 CodePen 上 Chris Coyier (@chriscoyier) 编写的 React 的内联样式

React 使用的虚拟 DOM 也很重要,因为它速度很快。DOM 操作通常被认为在 JavaScript 中很慢,因此通过 DOM 操作管理样式也会很慢。但 React 有魔法粉尘让操作速度变快,因此人们在使用 React 时无需担心速度问题。

Chris Nager 编写的另一个示例

样式创作仍然是抽象的

CSS 是将样式从其他任何东西中抽象出来。实际上是您打开并处理以管理样式的文件。在迁移到基于 JavaScript 的内联样式设置时,您可能不会放弃它。您可能只是使用 style.js 而不是 style.css。您仍然会编写键值对,并在构建过程中将文件合并在一起。

它会有所不同,但创作抽象仍然存在。

内联样式有什么好处?

层叠更少

CSS 令人恐惧的“全局”特性被削弱了。层叠被削减了。我认为您不能说层叠完全消失了,因为某些样式是继承的,因此样式仍然可以传递到子元素,这是一种层叠的定义。但是,这种开发样式的模块化特性可能会导致样式冲突更少。这边的一个模块以这种方式进行样式化,那边的一个模块以那种方式进行样式化——可能不会出现冲突。

所有 JavaScript

我感觉到,有些人就是喜欢并更愿意使用所有 JavaScript。您当然可以将 Node.js 的部分成功归功于这一事实。

动态样式

“状态”在很大程度上是 JavaScript 的关注点。如果您希望/需要样式根据网站上的动态条件(状态)更改,那么将与状态更改相关的样式处理与其他所有内容一起处理可能是有意义的。

最近在 CSS Conf 上的一次演讲幻灯片)中,Colin Megill 使用 Twitter 新推文输入文本区域为例,它是一个动态位置,可以更改其他元素的状态。

谁在实际做这件事?

我听说 Colin Megill 说他们正在“大型项目”中完全不使用 CSS,并且没有发现性能问题。如果我拿到链接,我会更新这里。我听说一个大型项目将在一个月内上线。

我知道 Jed Schmidt 在 优衣库移动版 上工作,你可以看到内联样式在那里起作用。

Jed 的更新:这个版本的网站完全使用 Sass,你看到的内联样式来自于 JavaScript 动画。

Christopher Chedeau 一直在谈论这个,他实际上是 Facebook 的工程师,所以也许 Facebook 也在使用这种方式?

这个概念可以与你知道的 CSS 结合吗?

即使你接受了内联样式的概念,它也能与一些(我必须说出来吗)普通的 CSS 和谐共处吗?页面布局是否适合作为内联样式?基础排版还是有必要全局设置吗?我不确定我们是否已经足够了解这个世界,能看到最佳实践的出现。

在上面 m.uniqlo.com 的示例中,他们也发布了一个 57k 的 CSS 文件,你也可以看到 DOM 中存在基于状态的类(例如 "is-open")。

很多人真的不喜欢这样。

令人惊讶的是!反对这种方法的人比支持的人更多。当我收集关于这个想法的意见时,我对 Lea Verou 说:“有些人真的很喜欢这个想法!”她回答说:

世界上总会有人喜欢吃粪便,但这并不意味着这是一个好主意。

让我们来讨论其他论点。

样式是 CSS 的作用。

这是一个“宗教”角度,可能不会让我们走得太远。

关注点分离是 CSS 的固有特性。

关注点分离是一个非常有用的概念,在构建像网站这样复杂的项目时,它可以使代码更清晰。当你编写 CSS 时,你会自动获得关注点分离:它只是一个用于样式的单独文件。

内联样式在特异性等级中处于最高级。

在 CSS 中保持低特异性意味着,当你确实需要依靠特异性来赢得一场样式战争时,你将拥有它作为工具。当你已经处于最高级时,你就没有这种回旋余地。

!important 声明仍然可以赢得一场针对内联样式的特定属性/值样式战争,但这是一个稍微不同的概念,也是一场更糟糕的战争。

一些简单状态在 CSS 中更容易实现。

如何在内联样式中实现 :hover/:focus/:active?你做不到。你只能模拟它们。那么媒体查询呢?

添加/删除类已经是处理状态变化的完美工具。

JavaScript 在元素上添加/删除/更改类方面非常擅长。而类是处理 CSS 状态的完美方式。

.is-open {
  display: block;
}

此外,你可以更改父元素的状态(通过更改类),从而影响其中许多元素的状态。

.tweet-too-long {
  .tweet-button {
    opacity: 0.5;
  }
  .warning-message {
    display: inline-block;
  }
}

浏览器不是为了以这种方式处理样式而设计的。

例如,内联样式实际上是保存在 DOM 元素上的属性中的数据。DOM 权重是一个问题(它会导致浏览器速度变慢或崩溃)。这些样式信息不仅存储在 style 属性中,而且还以元素的 style 属性的形式在 DOM 中表示。这难道不是同一件事吗?还是说这有点像双重加权的样式?

在…之间是否存在速度差异?

var thing = document.getElementById("thing");
thing.style.width = "100px";
thing.style.height = "100px";
thing.style.backgroundColor = "red";

var thing2 = document.getElementById("thing-2");
thing2.setAttribute("style", "width: 100px; height: 100px; background-color: red;");

是否已经发现了跨浏览器最佳方法?如果这些方法流行起来,浏览器是否需要进化以不同的方式处理它们?

浏览器拥有 CSSOM 这样的概念。我们可以通过 JavaScript 以更智能的方式使用它,而不是使用内联样式?

CSS 的成功是因为它的简洁性。

CSS 很容易上手。很多人知道它。你可以雇用相关人员。它是可移植的。

一些“动态”样式问题可以通过普通的 CSS 解决。

  • 有些演示包括测量宽度并从宽度中减去固定值。CSS 可以使用 calc() 完成此操作。
  • 有些演示包括设置 font-sizeline-height,这些值取决于浏览器宽度或高度。CSS 可以使用视窗单位完成此操作。在这种情况下使用 JavaScript 是过度设计。
  • 有些演示在许多不同的元素上动态更改颜色。CSS 将能够使用原生变量完成此操作。

我们在 1996 年尝试过这个方法,当时它是一个糟糕的想法。

滚出我的草坪。

CSS 是可缓存的。

网络仍然是瓶颈。CSS 文件可以被缓存,这样网络就不再参与进来,速度非常快。

你仍然可以使用 React。

React 非常棒。以下是 David Khourshid 关于在 Sass 中为 React 组件编写样式的文章。Mark Dalgleish 不喜欢 CSS 的全局特性,并且正在开发将选择器本地化的概念。Glen Maddern 在 互操作 CSS 中对此进行了扩展。

难道现在没人关心渐进增强了吗?

这是一个更广泛的讨论,可能在这里不合适。因为网站(包括使用内联样式的基于 React 的网站)可以完全在服务器端渲染,这意味着它们可以在考虑渐进增强的基础上进行。虽然“可以”和“实际鼓励的”是不同的。