
核心概念
从有限的一组基本工具构建复杂组件。
传统上,每当你需要在网页上进行样式设计时,你都会写CSS。
🌐 Traditionally, whenever you need to style something on the web, you write CSS.
使用传统方法时,自定义设计需要自定义 CSS
You have a new message!
<div class="chat-notification">
<div class="chat-notification-logo-wrapper">
<img class="chat-notification-logo" src="/img/logo.svg" alt="ChitChat Logo">
</div>
<div class="chat-notification-content">
<h4 class="chat-notification-title">ChitChat</h4>
<p class="chat-notification-message">You have a new message!</p>
</div>
</div>
<style>
.chat-notification {
display: flex;
align-items: center;
max-width: 24rem;
margin: 0 auto;
padding: 1.5rem;
border-radius: 0.5rem;
background-color: #fff;
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
}
.chat-notification-logo-wrapper {
flex-shrink: 0;
}
.chat-notification-logo {
height: 3rem;
width: 3rem;
}
.chat-notification-content {
margin-left: 1.5rem;
}
.chat-notification-title {
color: #1a202c;
font-size: 1.25rem;
line-height: 1.25;
}
.chat-notification-message {
color: #718096;
font-size: 1rem;
line-height: 1.5;
}
</style>
使用 Tailwind 时,你可以通过在 HTML 中直接应用预设的类来为元素添加样式。
🌐 With Tailwind, you style elements by applying pre-existing classes directly in your HTML.
使用实用类构建自定义设计,无需编写 CSS
You have a new message!
<div class="p-6 max-w-sm mx-auto bg-white rounded-xl shadow-lg flex items-center gap-x-4">
<div class="shrink-0">
<img class="size-12" src="/img/logo.svg" alt="ChitChat Logo">
</div>
<div>
<div class="text-xl font-medium text-black">ChitChat</div>
<p class="text-slate-500">You have a new message!</p>
</div>
</div>
在上面的例子中,我们使用了:
🌐 In the example above, we’ve used:
flex、shrink-0 和 p-6)来控制整体卡片布局max-w-sm 和 mx-auto)用于限制卡片宽度并水平居中bg-white、rounded-xl 和 shadow-lg)size-12)gap-x-4)text-xl、text-black、font-medium 等)这种方法使我们能够实现完全自定义的组件设计,而无需编写一行自定义 CSS。
🌐 This approach allows us to implement a completely custom component design without writing a single line of custom CSS.
现在我知道你在想什么,“这简直是一场灾难,真是糟糕透了!”,你说的没错,这确实有点丑。实际上,第一次看到它时几乎不可能觉得这是个好主意——你必须亲自试一试。
🌐 Now I know what you’re thinking, “this is an atrocity, what a horrible mess!” and you’re right, it’s kind of ugly. In fact it’s just about impossible to think this is a good idea the first time you see it — you have to actually try it.
但一旦你真的用这种方式构建了某样东西,你会很快注意到一些非常重要的好处:
🌐 But once you’ve actually built something this way, you’ll quickly notice some really important benefits:
sidebar-inner-wrapper 这样无意义的类名,也不需要再为一个实际上只是弹性容器的东西纠结于找到完美的抽象名称。当你意识到只使用带预定义实用类的 HTML 工作可以如此高效时,以任何其他方式工作都会感觉像是折磨。
🌐 When you realize how productive you can be working exclusively in HTML with predefined utility classes, working any other way will feel like torture.
对于这种方法,一个常见的反应是想,“这不就是内联样式吗?”在某些方面确实如此——你是直接将样式应用到元素上,而不是给元素分配一个类名然后为该类设置样式。
🌐 A common reaction to this approach is wondering, “isn’t this just inline styles?” and in some ways it is — you’re applying styles directly to elements instead of assigning them a class name and then styling that class.
但是使用工具类比使用内联样式有几个重要的优点:
🌐 But using utility classes has a few important advantages over inline styles:
该组件完全响应式,并包含一个具有悬停和聚焦样式的按钮,且完全使用工具类构建:
🌐 This component is fully responsive and includes a button with hover and focus styles, and is built entirely with utility classes:
Erin Lindford
Product Engineer
<div class="py-8 px-8 max-w-sm mx-auto space-y-2 bg-white rounded-xl shadow-lg sm:py-4 sm:flex sm:items-center sm:space-y-0 sm:gap-x-6">
<img class="block mx-auto h-24 rounded-full sm:mx-0 sm:shrink-0" src="/img/erin-lindford.jpg" alt="Woman's Face" />
<div class="text-center space-y-2 sm:text-left">
<div class="space-y-0.5">
<p class="text-lg text-black font-semibold">
Erin Lindford
</p>
<p class="text-slate-500 font-medium">
Product Engineer
</p>
</div>
<button class="px-4 py-1 text-sm text-purple-600 font-semibold rounded-full border border-purple-200 hover:text-white hover:bg-purple-600 hover:border-transparent focus:outline-none focus:ring-2 focus:ring-purple-600 focus:ring-offset-2">Message</button>
</div>
</div>
在使用以实用工具为先的方法时,最大的可维护性问题是管理常见的重复实用工具组合。
🌐 The biggest maintainability concern when using a utility-first approach is managing commonly repeated utility combinations.
这可以通过提取组件和局部文件以及使用像多光标编辑和简单循环这样的编辑器和语言功能轻松解决。
🌐 This is easily solved by extracting components and partials, and using editor and language features like multi-cursor editing and simple loops.
<!-- PrimaryButton.vue -->
<template>
<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
<slot/>
</button>
</template>
除此之外,维护一个以实用工具为优先的 CSS 项目实际上比维护一个大型 CSS 代码库要容易得多,这只是因为 HTML 比 CSS 更易于维护。像 GitHub、Netflix、Heroku、Kickstarter、Twitch、Segment 等大公司都在使用这种方法,并取得了很大的成功。
🌐 Aside from that, maintaining a utility-first CSS project turns out to be a lot easier than maintaining a large CSS codebase, simply because HTML is so much easier to maintain than CSS. Large companies like GitHub, Netflix, Heroku, Kickstarter, Twitch, Segment, and more are using this approach with great success.
如果你想了解其他人对这种方法的体验,可以参考以下资源:
🌐 If you’d like to hear about others’ experiences with this approach, check out the following resources:
想了解更多,请查看由 John Polacek 精选的《支持原子/实用优先 CSS 的理由》(The Case for Atomic/Utility-First CSS)。
🌐 For even more, check out The Case for Atomic/Utility-First CSS, curated by John Polacek.