html {
font-family: Roboto, sans-serif;
}
除了某些表单元素之外,您刚刚为网站上的所有文本设置了字体!不错!这可能是您想要做的事情,因为网站上可能有数百个元素,每次都设置font-family
会很繁琐且容易出错。
CSS 本质上是全局的。有意为之!
我喜欢 David Khourshid 的说法
您是否曾经停下来想过 为什么 CSS 有全局作用域?也许我们希望使用一致的排版、颜色、大小、间距、布局、过渡等,并使我们的网站和应用程序感觉像一个有凝聚力的整体?
热爱级联,级联是您的朋友。
然而,CSS 的全局性质可能是 CSS 最被人诟病的反功能。有些人真的不喜欢它。我们都知道,编写一条影响整个网站的 CSS 规则很容易,从而破坏了您实际上不想破坏的东西。
两个 CSS 属性走进一家酒吧。
一家完全不同的酒吧里的一把吧凳翻倒了。
— Thomas Fuchs 🎄🕹💾 (@thomasfuchs) 2014 年 7 月 28 日
有 全新的测试类别 来帮助解决这些问题。
作用域样式并不是 CSS-in-JS 工具领域如此受关注和采用的唯一原因,但这是一个重要的原因。有大量的网站根本不直接编写任何 CSS(即使是预处理样式),而是选择 JavaScript 库,在其中样式实际上是在 JavaScript 中编写的。 有一个游乐场 演示了各种选项的语法。这是 styled-components 的工作原理
import React from 'react';
import styled from 'styled-components';
const Container = styled.main`
display: flex;
flex-direction: column;
min-height: 100%;
width: 100%;
background-color: #f6f9fc;
`;
export default function Login() {
return (
<Container>
... Some stuff ....
</Container>
);
}
实际上有数十种选项,每种选项都以稍微不同的方式执行操作,同时提供略微不同的语法和功能。Vue 甚至 提供 了在 .vue 文件中直接作用域的 CSS
<style scoped>
.example {
color: red;
}
</style>
<template>
<div class="example">hi</div>
</template>
不幸的是,<style scoped>
并没有作为原生 Web 平台功能真正实现。但是,有 Shadow DOM,在 Shadow DOM 中,可以将样式块注入模板,并且这些样式将与页面的其他部分隔离
let myElement = document.querySelector('.my-element');
let shadow = myElement.attachShadow({
mode: 'closed'
});
shadow.innerHTML = `
<style>
p {
color: red;
}
</style>
<p>Element with Shadow DOM</p>
`;
没有样式会泄漏到该 Shadow DOM 边界内或外。对于寻求这种隔离的人来说,这很酷,但可能很棘手。您可能需要构建 CSS 以包含可以与 Shadow DOM 化的 Web 组件一起导入的某些全局样式,以便在您的网站中实现一些样式一致性。就我个人而言,我希望可以使 Shadow DOM 单向可渗透:样式可以泄漏进来,但在内部定义的样式不能泄漏出去。
CSS-in-JS 只是作用域样式的一种方式。实际上,存在两种方法。您可以将 CSS-in-JS 称为完全隔离,而您可以直接使用完全抽象来编写 CSS
完全抽象可能来自像 Tachyons 这样的项目,该项目为您提供了一组固定的类名来用于样式(Tailwind 类似于它的可配置版本),或一个编程工具(如 Atomizer),它将专门命名的 HTML 类属性转换为具有其所需内容的样式表。
即使在整个网站中 100% 遵守 BEM,也可以被认为是完全的 CSS 隔离,从而解决了全局作用域可能带来的问题。
就我个人而言,我希望看到我们转向 这种未来
当我们编写样式时,我们总是会做出选择。这是一种全局样式吗?我是有意地将此样式泄漏到整个网站吗?或者,我正在编写特定于此组件的 CSS 吗?CSS 将在这两者之间分成两半。特定于组件的样式将被作用域并与组件捆绑在一起,并在需要时使用。
两全其美,就是这样。
总之,很棘手。
问题不在于 CSS in JS。
而是 CSS 的全局作用域。
解决全局作用域,CSS in JS 就会随之而来。
(我不知道“随之而来”是指消失、完全被接受还是进行重大改革。)
(同样,我也不知道“解决全局作用域”意味着什么。)
— ppk 🇪🇺 (@ppk) 2018 年 11 月 28 日
也许这将成为 2019 年最热门的 CSS 主题。
一位智者曾经在我抱怨 CSS 影响了我不想让它影响的东西时告诉我:“问题不在于 CSS,问题是你对 CSS 不熟练。”他是对的。我想不出 CSS 问题无法通过仔细命名和抽象来解决。
对 CSS 的全局作用域有疑问?然后应用非全局作用域,很简单。想只影响表格中的字体?使用选择器“table”。想只影响表格标题的高度而不影响表格主体中的行?“table>thead>tr”。想控制单个 div 的大小而不影响所有 div 以及 div 内部的 div?使用类。
任何抱怨 CSS 具有全局作用域的人之所以这样做,只是因为他们不知道自己在做什么……
没错。我一定遗漏了什么,因为我不知道大家在吵什么。继承,伙计们。甚至还有一个方便的 * 选择器。
是的。我曾经与一位著名的推特用户争论,他声称“级联是 CSS 的缺陷”。我仍然想知道他认为 CSS 中的“C”代表什么。
当你认为 css-in-js 是解决问题的方案时,我有一个坏消息要告诉你。前端社区应该停止过度设计他们看到的一切,并停止在工具/JavaScript 中寻找不存在的问题的解决方案。
css-in-js 是我近年来见过的最愚蠢的事情之一。问题不在于 CSS,问题在于显示器和椅子之间!
我认为值得看看上面最后三条评论,看看人们对这种想法的态度是多么轻蔑和傲慢。我对此感到好奇。我没有任何使用 CSS-in-JS 的项目,但这并不妨碍我听取人们谈论他们为什么喜欢这种方法。随便说一下……
正如我所说,我的观点是有限的,因为我没有在正在处理的任何网站上积极使用任何 CSS-in-JS 库,但我仍然可以理解潜在的优势。为什么有这种仇恨?是因为地盘保护吗?
关于:Chris
您说得对,没有理由进行仇恨言论,而且这已经真正变成了网络的新宗教战争(我相信您已经写了一篇关于教条主义的文章 ;))。
也就是说,我认为 CSS 方面的人们对 CSS-in-JS 感到恐慌有两个原因
1) CSS 非常强大,它使人们能够以非常优雅的方式一次谈论大量事物。有些人主张使用 CSS-in-JS,仅仅是因为他们不想学习如何控制这种力量,或者是因为语法更熟悉。
2) CSS 纯粹是声明式的。这是它最大的优势之一;它没有状态,如果您知道如何使用它,那么它在规模上会不那么脆弱。图灵完备的语言有更多可能出错的地方,因此能够描述应用程序属性的很大一部分而无需其中一个是一个很大的优势。
此外,人们在 CSS-in-JS 中寻找的一些(真正)优势可以添加到 CSS 本身中。例如,纯函数。我们现在至少有了使用 calc() 的基本表达式,但我没有理由不向语言本身引入无状态函数。总会有需要从 JS 传递数据的情况,但 CSS 自定义属性使从 JS 代码中“发送和忘记”变得更加简单。
当足够多的人推动 CSS-in-JS 时,积极的创新就会转移到那里,并从 CSS 本身转移出去,这很可惜。但这仍然不是对你的同行开发者不友好的理由,但我认为这是偏好变成防御的原因。
在我参与开发过的所有语言/环境中,总会有很大一部分开发者要么没有学习语言/环境中内置的简单解决方案,要么他们觉得它“不够有挑战性”,所以他们使用他们更喜欢的范式重新发明它(通常使用他们从完全不同的语言/环境中带来的范式)。我认为这很好——真正进行重新发明的人通过这样做学到了很多东西。然而,他们通常只是喜欢发布他们发现的东西的人,而且通常开发社区的大量成员像旅鼠一样追随他们,走向越来越复杂的道路。
我认为问题在于,简单的解决方案通常需要很长时间才能找到并学会如何完善,而任何有足够时间的人都可以直接去构建一些满足需求但不够健壮和可维护的东西。如今的 Web 开发生态系统充斥着从不觉得有时间学习到这种程度的人。就在你对某个“本月热门”感到舒适时,你的技能就有可能过时,因为它会被砍掉并被 5 个新框架/库取代,每个库都比上一个更难学习。推荐读物:《猿人与本质》作者:奥尔德斯·赫胥黎
完全同意你的观点
我完全同意 Chris。对我来说,拥有全局样式和局部样式是有意义的。
我一直都是一个精通 CSS 的人,而且从未真正地为 CSS 的全局性而苦恼。我通常使用 ECSS(因为我曾经与 Ben Frain 合作过),而且它一直伴随着我。但是……也许 Ben 会不同意,我可能也有一些遵循不同命名规范的全局类名,这样就可以将它们与局部组件类名区分开来。我通常会创建这些类名来为文本元素设置样式。
这一切都很容易。不知道为什么大家要大惊小怪。
我不是我任何网站上 CSS-in-JS 库的积极用户,但我仍然觉得这会给我们带来好处。这可能是解决很多问题的方案。
我以前说过,现在再说一遍
CSS 没有全局作用域。
说 CSS 规则有全局作用域就像在一个函数中编写一个完整的程序,然后抱怨它里面的所有变量都是“全局的”。如果你的 CSS 是全局的,那是因为你拒绝使用该语言提供的工具。任何“局部 CSS”提案都只是在这些工具之上的一种多余的元机制。
如果你认为 CSS 的“全局作用域”是一个问题,那你对 CSS 的理解不够深。这不是一个问题,只要让那些了解 CSS 的人来做就行了。不要试图为一个不存在的问题想出“解决方案”,让 CSS 比它本应有的复杂得多。
CSS in JS 是为那些不想学习 CSS 而且对网页设计历史一无所知的人准备的。早在 90 年代,我们就有了这种将所有内容放在一个文件中的糊状物。分层关注是一个如此重要的概念是有原因的。
评论中的那种居高临下的态度令人沮丧。这种态度让人感到疲惫不堪。
作为一名拥有 20 多年经验的 Web 开发人员,我几乎使用过与 CSS 相关的每种工具和技术。在过去二十年里,我对 CSS 和 JS 的看法一直出错。重要的是要检查自己的偏见。
我在评论中看到一种精英主义,即“让开,新手,让专家告诉你怎么做”。Web 的成功在于它对每个人的可访问性。HTML、CSS 和 JS 被广泛使用正是因为它们易于编写,尽管它们并不一定容易掌握。当你开始告诉人们,他们应该把 CSS 交给那些已经了解它的人,那么你就会阻碍那些可能成为下一代专家的很多人。
在一家企业中,你必须取得平衡。你会遇到一些精通 CSS 的作者,也会遇到一些不精通 CSS 的作者;实习生、临时工、业务用户等等。原生 CSS 很棒,因为它很容易通过一个小的更改影响整个网站,这也是它最大的摩擦点之一。我们必须学会区分哪些应该有全局影响,哪些不应该有全局影响。
在原生 CSS 中,我们使用命名空间来实现这一点,但即使这样也不完美,需要培训和监督才能正确实现并在长期内维护。OOCSS、BEM 和现在的 CSS-in-JS 都是针对 CSS 根本问题的权宜之计;我们需要一种更简单的方法来对 CSS 进行作用域限定。除此之外,我们还需要更简单的方法来使 CSS 变得动态且跨浏览器兼容。我认为 CSS-in-JS 在这方面有所帮助;我可以动态切换主题,更一致地响应屏幕尺寸和方向变化,根据浏览器调整 CSS 属性,甚至在一个页面内混合主题/品牌以实现组件。当然,使用原生 CSS 以及开发人员和设计师多年来积累的库和模式,也可以实现这些功能,但所需的努力和知识水平要高于 CSS-in-JS。
这些对话中缺少的是对我们 Web 语言需要保持对广泛作者的可访问性的承认。它们应该对专家来说很健壮,对新手来说很容易原谅。这就是平衡之道。
我的观点不是 CSS 应该留给“CSS 专家”,而是每个人都应该学会正确地利用 CSS。
我无法告诉你,有多少其他方面都很出色的程序员告诉我,他们就是不喜欢 CSS,也不想学习,所以每次被迫面对它时,他们都会畏缩不前,然后拼凑出一些代码。程序员讨厌 CSS 已经成为了一种潮流,而且没有充分的理由。但是,当你给它一个机会时,CSS 真的非常棒 (https://css-tricks.cn/css-is-awesome/)。大多数程序员只是拒绝学习。
这不是精英主义;任何程序员都可以学会正确使用 CSS。他们只需要付出一些努力,而不是试图拉低 CSS 来满足他们的舒适区。请记住,那些推动 CSS-in-JS 的人并不是在四处乱搞的业余爱好者;它仍然适用于简单的用例。这些都是已经开始面临扩展问题的专业人士。他们有能力花一些时间扩展自己的技能。
带有 ITCSS 模型的 BEM 命名约定已经涵盖了这个问题。我也完全反对 css in js。感觉像是过去几年中最糟糕的想法之一。关于 Chris 提到的消除未使用的 css 的问题,这可以通过在普通 css 或 sass 中使用后处理器来实现。
我对此有一些额外的想法:https://css-tricks.cn/heres-the-thing-about-unused-css-tools/
我同意 Chris 的观点。Rich Hickey(Clojure 的创建者)曾经在谈到测试、类型系统和其他代码分析工具时说过
“我认为我们身处一个我称之为‘护栏编程’的世界……‘我可以进行更改,因为我有测试!’谁会这样做?谁会开车到处乱撞,撞到护栏上?护栏能帮助你到达目的地吗?”
程序员必须决定她想要让她的 CSS“去往”哪里。这有时会与工具认为哪些规则是无用的发生偏差。这些工具不是你可以把方向盘交到它们手里的东西,它们是用来帮助你做出决定的手段。
在我们工作室,我们不使用未使用的 css 处理器,因为与 Chris 在另一篇文章中提到的可能问题相比,收益非常小。但我认为指出这个功能的存在是有价值的。
不过,重点是你可以通过命名约定和适当的 CSS 结构,轻松地从 CSS 本身内部对 CSS 进行作用域限定。
这不是一个非黑即白的解决方案,我理解一些设计需要高度局部化的模块、对象等。然而,我的感觉是,设计往往先倾向于全局作用域,然后才能从中缩小作用域。
即使 Facebook 本身也遇到了 React 相关的全局蓝色问题。他们可能在代码中使用了数百种变体,这可能是由于 React 的局部化程度过高造成的,而事实上,更全局的 CSS 设置会更有效。我在这里的感觉是,对于像 Facebook 这样快速开发和迭代的大型应用程序来说,将 CSS in JS 局部化可能是避免任何灾难性的样式错误的最佳选择。但是对于我们这些普通人,比如 95% 的人来说,全局 CSS 在使用正确的命名约定和结构的情况下工作得很好。
从某种意义上说,解决 CSS 中全局作用域问题的办法很简单:将一个类附加到你的元素(确保它是唯一的),然后创建一个针对该类的规则集,包含你想要的所有声明(和覆盖)。
每个开发人员都知道这一点。
问题是当开发人员既想要蔑视全局作用域,又想要利用它时,通常是由于他们对“可重用性”的错误追求。
在我看来,CSS 的可重用性被高估了。我并不是说我们永远不应该追求它,但我们应该非常谨慎。例如,只有当我们发现自己实际上在别的地方重用了一个组件时,我们才应该从另一个组件中提取一个单独的“可重用”组件。本质上,我认为我们应该避免过早地进行可重用性,就像我们避免过早优化一样。
Chris 发表了一篇很棒的文章,评论中提出了一些非常有趣的问题。
我可以理解为什么很多人抵制 CSS-in-JS,我也有同感。我有一些顾虑——它在网站构建和维护方面增加了额外的复杂性。我也喜欢在浏览器中调整 CSS 的能力,并且想知道当您迁移到 CSS-in-JS 时,这种能力是否会减弱?也许我错了,我很乐意被纠正。
似乎有一种(在我看来是不公平的)感觉,认为 CSS 只能由来自“设计”背景的人处理,而“程序员”不喜欢 CSS 的工作方式,并且试图在其上强制实施技术,而“CSS/UI 工程师”则对此感到反感,因为这意味着他们必须学习 JavaScript,而并非每个人都对此感到满意。
我倾向于属于“CSS/UI 工程师”类别——了解 CSS 并掌握浏览器如何解释、渲染以及帮助您调试所有这些内容,本身就是一个职业。
看看 2019 年及以后这段时间的发展将非常有趣!
这是我最喜欢 Vue 的做法之一,我为组件特定样式设置了作用域,并为布局和全局样式等内容导入全局 CSS 文件。非常实用。