Install ExtensionApp Store

Ecosystem World Tour • CSS for JavaScript Developers

(Optional lesson)(选修课)

When it comes to writing CSS in a modern JS application, there are a lot of options!
当谈到在现代JS应用程序中编写CSS时,有很多选择!

In this course, we'll use styled-components. I chose this option for a few reasons:
在本课程中,我们将使用styled-components。我选择这个选项有几个原因:

  • It encourages good habits, and solves whole classes of CSS problems for us, like scoping and specificity.
  • It's a very popular tool! styled-components + React is likely the most common combo when it comes to styling in modern JS applications.
    这是一个非常流行的工具!当涉及到现代JS应用程序的样式时,styled-components + React可能是最常见的组合。
  • I have a lot of experience, both using it and teaching it.
    我有很多经验,既使用它,也教它。

In my own career, I've used many different CSS preprocessors and frameworks, and I considered many options for this course. In this optional lesson, we'll look at some of the other solutions out there, and talk about their pros and cons.
在我自己的职业生涯中,我使用过许多不同的CSS预处理器和框架,我为本课程考虑了许多选择。在这个选修课中,我们将看看其他一些解决方案,并谈谈它们的优点和缺点。

An important bit of context: these are my opinions. They're not “hot takes” — I've worked with each of the tools mentioned in this list, and my opinions are based on real-world experience — but they also aren't objective or universal. Lots of very smart and experienced developers will likely disagree with me, that's just the way it goes.
一个重要的背景:这些是我的观点。它们不是 "热议"--我与这个列表中提到的每一个工具都有过合作,我的意见是基于现实世界的经验--但它们也不是客观或普遍的。很多非常聪明和有经验的开发者可能会不同意我的观点,这就是事情的真相。

Vanilla CSS

Pros:优点:

  • No tooling means less complexity, no runtime performance costs
    没有工具意味着更少的复杂性,没有运行时的性能成本
  • Modern CSS features like 现代CSS功能,如 make certain tooling features (eg. Sass variables) redundant
    使某些工具特性(如Sass变量)成为多余。

Cons:弊端:

  • Global and unscoped. The CSS you write in one place will be applied everywhere. Using a naming convention like BEM can help, but it's high-friction and prone to failure at scale: naming collisions are still possible, and it requires enormous dedication and willpower to stay 100% consistent with it.
    全局性和非范围性。你在一个地方写的CSS将被应用到所有地方。使用像BEM这样的命名规则可以有所帮助,但它的摩擦力很大,而且在规模上容易失败:命名冲突仍然是可能的,而且需要巨大的奉献精神和意志力来保持与它的100%一致。
  • Requires that you remember to add vendor prefixes for many CSS properties, to ensure optimal browser support.
    要求你记得为许多CSS属性添加供应商前缀,以确保最佳的浏览器支持。
  • Can't easily share data between CSS and JS.
    不能轻易在CSS和JS之间分享数据。
  • When it comes to modern JS application development, it feels a bit like a square peg being squeezed into a round hole. CSS is built for documents, not apps.
    谈到现代JS应用开发,感觉有点像方枘圆凿。CSS是为文档而建,而不是为应用程序而建。

Sass / Less萨斯 / 少

As we saw in this module's introduction, Sass is a preprocessor that compiles to vanilla CSS. It extends CSS with features like nesting, variables, and iteration.
正如我们在本模块的介绍中所看到的,Sass是一个预处理器,可以编译成vanilla CSS。它用嵌套、变量和迭代等功能扩展了CSS。

It's similar in operation to TypeScript: all valid CSS is also valid Sass, and Sass compiles to CSS at build-time, just like TypeScript compiles to JavaScript.
它在操作上与TypeScript类似:所有有效的CSS也是有效的Sass,Sass在构建时编译成CSS,就像TypeScript编译成JavaScript一样。

$font-stack: Helvetica, sans-serif;
$primary-color:#333;
.wrapper {
font-family:$font-stack;
h1 {
font-size:2rem;
color:$primary-color;
}
}

I grouped Less into this category because it's quite similar. I've worked with both extensively, and the main difference I remember is that they use different syntax for variables: @var: 10 vs $var: 10.
我把Less归为这一类,因为它很相似。我曾广泛地使用过这两种软件,我记得的主要区别是它们对变量使用不同的语法: @var: 10 与 $var: 10 。

Pros:优点:

  • Includes powerful tools like for-loops, mixins, and nesting
    包括强大的工具,如for-loops、mixins和嵌套。
  • Has really high developer satisfaction compared with vanilla CSS.
    与vanilla CSS相比,具有真正高的开发者满意度。

Cons:弊端:

  • Requires a build step (and it's pretty slow in development compared with hot-reloading)
    需要一个构建步骤(与热重载相比,它的开发速度相当慢)。
  • Because it compiles to CSS, it remains global by nature, and isn't scoped to specific components. It inherits a lot of "cons" from vanilla CSS, such as not automatically vendor-prefixing.
    因为它可以编译成CSS,所以它在本质上仍然是全局性的,并不局限于特定的组件。它继承了vanilla CSS的很多 "缺点",比如不能自动给供应商加标签。
  • Everything happens at build time, so it can't react to things in real-time. As we'll learn later on, Sass variables are nowhere near as powerful as CSS variables for this reason.
    一切都发生在构建时间,所以它不能对事情做出实时反应。正如我们稍后将了解到的,由于这个原因,Sass的变量远不如CSS的变量那么强大。
  • Requires native dependencies that can fail or get out-of-date. I can't access my old Sass projects without spending hours dealing with native dependency issues. I can't just npm install — it's a real pain.
    需要原生的依赖性,可能会失败或过时。如果不花几个小时处理本地依赖问题,我就无法访问我的旧Sass项目。我不能只是 npm install - 这是一个真正的痛苦。
  • CSS has added a bunch of new features over the years, and there have been naming clashes. CSS has a native min function now, and it's way better than Sass' min function, but the keyword is already reserved. There are workarounds, but it's added friction.
    这些年来,CSS增加了大量的新功能,而且还出现了命名冲突。CSS现在有一个原生的 min 函数,它比Sass的 min 函数好得多,但这个关键词已经被保留了。有一些变通方法,但这增加了摩擦。
  • It's becoming less and less popular in the JS scene. While popularity isn't everything, a fading solution will have less community resources, less support, and more potential for trouble.
    它在JS场景中越来越不受欢迎了。虽然流行不是一切,但一个逐渐消失的解决方案将拥有更少的社区资源,更少的支持,以及更多的潜在麻烦。

Aphrodite

Aphrodite was one of the first popular CSS-in-JS libraries. It was created and maintained by Khan Academy, an organization I used to work for!
Aphrodite是第一批流行的CSS-in-JS库之一。它是由可汗学院(Khan Academy)创建和维护的,我曾经为这个组织工作过!"!

Aphrodite brings a React-Native-like styling solution to the web. Styles are written in JS, and used by your React components:
Aphrodite为网络带来了类似React-Native的风格化解决方案。样式是用JS编写的,并由你的React组件使用:

import{StyleSheet, css }from'aphrodite';
functionApp(){
return(
<divclassName={css(styles.wrapper)}>
Hello World!
</div>
);
}
const styles =StyleSheet.create({
wrapper:{
backgroundColor:'gray',
minHeight:200,
'@media (min-width: 1025px)':{
fontSize:'1.25rem',
},
},
});

Pros:优点:

  • Scoping and specificity issues entirely disappear. This is the real game-changer, and the reason so many React applications use one CSS-in-JS solution or another.
  • Allowed you to use JS within your CSS! This makes it easy to share state (eg. design tokens). It also allows for complex iteration and generation without the need to learn a new DSL (as you would with Sass/Less).
    允许你在你的CSS中使用JS!这使得共享状态(如设计令牌)变得很容易。它还允许复杂的迭代和生成,而不需要学习一个新的DSL(就像使用Sass/Less那样)。
  • Encourages good habits — no support for nesting, or other things that can land you in hot water.
    鼓励良好的习惯--不支持窝里斗,或其他可能使你陷入困境的事情。
  • Automatically adds vendor prefixes, so you don't have to worry about it.
    自动添加供应商的前缀,所以你不必担心这个问题。
  • Similar API to React Native makes it easy to move between projects, or possibly port components between them (though the CSS alternative on React Native is a bit different, so this isn't trivial).
    与React Native类似的API使得在项目之间移动很容易,或者可能在它们之间移植组件(尽管React Native上的CSS替代方案有点不同,所以这不是小事)。
  • Having styles and JSX in the same file is awesome. No need to keep tabbing between files.
    样式和JSX在同一个文件中是非常棒的。不需要在不同的文件之间不停地滑动。

Cons:弊端:

  • Requires a build step需要一个构建步骤
  • High-friction. It's a lot of messing around, and it's so easy to forget the css() function call.
    高摩擦。乱七八糟的事情很多,而且很容易忘记 css() 函数的调用。
  • Has a cost in terms of bundle size and runtime execution time, though it's relatively small.
    在包的大小和运行时的执行时间方面有代价,尽管它相对较小。
  • Styles must be written in JS. Property names are camelCased, values must be quoted. This can lead to surprising and frustrating differences, like needing to write content: '""' for pseudoelements (discussed later in this course).
    样式必须用JS编写。属性名是CamelCased,值必须是引号。这可能导致令人惊讶和沮丧的差异,比如需要为伪元素写 content: '""' (在本课程后面讨论)。
  • Writing global styles is a bit funky (requires using an extension with some unintuitive syntax).
    编写全局样式有点古怪(需要使用具有一些不直观的语法的扩展)。
  • It's not a very active project — no new releases in 2020. Possibly as a result, the project has been losing the mindshare game.
    这不是一个非常活跃的项目--在2020年没有新的发布。可能是由于这个原因,该项目一直在心智游戏中失利。

Aphrodite is a great tool: it gets the important parts right and solves the biggest problems we face. My biggest complaint is that it's a bit more high-friction than some of the other alternatives: I have less fun building with Aphrodite compared to styled-components. Though this is subjective.
Aphrodite是一个伟大的工具:它把重要的部分做对了,解决了我们面临的最大问题。我最大的抱怨是,它比其他一些替代品更容易产生摩擦:与风格化组件相比,我使用Aphrodite构建的乐趣较少。尽管这是很主观的。

CSS ModulesCSS模块

CSS Modules is a tool that allows you to write vanilla CSS, and import it into a JS file.
CSS模块是一个工具,它允许你编写虚无的CSS,并将其导入JS文件。

“CSS Modules” is a name for a very specific third-party project, not a built-in CSS feature for modules.
"CSS模块 "是一个非常特殊的第三方项目的名称,而不是模块的内置CSS功能。

/* App.module.css */
.wrapper{
background-color:gray;
min-height:200px;
}
@media(min-width:1025px){
.wrapper{
font-size:1.25rem;
}
}
// App.js
importstylesfrom'./App.module.css';
functionApp(){
return(
<divclassName={styles.wrapper}>
Hello World!
</div>
);
}

Pros:优点:

  • Solves scoping and specificity! The .wrapper class you write will be globally-unique, even if a different CSS file has a .wrapper as well. If you were to console.log in the JS file, you'd see something like .wrapper-abc123.
    解决了范围和特异性问题!你写的 .wrapper 类将是全局唯一的,即使不同的CSS文件也有一个 .wrapper 。如果你在JS文件中加入 console.log ,你会看到类似 .wrapper-abc123 的东西。
  • Feels like writing straight-up CSS, which can be nice and familiar
    感觉就像直接写CSS,这可能是很好的和熟悉的。
  • Offers a composes feature, to extend existing CSS classes
    提供一个 composes 功能,以扩展现有的CSS类。

Cons:弊端:

  • Doesn't really offer any modern convenience features, like autoprefixing
    没有真正提供任何现代的便利功能,比如说自动排序。
  • Hard to share data between CSS and JS
    很难在CSS和JS之间共享数据

CSS Modules are often mixed with PostCSS, a plugin ecosystem for extending CSS in beneficial ways (autoprefixing, transpiling, etc). This can smooth out the experience a bit, but in my opinion, it still doesn't feel near as nice in a modern JS context as some of the other options.
CSS模块通常与PostCSS混合使用,后者是一个以有益方式扩展CSS的插件生态系统(自动重命名、转码等)。这可以使体验更顺畅一些,但在我看来,在现代JS环境下,它仍然感觉不如其他一些选项好。

Single-file components单一文件组件

Both Vue and Svelte offer a way to create scoped CSS in the same file as your component definition.
Vue和Svelte都提供了一种方法,可以在组件定义的同一文件中创建范围化的CSS。

// Hello.vue
<template>
<p>Hello World</p>
</template>
<stylescoped>
p{
background-color:gray;
min-height:200px;
}
@media(min-width:1025px){
p{
font-size:1.25rem;
}
}
</style>

This solution reminds me a lot of CSS Modules, and the pros and cons are essentially the same: we can scope our CSS to our component and not have to worry about fallible naming methodologies, but it doesn't help us share data or state between JS and CSS. It feels a lot like writing vanilla CSS, for better or worse.
这种解决方案让我想起了CSS模块,其优点和缺点基本上是一样的:我们可以将CSS的范围扩大到我们的组件,不必担心易变的命名方法,但它不能帮助我们在JS和CSS之间共享数据或状态。这感觉很像在写vanilla CSS,无论好坏。

(Vue recently added support for state-driven dynamic CSS, which uses CSS variables to pass data from JS to CSS, but I haven't personally tried it, so I can't vouch for its effectiveness.)
(Vue最近增加了对状态驱动的动态CSS的支持,它使用CSS变量将数据从JS传递到CSS,但我没有亲自尝试过,所以我不能保证它的有效性。)

In my opinion, the biggest benefit compared to similar options is that your styles and markup are written in the same file. This is awesome, and requires way less jumping-around between files.
在我看来,与类似的选项相比,最大的好处是你的样式和标记都写在同一个文件里。这很好,而且需要减少文件之间的跳转。

styled-components风格化的组件

As we've already discussed, styled-components is a CSS-in-JS solution with a radical idea: every style is also a React component.
正如我们已经讨论过的,styled-components是一个CSS-in-JS解决方案,有一个激进的想法:每个样式也是一个React组件。

importstyledfrom'styled-components';
functionApp(){
return(
<Wrapper>
Hello World!
</Wrapper>
);
}
constWrapper= styled.div`
background-color:gray;
min-height:200px;
@media(min-width:1025px){
font-size:1.25rem;
}
`;

Pros:优点:

  • Solves scoping and specificity in a magnificent way. This solution is tailor-made for component-driven architectures, and it fits like a glove.
    以一种宏伟的方式解决了范围和特异性问题。这个解决方案是为组件驱动的架构量身定做的,它就像一个手套一样合适。
  • Feels like writing CSS (since you are just writing css!), with some of the quality-of-life improvements from Sass/Less rolled in.
    感觉就像在写CSS(因为你只是在写css!),并加入了Sass/Less的一些生活质量改进。
  • Offers good solutions for animations and global styles — you can write 100% of your CSS with this tool
    为动画和全局样式提供良好的解决方案--你可以用这个工具编写100%的CSS
  • Extremely high developer satisfaction.
    开发者满意度极高。
  • Best-in-class performance: styled-components version 5 has gotten extremely performant, as we'll see in a future lesson. Plus it supports
    一流的性能:正如我们将在未来的课程中看到的,styled-components第5版的性能已经变得非常好。此外,它还支持
    , which allows us to improve performance even more.
    ,这使我们能够进一步提高性能。
  • The most popular CSS-in-JS solution out there, according to the # of Github projects that depend on it. Lots of active development, an engaged community, and plenty of resources.
    根据依赖它的Github项目的数量,这是目前最流行的CSS-in-JS解决方案。很多活跃的开发,一个参与的社区,以及大量的资源。

Cons:弊端:

  • Requires a build system需要一个构建系统
  • It's primarily a React tool (you can use styled-components with Vue and possibly other frameworks, but those communities will be much smaller).
    它主要是一个React工具(你可以用Vue和可能的其他框架使用风格化组件,但这些社区会小得多)。
  • Obfuscates the underlying markup tags, which can make it harder to get a sense of the HTML semantics at a glance.
    掩盖了底层的标记标签,这可能会使人更难一眼看清HTML的语义。

Emotion情感

Emotion emerged shortly after styled-components, featuring a very similar API, but with improved performance characteristics.
Emotion在styled-components之后不久出现,具有非常相似的API,但性能特征有所提高。

Over time, the performance difference has disappeared (both libraries are extremely fast), and Emotion has grown to be a bit broader in scope.
随着时间的推移,性能上的差异已经消失了(两个库都非常快),Emotion的范围也越来越广了。

Pros:优点:

  • Can be used without React (albeit with a different syntax)
    可以在没有React的情况下使用(尽管有不同的语法)。
  • Slightly smaller bundle size compared with styled-components
    与风格化组件相比,捆绑的尺寸略小

Cons:弊端:

  • Not as popular or battle-tested as styled-components — according to Github in early 2021, ~100k projects depend on Emotion, while ~500k projects use styled-components.
    不像风格化组件那样流行或经过战斗考验--根据Github在2021年初的数据,约10万个项目依赖Emotion,而约50万个项目使用风格化组件。
  • emotion/styled takes a different approach towards dynamic props which can be slightly less flexible.
    emotion/styled 对动态道具采取了不同的方法,其灵活性可能稍差。

Ultimately, Emotion is so similar to styled-components that it largely doesn't matter which you pick. They're both fantastic choices.
最终,Emotion与styled-components是如此相似,以至于你选择哪一个基本上并不重要。它们都是很好的选择。

Tailwind尾风

Tailwind is a utility-first CSS framework.
Tailwind是一个实用至上的CSS框架。

"Utilities" in this context are short CSS classes that map to specific styles. Here's an example:
这里的 "实用工具 "是指映射到特定样式的简短CSS类。这里有一个例子:

<divclass="relative z-10 max-w-screen-lg xl:max-w-screen-xl mx-auto">
Hello World
</div>

These classes apply the following CSS to the div:
这些类对 div 的CSS应用如下:

z-index:10;
position: relative;
max-width:1024px;
margin-left: auto;
margin-right: auto;

Pros:优点:

  • Solves scoping and specificity解决了范围和特异性问题
  • Encourages good habits when it comes to following a design system — instead of specifying sizes in pixels, for example, they're specified in terms of size (lg, xl)
    鼓励在遵循设计系统时养成良好的习惯--例如,不以像素为单位指定尺寸,而是以尺寸( lg , xl )来指定。
  • Includes built-in design tokens (colors, sizes…), which can make it easier to come up with a nice design.
    包括内置的设计令牌(颜色、尺寸......),这可以使你更容易想出一个漂亮的设计。
  • Can be faster to write, once you get the hang of it
    一旦你掌握了诀窍,写起来就会更快。
  • Not React-specific不是针对React的
  • Tailwind has exploded in popularity over the past few years. It has an extremely passionate user base, and a ton of community resources.
    在过去的几年里,Tailwind的受欢迎程度呈爆炸式增长。它有一个极其热情的用户群,并有大量的社区资源。

Cons:弊端:

  • Relatively steep learning curve, compared to other tools
    与其他工具相比,学习曲线相对较陡峭
  • Because not all CSS can be turned into utilities, you'll likely need a secondary system for writing more-traditional CSS
    因为不是所有的CSS都可以变成实用程序,你可能需要一个辅助系统来编写更传统的CSS
  • Adds a lot of "bulk" to your markup. In real-world scenarios, many many classes are required, and this can make it harder to read. For example:
    给你的标记增加了很多 "体积"。在现实世界的场景中,需要很多很多的类,这可能会使它更难阅读。比如说:
<div
class="relative col-start-1 col-end-2 sm:col-start-2
sm:col-end-3 lg:col-start-1 lg:col-span-full
xl:col-start-2 xl:col-end-3 row-start-2 row-end-3
xl:row-start-3 xl:row-end-4 self-center pr-8 sm:px-6
md:px-8 pb-6 md:pb-8 lg:px-0 lg:pb-0 -mt-6 sm:-mt-10
md:-mt-16 lg:-mt-32 xl:mt-0"
></div>

Tailwind tends to be very polarizing: developers love it or hate it.
Tailwind往往是非常两极化的:开发者喜欢它或讨厌它。

For React developers, an interesting option has surfaced recently: twin. With twin, you write Tailwind classes, but it gets transformed under-the-hood to use styled-components. This allows us to mix "raw" CSS in with our Tailwind classes, for cases when utilities don't exist. It also addresses some of the build complexities.
对于React开发者来说,最近出现了一个有趣的选择:Twin。有了twin,你可以写Tailwind类,但它会在后台被转换为使用styled-components。这允许我们将 "原始 "CSS与我们的Tailwind类混合在一起,以应对不存在实用工具的情况。它还解决了一些复杂的构建问题。

The list goes on!这样的例子不胜枚举!

Since writing this original list in 2020, several options have risen to prominence:
自2020年写下这份原始清单以来,有几个选项已经上升到突出地位:

I don't have significant experience with any of them, so I haven't really formed much of an opinion.
我对他们中的任何一个都没有重要的经验,所以我还没有真正形成什么意见。

One thing they all share in common: they either have no runtime, or a very light runtime. This seems to be a popular trend these days. We'll learn more about the effects of CSS-in-JS runtimes in an upcoming lesson on performance.
它们都有一个共同点:要么没有运行时间,要么运行时间很短。这似乎是最近的一个流行趋势。我们将在即将到来的关于性能的课程中了解更多关于CSS-in-JS运行时间的影响。

At the time of writing (late 2022), none of them have found widespread adoption. Personally, I would much rather stick with a battle-tested tool with tons of community support and resources. But, if you're looking to try something different and potentially get in early on the next big thing, these tools could be worth experimenting with!
在写这篇文章的时候(2022年底),它们都没有得到广泛的采用。就个人而言,我更愿意坚持使用一个经过战斗考验的工具,有大量的社区支持和资源。但是,如果你想尝试一些不同的东西,并有可能提前进入下一个大事件,这些工具可能是值得尝试的!

In the end, it doesn't really matter
最后,这其实并不重要

We're living in something of a "golden age" of CSS — we have so many awesome tools to pick from!
我们正生活在CSS的 "黄金时代"--我们有这么多了不起的工具可供选择!"!

This course uses styled-components, but ultimately, it doesn't really matter which tool you use. The fundamentals are all the same. The skills you learn in this course will stick with you for your entire career, regardless which tool you use. In 5-10 years, we'll probably all be using some fancy CSS tool that doesn't even exist yet, and I feel confident the skills you learn in this course will still help you every day.
本课程使用风格化的组件,但最终,你使用哪种工具并不重要。基本原理都是一样的。你在本课程中学到的技能将伴随你的整个职业生涯,无论你使用哪种工具。5-10年后,我们可能都会使用一些甚至还不存在的花哨的CSS工具,而我相信你在本课程中学到的技能仍然会每天帮助你。

If I had to make one recommendation, it's that you pick an option that is scoped by default — using Vanilla CSS or Sass (without another tool like PostCSS) is still a viable path, but it adds a lot of mental overhead and unnecessary challenge. It takes all the fun out of writing CSS. Beyond that, though, they're all good choices. The tool matters less than how you use it.
如果我不得不提出一个建议,那就是你应该选择一个默认范围的选项--使用Vanilla CSS或Sass(不使用PostCSS等其他工具)仍然是一条可行的途径,但它增加了很多精神开销和不必要的挑战。它把编写CSS的所有乐趣都剥夺了。不过,除此之外,它们都是不错的选择。工具的重要性不在于你如何使用它。

As I mentioned in the last video, though, it's worth getting comfortable with styled-components even if you have no intention of switching to it as your primary tool. It'll help you in this course, and give you ideas you can take back to your tool of choice.
正如我在上一个视频中提到的,即使你不打算把它作为你的主要工具,也值得去适应风格化组件的使用。它将在本课程中帮助你,并给你带来一些想法,你可以把它们带回你选择的工具。