有些人完全讨厌 CSS-in-JS 的想法。仅仅这个名字就令人反感。坚决反对。样式不属于 JavaScript,它属于 CSS,一个已经存在并且浏览器对其进行了优化的东西。关注点分离。其他任何做法都是可笑的错误,是没能从过去的错误中吸取教训的标志(比如 <font>
标签等等)。
有些人完全喜欢 CSS-in-JS 的想法。模板和功能的同处一地,就像大多数 JavaScript 框架一样,对他们来说已经证明是成功的,所以将样式包裹起来似乎很自然。Vue 的 单文件组件 就是一个典型例子。
(这里有一个视频 关于 CSS-in-JS,是我和 Dustin Schau 一起做的,如果你需要入门的话。)
Brent Jackson 认为你绝对应该学习它,但也提出了一些关于它能做什么和不能做什么的实用观点。
CSS-in-JS 能做什么?
- 允许你用 JavaScript 语法编写 CSS
- 将样式与组件放在一起
- 利用原生 JS 语法特性
- 利用 JS 生态系统中的任何东西
CSS-in-JS *不能*让你不必理解什么
- 样式如何应用到 DOM
- 继承是如何工作的
- CSS 属性是如何工作的
- CSS 布局是如何工作的
CSS-in-JS 并不能免除你学习 CSS 的责任。至少大部分情况下是这样的。
我听说过 很多 关于 CSS-in-JS 的 反对意见,诸如“你们这些人之所以使用 CSS-in-JS 是因为你们不懂 CSS”或者“你们这样做是因为你们害怕级联。我已经知道如何为 CSS 设定作用域了”。我发现这些言论更像是跨过通道的指指点点,并不是特别有用。
Laura buns 有一篇非常棒的两面性文章,标题为 “没有网络的网络”,其中一部分是关于 React 和 CSS-in-JS 的。
我讨厌 React,因为它默认的 CSS-in-JS 方法鼓励你编写完全自包含的一次性组件,而不是尝试将网站 UI 作为一个整体构建。
你不需要仅仅因为使用 React 就使用 CSS-in-JS,但它很流行,这是一个非常有趣且公平的批评。如果你为所有内容设定作用域,是不是会让自己面临更高的不一致性风险?
到目前为止,我一直是 CSS 模块的粉丝,因为它在 CSS-in-JS 中尽可能地轻量级,*只*处理作用域和同处一地,仅此而已。我将其与 Sass 一起使用,这样我们就可以访问帮助保持一致性的 mixin 和变量,但我可以理解它如何可能导致过于依赖一次性组件的危险境地。
然而,它们将是一次性的可丢弃组件。可代码分割的一次性组件。一切都在平衡中存在。
Laura 接着说她喜欢 CSS-in-JS 方法提供的一些强大功能和灵活性。
我喜欢 CSS-in-JS 的方式,它提供了足够的抽象,让你仍然可以使用像盲目猫头鹰选择器这样的技巧,同时也能让你充分利用 JS 的强大功能来做一些事情,比如容器查询。
Martin Hofmann 创建了一个比较 BEM 和 Emotion 的网站,它查看了一个小的“警报”组件。我喜欢它是一个没有感情(字面意思,不是指库)的比较,它查看了语法。BEM 有一些优势,尤其是不需要任何工具并且可以轻松地共享到任何 Web 项目中。但 Emotion 的方法在许多方面都更简洁,并且看起来更容易处理。

我希望看到更多关于这些技术的没有感情的比较。选项 A 在这三件事上做得很好,但在那里和那里很痛苦,而选项 B 在其他事情上做得很好,并解决了其他一些痛点。
我们最近 链接了 Scott Jehl 的文章,该文章探讨了异步加载 CSS 的问题。Scott 的开场白是
为了提高页面性能和弹性,我们可以做的最有影响力的事情之一就是以一种不会延迟页面渲染的方式加载 CSS。
值得注意的是,全面的 CSS-in-JS 方法可以自然地获得这种能力,因为样式被捆绑到 JavaScript 中。它是以成本为代价捆绑的。对性能的成本。但是,如果我们消除了其他阻塞渲染的事情,我们就可以收回一些成本。这很有趣,至少值得更多的数据。
我可能会因为这个被痛批,但我对试图将 CSS-in-JS 归咎于提高行业入门门槛的讨论不太感兴趣。这是一个需要认真考虑的大问题,但我们并不是在谈论关闭 CSS 并强迫每个人使用其他语言。我们谈论的是针对特定类型项目和特定规模的利基库。
我认为,如果你… 那么值得看看 CSS-in-JS 的想法。
- 无论如何,你都在处理一个组件繁重的 JavaScript 项目。
- 你已经在将模板、功能和数据查询放在一起。
- 你认为你可以在不损害用户体验的情况下利用它,比如在其他地方获得速度提升。
- 你的团队对所需的技术感到满意,也就是说,你没有排斥人才。
Max Stoiber 是一个毫不掩饰的粉丝。他在这个主题上的文章 谈到了这种风格给他带来的信心以及他节省查找所需内容的时间,这两件事我发现都是真的。但他也认为这种方法专门针对 JavaScript 框架应用程序。
如果你正在使用 JavaScript 框架构建一个带有组件的 Web 应用程序,那么 CSS-in-JS 可能是一个不错的选择。特别是如果你所在的团队中的每个人都理解基本的 JavaScript。
我很想在评论中听到你们的看法。你是否已经想通了所有这些问题?疯狂地爱着?咬牙切齿地讨厌?我非常有兴趣听到真实项目中的成功案例或失败案例。
我个人对此完全没有偏见,另一方面,我认为这是一个好主意,因为它带来了大量新的机会。
更喜欢普通的 CSS,因为它更简单。
如果任何大型组织选择使用 CSS-in-JS,然后有一天决定回到普通的 CSS。提取或重写 CSS 的过程似乎非常困难。这类不可逆的决策很难做出。
实际上这是一个很好的观点,我以前从未这样想过。
那不是问题。有多少大型组织从 LAMP 架构迁移到 React 之类的架构,然后又想回到 LAMP?我参与过的网站每 4 到 7 年就会从一个平台迁移到另一个平台。
@ Rocky Kev
如果不想进行完全重写,这是一个问题。如果你从 LAMP 迁移到 React,你*希望*进行重写。
但是如果你想切换逻辑而不重写 CSS,你也被迫重写(移植)它。
我对此有一些想法。
我能想到的关于 css-in-js 最好的论点是:关注点分离并不一定意味着语言分离。所以关注点分离也可以理解为支持 css-in-js 的论点。我在 React 中感受到了这种组件化方法带来的乐趣。
我的另一个想法是,我仍然认为只有在必要时才使用 JS 非常重要。始终要质疑是否必须使用它,并始终尝试构建不依赖于 js 的网站。就像当年的 Flash 一样。
我心中记着网站消耗的资源。不仅是流量,还有电力。与 10 年前相比,网站的平均大小增加了 10 倍,我担心 JS 框架过于频繁地被用来简化开发人员的工作,而没有为用户带来很多好处,反而不必要地增加了网站的体积。
所以问题可能是:哪种技术真正有助于事业发展,哪种技术只是在安慰开发人员,甚至可能在没有必要的情况下给用户带来成本?
“我担心 JS 框架过于频繁地被用来简化开发人员的工作,而没有为用户带来很多好处,反而不必要地增加了网站的体积。”
你并不是唯一有这种担忧的人。人们过于关注简化产品构建的工具。但这与构建更好的产品并不相同。
我希望更多工程师/开发人员能够接受的两件事
1) 仅仅因为你可以,并不意味着你应该。
2) 少即是多。
工具不是万能药。更多和更快≠更好的产品。不幸的是,这似乎不是业界愿意承认的事情。
目前这种将关注点分离的原因曲解为 CSS、JS 和 HTML 是不同的语言的说法是如此倒退。它们之所以是不同的语言,是因为它们是不同的关注点。这些关注点受益于分离,因为它们经常独立于彼此发生变化,并且可以也应该由不同类型的开发人员进行贡献。
存在水平和垂直关注点。仅垂直切分将与仅水平切分一样多地存在缺点。
不用谢,使用BEM约定作为SCSS就很好,Material UI就是我强烈不喜欢CSS in JS的一个完美例子
我绝对欣赏这种公正的看法。人们应该可以使用使他们高效的工具。对CSSinJS的想法存在很多敌意,而且很多时候感觉像是门禁,在我看来,这损害了社区,而不是帮助它。
我不一定对CSS以Javascript形式交付的概念有异议,但我确实不喜欢许多改变你与语言交互方式的实现。
我唯一喜欢的CSS-in-JS是Vue的实现,因为它在编写样式时仍然分离了关注点。
另一方面,我是一名前端的前端开发人员,正在向更全面的前端职位发展,所以当我看到有人修改我的CSS格式时,我会感到不安。
我喜欢CSS-in-JS只包含必要的“声明”。;)
“值得注意的是,全面的CSS-in-JS方法自然地获得了这种能力,因为样式被捆绑到JavaScript中。它是以代价为代价捆绑的。性能的代价。但如果我们正在消除其他阻塞渲染的内容,我们就会部分收回这部分成本。”
是的,部分。但这些部分也带有一个非常重要的IF。也就是说,如果有人关心性能(阅读:有时间、预算和领导层的优先级)。
CSS-in-JS在我看来一直是办公室政治的现代科技版本。它赋予工程师/开发人员更多(集中化)的控制权,而不在核心圈子内的人则控制权较少。这是领导层/管理层无法基于(传统)标记+CSS+JS进行管理建设的廉价且肮脏的代理。这项技术很好。也许并不完美,但任何东西都不是完美的。但它确实需要合作与协作。CSS-in-JS旨在减轻这种摩擦,但产生了其他问题。
人和权衡。它总是归结为人与权衡。
CSS in JS是一种暴行,任何认为它是个好主意的人应该立即被直升机运送到海里,然后毫不客气地扔进去。它没有解决它声称要解决的任何问题,阻碍了DRY代码的编写,并增加了开发过程的不必要的复杂性。
我们组织使用基于Material UI的组件库。我们去年需要完成的一项任务是在Ember应用程序中应用此组件库中使用的新的企业样式。我们花了10个人8个月的时间才完成了一些事情,如果制作组件库的团队抵制了这种荒谬的潮流并编写了一些可移植的东西,那将是一项复制粘贴的工作。
我现在已经加入了一个直接使用组件库的新团队。为什么我们需要将我们的应用程序包装在一个ThemeProvider组件中,然后将我的每个单独组件包装在一个withStyles高阶组件中,而一个简单的导入语句就可以完成?为什么我们在单元测试中遇到javascript错误,因为我们没有为每个测试设置所有这些东西?为什么每次样式更改时,livereload都会进行全页刷新?我们现在究竟能够做些什么,才能使这种努力的权衡变得值得?
任何认为CSS in JS是个好主意的人都应该狠狠地打一巴掌,它的替代品越快出现越好。
写出来感觉真好——感谢你给我一个平台让我把这些话说出来
Jonathan,css-in-js与这有什么关系?
似乎你使用了高阶组件和装饰器来管理样式,这并不是css-in-js的常用方法。
请详细说明
也许这应该放到一篇关于Material UI的文章中,而不是关于一般的CSS-in-JS。我一直在挑剔Material UI,因为我们不得不使用它,而且它也是CSS-in-JS的一个流行实现。
但是,即使没有Material UI,在样式方面仍然需要全局样式来处理字体、调色板、链接样式、网格布局等。你仍然希望尽可能避免重复,因此可能希望使用混合或辅助类来避免这种情况(例如,flex-column混合/辅助类)。
为了在CSS-in-JS中应用这些东西,你的选择是
1. 不断重复自己。并希望你使用的企业红色阴影永远不会改变。
2. 使用提供者和/或高阶组件,这会导致我的原始帖子中提到的所有问题
3. 你可以将这些添加到一种globalStyles.js文件中,你将其导入到所有组件中(或者如果你这样做的话,可能是component style.js文件),这仍然比简单地将它们导入到样式表的顶部并让它们级联更费力。如果计划不当,这仍然可能导致需要覆盖样式,这显然是CSS-in-JS通过其疯狂的组件特定作用域级别试图解决的问题之一。
4. 只使用CSS(或SCSS或任何你喜欢的预处理器)。
就我个人而言,我选择选项4,因为对于任何其他选项,你都可以使用CSS,并且你也可以将你的样式移植到其他项目中。
这只是Emotion或Styled Components等流行的运行时CSS-in-JS的问题。
有一些零运行时CSS-in-JS解决方案,它使用Babel将CSS从JS提取到静态CSS文件中,并将此静态CSS文件用作CSS模块。完美的性能,与所有CSS工具兼容,同时将CSS保留在同一个JS组件文件中。
https://github.com/4Catalyzer/astroturf
https://github.com/callstack/linaria
https://github.com/lttb/reshadow
我不喜欢css in js。需要在css中插入某种标签来提取组件所需的css。
我认为,对我来说,我提出的第一个论点是它可能产生的进入门槛。具体来说,在设计师变得越来越技术化,并且出现了“UX工程师”类型角色的时代,许多这些设计师已经非常擅长基本的HTML/CSS操作和创作。许多人转向了Sass(像我一样),并且发现能够拥有这种控制和自主权非常令人耳目一新。然后你还有BEM、SMACSS或SuitCSS等下一级别的组织……这些使得组织你的样式并在层次结构中构建它们变得很容易,并且你的组织或产品定义了清晰的(希望如此)规则。
当你向可能不太习惯在例如基于React的系统中工作的人员引入JS这个变量时,你就会引入一些风险。我遇到过这样的情况,有人在我们应用中工作,他不了解JS语法,并且花了几个小时试图让某些东西工作。另一个案例是,有人在它发布到生产环境后最终破坏了一些东西……所以存在固有的风险。
每个人都应该乐于学习,但强迫使用其中一个不是答案。我认为链接样式表仍然是最佳选择,尤其是在设置可以构建Sass或Less或Stylus的环境更容易的情况下,但CSS-in-JS绝对有一些优点……最值得注意的是与JS一起直接操作。我发现这很有用,例如,执行可能对组件更琐碎或更具体的特定状态的事情,而不是将它们写入我的Sass库中。
我有点同意上面Jonathan Steven的评论,但我比一年前更开放地接受这个想法……但仍然非常犹豫是否要直接将CSS-in-JS作为首选或唯一选择。我希望许多团队停止直接跳入其中,原因与他列出的相同。如果你决定进行更大的更改甚至一些更简单的更改,你将在未来给自己设置障碍。至少使用Sass库,我们拥有导入的功能,并且可以更容易地封装组件和布局(对我来说)。
我对JS比较陌生,一开始我非常喜欢CSS-in-
JS的想法。随着我使用和学习的越多,我正在远离如此多的CSS in JS源代码。我认为在全局CSS/SCSS中采用默认的更好方法,并且可能在JS中进行少量稀疏的调整。但它也可能取决于项目,并为项目的范围选择合适的工具。
@Chuck Smith 基本上这就是我所指的。确实应该有一个全局级别的控制,然后如果你需要在组件级别进行特殊调整,那么CSS-in-JS就有意义了。尤其是在管理状态级别的事情时,这样你可能不必操作DOM来更改或添加修饰符类。
为什么不两者都用呢?
在原生CSS中为UI本身建立一个包含已建立的全局变量、实用程序和默认值的的设计系统,然后为状态管理的UI更改扩展CSS-in-JS,从而在用户无法加载JS或将其关闭时实现优雅降级。此外,如果你出于任何原因必须将CSS与JS分离,它不会变成非常沉重的技术债务,而只是将这些样式转移回设计系统的生态系统中。
一个很棒的方法。换句话说:当然,将等效于“用户代理”样式构建到组件中并将其紧密耦合有很多价值。
我并不认为 Vue 或 Svelte 的单文件组件样式作用域真正属于 CSS-in-JS。当然,它在幕后运行,但它只处理作用域问题,并且不阻止你使用 SCSS 或 Stylus(就像 CSS Modules 一样),而且它为主要了解 HTML 和 CSS 的设计师和其他人员提供了更低的入门门槛。
我认为 CSS-in-JS 一个鲜为人知的问题是,据我所知,用它来干净利落地管理大规模设计系统更加困难。当然,可以做到很好且干净,但它增加了在项目中正确工作和为正在使用的任何 CSS-in-JS 框架和方法组合编写文档所需的知识层面。这不可避免地会导致更多复杂性,以及人们偏离一致性或最佳实践方法。
入门门槛部分比我们给予的重视程度更大。有些人专门学习可访问、高性能且经过深思熟虑的 HTML 和 CSS,他们不应该为了参与大型 Web 应用程序而需要学习 JS。尤其是在我们拥有比 React 更好更新的框架(如 Vue 或 Svelte)的情况下。
这就是我提到入门门槛的原因。我知道你现在很喜欢 Svelte,但 Vue 也有同样的想法,你可以更好地将这两个问题分开,并使事情更…怎么说呢,更正规一些。你关于大规模系统的观点是我不喜欢将 CSS-in-JS 作为唯一解决方案的首要原因。再说一遍……它有其优点,但我认为缺点远大于优点。与预处理和编译或原生 CSS 相比。
CSS-in-JS 的成本难道不是将任何可重用的 CSS 组件化到 JS 中,从而导致需要下载更多的 JS 吗?
@Sergey CSS-in-JS 的讽刺之处就在于此……也是我在考虑 CSS-in-JS 核心思想作为性能提升时一直在思考的事情之一。
完全同意。尤其是你关于 Vue 的单文件组件 *不* 属于 CSS-in-JS 的观点,至少就“开发者体验”而言是如此!
直到最近,我还没有使用 CSS-in-JS 的需求。我使用 Vue.js 的单文件组件及其 CSS 模块。
但最近我需要计算一些值,所以我需要构建一个样式对象。当我需要为伪元素设置样式并需要使用媒体查询时,就碰壁了。据我所知,这两者都不可能实现。
所以这又加剧了不一致的问题。
我确实看到了 CSS-in-JS 的优势。
我现在的问题是我需要学习 Javascript 和 React 才能使用它。
希望它能提高网站性能和工作效率。
通常我必须访问一个网站,每次更新网页时都要手动创建关键路径样式。
我听说 CSS-in-JS 和/或 React 可以解决这个问题。
感谢这篇文章,读起来很不错。
CSS-in-JS 似乎在 React 领域最流行,所以这很公平,但所有主要参与者(例如 Emotion)至少声称自己是框架无关的,或者有适用于其他框架的版本。
但如果它类似于 Storybook 如何与多个框架一起工作,那么在核心上,设计思路就像一个 React 应用程序和一个 React 开发人员。
CSS-in-JS 的存在似乎是因为 React 没有开箱即用的方法在 JSX 文件中添加 CSS。我花了很长时间才意识到这一点。来自 Vue.js,在那里单文件组件也可以将 CSS 作为一等公民包含进来,CSS-in-JS 的分裂似乎是一个暂时的现象,它将持续到 React 存在的那一天。谁知道,那会持续多久。
老实说,这真的关乎选择合适的工具来完成工作。简单的原生 CSS 是你能做出的最棒、最优的选择。没有什么比它更快、更优化、更可控了。其他任何东西都或多或少是一种权衡。
处理器——为你提供了一些维护功能,但你失去了效率感,并获得了一系列问题,例如需要构建更改、额外处理、陷入 XXXL 选择器地狱等等。
CSS-in-JS——SSR 渲染存在问题,优化绘制存在问题,代码重复本身就是一个问题,样式一致性等等。另一方面,大型团队在较长时间内可以快速迭代,一旦你将组件的所有代码放在一个地方,维护就更容易了,等等。
我有点晚才加入讨论,但我只是想为 CSS-in-JS 的缺点再补充几点,在我看来,对于大多数项目来说,它的缺点太多了。如果你想将 JS 作为预处理器,没问题,尽管使用,但作为需要通过互联网下载的运行时,它是一种反模式。
我很高兴你提到了有限的分布。但恕我直言,这是反对 CSS-in-JS 的根本原因。到目前为止,还没有达成使用特定库的共识。因此,即使“每个人”都开始使用它们,CSS 的可重用性也很糟糕。在原型设计时尤其糟糕。有时我只是想在屏幕上粘贴一个看起来不错的表单!
我实际上会从 CSS 方面删除“更多代码”,并将其替换为 JS。SASS/POSTCSS/LESS 不是运行时,但它们可以解决大多数代码重复和消除问题。CSS-in-JS 在这里唯一获胜的领域是延迟加载。但这现在很容易使用外部 CSS 和 Webpack(我假设 Rollup/其他工具也可以)。
将“更多代码”“添加到”CSS-in-JS 的原因是,浏览器必须下载并解析完整的 Javascript(它将大得多)才能呈现任何内容。如果你有一个只有一个名为“root”的 div 的原生 SPA,那无关紧要,但如果你正确地做了,并且拥有同构或静态(Gatsby 等)初始渲染,那么你的页面将使用传统的 CSS 显示得更快。这是因为它只需要下载 html 和 css(更少的代码和解析时间)来显示视图。
命名空间代码也属于传统 CSS 列,因为有 CSS 模块。对 Chris 表示应有的尊重,我知道他希望在各方之间成为调解人,并有正当理由试图包容,但现在是 2019 年,这个论点已经失去了所有的分量。你可能会说它不是开箱即用的,但那么 CSS-in-JS 超出 style 标签之外能做到吗?
没有提到浏览器缓存(没有复杂的 service worker 设置)和 HTTP2。标准 CSS 从一开始(CSS 出现的时候)就开箱即用地支持了这些功能。单独的 CSS 也更好地与 HTTP2 和并行请求配合使用。
缺乏约定。这是另一个大问题。因为每个库都有不同的约定/语法。我见过的多数项目都是 CSS 与应用程序逻辑混合在一起的混乱局面。有些人习惯了这种情况,并说“这是一种耳目一新的体验”。这些人是谁,他们写过多少 CSS?还有什么比在屏幕上将 CSS 文件放在右侧,应用程序放在左侧更简单呢?
最后但并非最不重要的是,“HTML-in-JS”作为组件视觉方面的主要载体带来的姊妹问题。我们是否忘记了 CSS 已经有组件了?没错,组件是内置在 CSS 中的。这是一个例子
为什么这种编写 CSS 类的方式不受欢迎了?害怕级联和任何全局变量。作为软件工程师,从一开始你就被教导并偏向于尽可能地最小化全局变量。但作为一个从在 QuarkXpress、Pagemaker 和 Indesign 中设计杂志和目录开始的人(每个产品的品牌和风格都非常独特),我很清楚为什么 CSS 的设计方式如此。
这是否意味着来自软件工程师(其专业知识可能不是设计)的一些新想法没有价值?当然有价值,他们提出的许多问题都是合理的。但我们需要动脑筋,学习好的部分,而不仅仅是让自己开始使用和宣扬任何时髦的新事物。别忘了,Web 社区中一些最受尊敬的人往往是大公司软件工程师,因此声音更大。不幸的是,我们没有足够像 Jen Simmons 或 Rachel Andrews 这样在创意方面有影响力的人来平衡这一点,因此我们需要思考并勤奋(是的,先尝试一下)我们选择接受的东西。
对我来说,这就是我期望从那些没有资格编写一行 HTML 的人那里获得的那种思维狭隘。如果这听起来很苛刻,我表示歉意,但这叫做关注点分离。HTML 用于描述事物 *是什么*——语义上、语法上——CSS 用于描述事物 *看起来像什么*。而 JavaScript?那是为了增强一个已经正常工作的页面。至少对于任何正常的以内容为中心的网站来说都是如此。
但是,那些从未接受语义的人,认为在他们的页面中塞入无数的表示类(参见“bootcrap”)没有任何问题,从如此高的地方向缓存模型撒尿,以至于你会认为全能的上帝刚从一个狂欢派对回来,并且总体上未能理解或接受 HTML 和 CSS 创建的原因或它们存在的目的!
这与你 99% 的时间看到 style="" 和 100% 的时间看到 的情况没有什么不同,你真正看到的是开发人员的无知、不称职和无能。这与你看到人们从 H5 开始弄乱页面,或者使用 innerHTML,或者任何其他“好吧,去你的好实践”的胡言乱语没有什么不同,这些胡言乱语似乎是那些无知的骗子的看家本领,他们用“JS 什么都不做,你的脚本免费”来招摇撞骗。
那不是工作,那不是你应该怎么做。
尽管你的评论非常粗鲁,但我仍然很高兴版主们允许它存在,因为我坚信言论自由(至少在它没有欺凌整个群体或某些希望停止的人之前,否则请把我排除在外)。
.
如果你真的想回复我的评论(你的表达方式几乎无法理解,除了提到 CSS 组件之外,没有回应我的任何观点),你竟然认为我经验不足,这很有趣。虽然我“起步”于平面设计师,但我从 1997 年就开始编写网站代码了,朋友!那可是在 CSS 出现之前,那时候用的是 HTML 3、Netscape Navigator、CGI、ASP(最初版本),然后是 PHP、jQuery/原生 JS,一直到现在的 React、Angular、后端、前端、运维等等。我是一名全栈开发者,曾构建并参与过许多高流量产品的开发,从初创公司到大型企业都有。最重要的是,我从未停止关注变化和新想法。不是自吹自擂,但我认为自己至少有资格对这个话题发表意见。
听一听吧,如果你愿意;不愿意也没关系。但如果你想要引起我的注意,至少你得为我所说的内容提供一个理性的论证,无论是赞成还是反对。我看到的只是,似乎有人心情不好,觉得语义类是邪恶的化身……却连为什么都不肯说明。我没有看到任何反驳目前 css-in-js 库和惯例混乱现状的内容,也没有看到任何关于浏览器构建和优化以支持外部 CSS 文件(以及目前)性能更好的内容,最重要的是,没有看到任何积极的论点来支持 css-in-js 相比于经过优化的传统 CSS 架构和现代工作流程(例如 CSS Modules、预处理等)的任何优势。只是说 Bootstrap 不好(在我看来,Bootstrap 以一种过于宽泛的方式使用了我在文中描述的 CSS 类模式,导致与特定 HTML 嵌套过度的耦合)。
代码混乱,使用更长、更繁琐的过程来模拟它应该做什么,更高的财务和技能成本,仅仅因为你可以这样做,即使你永远不会编写文档,只是期望每个人都能立即知道如何使用它?算我一个!
JS 已经变成了那句谚语中的锤子,而开发者则把所有东西都看成钉子。
我想指出的一件事是未来的兼容性。
使用 CSS,你永远不必担心更新库或担心重大更改。
我们最初发布时使用了 styled components,随着时间的推移,他们发布了几个更新。其中一些是重大更改。更新和改进库本身没有错,但归根结底这是一种成本。
我们最终做了什么?我们将遗留组件保留在 styled-components 中,而新组件则使用普通的 CSS。我们将慢慢地恢复 CSS 并完全摆脱 styled-components。因为新开发人员需要时间才能熟练使用它(他们觉得它很烦人),而这对于我们这样已经有很多任务在身的初创公司来说,是我们真正不想承担的成本。
我个人喜欢 CSS-in-JS 的理念,但话又说回来,萝卜青菜各有所爱。
CSS-in-JS 可能是好主意,因为它可以消除渲染阻塞,但无论如何,编码都不会容易。
我对 CSS-in-JS 的主要问题是,人们很容易将组件的所有 CSS 都放在该组件中。不久前,我们不得不进行重构,因为网站的创建者决定将字体颜色和大小锁定在组件中,而客户需要在网站的其他地方使用该组件的副本,并且需要不同的颜色和字体大小。
之后,客户决定稍微更改一下整体字体大小,我们不得不对所有组件都执行相同的操作。
所以,不,CSS-in-JS 既不好也不坏,它需要出于某种原因而实现,而这个原因永远不能是“它很流行”或诸如“大公司就是这样做的”之类的废话。
根据我的经验,使用 CSS-in-JS 并不妨碍你“将网站 UI 作为一个整体构建”。举个例子,在过去的两年里,我们一直在将基于 CSS 模块的组件迁移到使用 Styled Components。许多这些组件在整个应用程序中使用(以及在其他应用程序中)。它已经实现了 1 对 1 的转换,并且能够消除处理条件 UI 逻辑所需的 className 绑定。
至于毫无根据的论点“……人们使用 CSS-in-JS 是因为你不懂 CSS”,CSS-in-JS 在浏览器中渲染 CSS,这需要……至少从我看来,需要理解 CSS。 :)
话虽如此,CSS 模块对于处理全局样式以及可能无法处理复杂 UI 交互的高级组件和包装器仍然非常出色。
在过去的 4 年里,我一直在使用 CSS-in-JS,而且,我在我工作的大多数应用程序中都使用了 React、Vue 和 Angular(即 JavaScript 框架)。我承认,我对使用 React 的美好体验以及社区为此提供的可用和流行的实践有偏见。
CSS-in-JS 彻底改变了我。它实际上并没有破坏任何样式范式,真正的益处更多地体现在跨组件的样式结构和分离方面,这就是 styled-components 或 emotion 的用途,它在任何应用程序中构建文件夹/组件结构时确实很有帮助。
我也想说 Vue 不是 CSS-in-JS。在使用 Vue 单文件组件时,唯一类似于 CSS-in-JS 的事情是,你没有全局样式表,并且它在后台获得了作用域(如果你愿意)——除此之外,你使用常规 CSS 语法和熟悉的嵌套语法等(当使用 SASS 或 LESS 时)。
在研究这个主题时,我也看到了 CSSinJS 的潜力和优势。我想我最初的挫败感来自于 material-ui 要求你在组件中覆盖样式的方式。在用这种方式编写了一周的样式后,它仍然让我感到恼火……
好吧,我同意并非所有网站开发人员都以此为生,而是出于家庭原因/或小型俱乐部等原因帮助其他人编写网站。
因此,我同意我没有时间学习 JavaScript,但对 JavaScript 库没有问题,它们可以帮助某些领域。
Brianran
好文章!
来自传统的 CSS/Sass 背景;一旦我开始使用 React,通过 styled components 使用 CSS-in-JS 的方式对我来说就非常有意义。我真的很喜欢所有内容都在组件内本地化,并且可以根据需要轻松移动。我曾经 100% 反对将样式与功能混合,但,人都会改变。
也就是说,一旦组件开始增长,它可能会变得有点混乱。但在那一点上,我认为组件试图完成的任务太多了,我会将其重构为更专注的组件。
我仍在摸索我将采用的“完美”的 React 样式方法,但目前我对 CSS-in-JS 很满意。
此外,这是我在第一个想法之上的另一个想法。
Jen Simmons 提到了关于 CSS-in-JS 的一些内容,我想更进一步。CSS 是“层叠样式表”,但当你以 CSS-in-JS 的方式使用它时,就不再有“样式表”了。你基本上是在内联所有内容,并且不再像基于预处理器的方案或记录良好的 CSS 库那样具有层次结构的概念。但问题在于:这种方法很可能没有中心库。你可以创建一个,但我真的不确定这种方法是否真的可以被称为“CSS”,因为没有级联……我想也没有真正的表。
对此有何看法?
同意,特异性完全消失了。使用 Vue,我可以通过简单地使用特异性来覆盖 UI 框架组件样式。使用 React 和 Styletron,我必须希望开发人员公开了足够的 API 来覆盖样式。
如果你担心作用域,只需编写嵌套的 scss 即可。问题解决。
顺便说一句,css-in-js 并不能让你免于编写干净的代码。
在我看来,这像是 js 开发人员不想费心学习 css 的一个借口。
级联的优势远大于组件方法的特异性。
(像往常一样,某件事的最大优势往往也是其最大的弱点)。
但是你需要对 css 有相当的了解才能正确使用它。
所以我的问题是,js 开发人员应该学习 css 吗?
我同意你的观点,这似乎是 JS 开发人员接管另一件事的方式,而他们的语言不需要这样做,从而避免学习另一种语言。
我在 React 中使用 CSS Modules,但我喜欢 CSS-in-JS 在 Vue 等单文件组件中的概念,我将在我的下一个项目中使用 emotion。
我对 CSS-in-JS 的观点是,如果你有一个非常庞大的模块化应用程序,包含数百个组件,那么共享 .css/scss 文件将成为技术债务,因为如果 css 架构没有得到正确组织,则很难丢弃未使用的 css。
使用 CSS-in-JS,如果你重构你的应用程序或丢弃整个功能,整个 CSS 都会随之无痛地消失,从而减小包大小并防止出现问题。
对于我这种面向 React 和 Storybook 的思维方式来说,CSS-in-JS 感觉非常合适。我最初是通过 JSS 了解到这个概念的,styled-components 是一种介于两者之间的方案。我还没有尝试过 Emotion。但所有这些库都是为组件世界创建的,如果你没有使用 React/Vue 或任何这些库来创建应用程序,那么你可能不需要 CSS-in-JS。
由于组件库的构建大多为此目的,因此问题在于我们是否应该将组件样式封装在一个组件文件中,或者允许将其分成两部分——一部分在 JS 文件夹中,另一部分在 CSS 文件夹中。
关于可维护性的担忧似乎更像是主题问题,而不是组件功能的样式问题。在样式组织方面,我特别注意将主题和组件功能样式分开。例如,Semantic UI 坚持不对主题进行任何风格上的意见,并将主题保持为一个完全独立的事物。同样,广受欢迎的 Bootstrap 和其他框架也是如此。由此可以得出结论,某些样式规则可能与组件的核心相关,不会因主题而改变,而某些样式规则可能会因主题而改变。
那些不会改变的规则可以放在同一个组件文件中,一个组件一个文件。这样一来,主题文件仍然保持分离,因为它们应该如此。我不想为了更改一件事情而需要去两个地方——Redux 已经给我留下了阴影,不!
更重要的区别在于,什么时候某些东西算作“主题”,什么时候不算。现在这需要一些实践和智慧,我希望有人能直接灌输到我的脑子里,而这正是混乱的根源。
但说实话,如果我们在一个无法区分形式与功能的项目中,或者产品尚未成熟到能够看到这种区别,或者样式就是功能,那么任何过度工程都会阻碍项目的进展。“过度工程”在这种情况下对我来说就是回到 SASS 或 LESS 的时代,为单个组件保留两个独立的目录树,而对其他人来说,“过度工程”可能意味着交付产品不需要的新技术。
为什么不能同时使用 css 和 js 中的 css 呢?我使用一个自制的实用程序类库来为我的大多数网站进行样式设置。但是容器查询在 js 中效果更好,所以当实用程序库没有相应的实用程序并且该功能不够通用以至于不值得添加到库中时,我就会使用 js 中的 css 来解决问题。虽然我非常喜欢纯 css,但这并不意味着我们必须二选一。
我认为 CSS-in-js 在基于组件的架构中有一定的地位,它有优缺点。您只需要选择合适的工具来完成工作即可。我认为围绕某些 CSS-in-js 解决方案存在一定程度的炒作,人们使用它们试图解决他们并不存在的问题。
但是,我认为围绕扩展性和代码重用的大多数缺点都可以解决并轻松实现,例如使用预处理、mixin、组件重用、全局实用程序类等。
当然,这是否会在实际开发中实现,以及开发人员是否真的会利用它并避免代码重复是一个不同的问题,尽管对于大型 BEM 代码库来说也是如此。
此外,如果有人感兴趣,我在 kialo 上发起了一个投票,对于标题有点哗众取宠,抱歉…
kialo.com/css-in-js-is-a-great-idea-29721