good-css
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseGood CSS
优秀的 CSS
One declaration that adapts on its own beats a set of breakpoints, and a CSS feature beats a script. Use JavaScript only where it makes a result nicer that already works without it.
Each technique is a set of properties and values, so it works in any authoring system. Class names in the examples are placeholders. Write the declarations in what the project already uses, whether that is a stylesheet, Tailwind utilities or StyleX objects. Where that system has no shorthand for a declaration, write it the long way, as a Tailwind arbitrary property or a rule in the project's CSS file. Do not swap the technique for a breakpoint.
一个能够自动适配的声明胜过一组断点,一个 CSS 特性胜过一段脚本。只有在 JavaScript 能让原本已经可以正常工作的结果体验更好时,才使用 JavaScript。
每种技术都由一组 CSS 属性和值构成,因此适用于任何编写体系。示例中的 class 名称均为占位符。应按照项目已经使用的体系编写声明,无论它使用的是样式表、Tailwind utilities 还是 StyleX objects。如果该体系没有某个声明的简写形式,就使用完整写法,例如 Tailwind arbitrary property 或项目 CSS 文件中的 rule。不要用断点替换这些技术。
In all CSS
适用于所有 CSS 的规则
These need no file.
- Write and
inlineproperties in place of left, right, top and bottom. Tailwind has them too, as inblock,mbs-andpe-, so never writeinset-bs-,mt-orpr-.top- - Write colors in , with
oklch()as the hue of a gray, white or black. Derive a hover, tint or transparent version withnone.color-mix(in oklch, …) - Put sizes that grow with the screen in one token.
clamp() - Put every rule inside
:hover.@media (hover: hover) and (pointer: fine) - Style focus with and
:focus-visible. Never writeoutline.outline: none - Give everything pressable an state.
:active - Put a transition that moves or scales something inside . Name its properties, never
@media (prefers-reduced-motion: no-preference), and never useall.ease-in - Cut off overflow with . Keep
overflow: clipfor an element a script scrolls.hidden
这些规则不需要任何文件。
- 使用 和
inline方向的属性来代替block、left、right和top。Tailwind 也提供这类工具类,例如bottom、mbs-和pe-,因此绝不写inset-bs-、mt-或pr。top- - 使用 编写颜色,以
oklch()作为灰色、白色或黑色的色相。通过none派生 hover、淡色或透明版本。color-mix(in oklch, …) - 将随屏幕尺寸增长的尺寸集中到一个 token 中。
clamp() - 将所有 规则放在
:hover内。@media (hover: hover) and (pointer: fine) - 使用 和
:focus-visible设置焦点样式。绝不写outline。outline: none - 为所有可按压元素添加 状态。
:active - 将移动或缩放元素的 transition 放在 内。明确指定参与 transition 的属性,绝不使用
@media (prefers-reduced-motion: no-preference),也不使用all。ease-in - 使用 截断溢出。仅对由脚本滚动控制的元素使用
overflow: clip。hidden
Read the entry before you write
编写前先阅读对应条目
Each file holds entries with the CSS and its rules. The rules are the conditions the CSS needs to work, so keep all of them. Read only the files whose row matches what you are about to write. One component matches two or three, and a whole page matches most of them.
| Read | Before you write |
|---|---|
| a reset or base stylesheet, a set of color tokens, dark mode, a type or spacing scale |
| a page container or wrapper, a grid of cards, cards whose parts line up, a sidebar, a component placed in slots of different widths, overlapping layers, centered content that can overflow |
| spacing between sections, elements stacked one above another, one item pushed to the far end of a row or column, nested rounded corners |
| text or images that come from a user or a CMS, such as names, titles, excerpts, thumbnails, avatars and embeds, an icon next to a label, a label that looks off-center, numbers in a column |
| the focus, hover and press states of a button, link, input or card, a small tap target, a clickable card, form validation, a textarea, a parent styled by what it contains, page scroll locked behind a modal |
| easing and duration tokens, one state change that drives several values, a shadow that changes on hover, a transition between pages, the indicator under an active tab |
| a dialog, popover, dropdown menu or accordion |
| a carousel, a row that may overflow, a modal body, chat list or drawer that scrolls between a header and a footer, in-page links under a sticky header, an app shell on desktop or on a phone |
每个文件都包含 CSS 及其适用规则的条目。这些规则是 CSS 正常发挥作用所需的条件,因此必须全部保留。只读取表格中“编写前”场景与当前任务匹配的行所对应的文件。一个组件通常会匹配两三项,而整个页面会匹配其中大多数。
| 阅读 | 编写前 |
|---|---|
| 重置样式或基础样式表、一组颜色 token、深色模式、排版或间距尺度 |
| 页面容器或包装器、卡片网格、内部各部分对齐的卡片、侧边栏、放置在不同宽度插槽中的组件、相互重叠的图层、可能溢出的居中内容 |
| 区块之间的间距、纵向堆叠的元素、被推到一行或一列最末端的单个项目、嵌套的圆角 |
| 来自用户或 CMS 的文本或图像,例如名称、标题、摘要、缩略图、头像和嵌入内容;位于标签旁的图标;看起来未居中的标签;一列数字 |
| 按钮、链接、input 或 card 的 focus、hover 和 press 状态;较小的点击目标;可点击的 card;表单验证;textarea;根据所含内容设置样式的父元素;模态框后方的页面滚动被锁定 |
| 缓动和时长 token;一个状态变化同时驱动多个值;hover 时变化的阴影;页面之间的 transition;活动 tab 下方的指示器 |
| dialog、popover、dropdown menu 或 accordion |
| carousel、可能溢出的行、在 header 和 footer 之间滚动的 modal body、chat list 或 drawer、位于 sticky header 下方的页内链接、桌面端或手机端的 app shell |
Left out on purpose
有意省略的内容
Never add trim on , , or a reset that puts or one shared grid cell on every element. has the reasons.
text-box*text-rendering: optimizeLegibilitydisplay: contentsreferences/foundations.md绝不要对 添加 ,也不要使用 ,或采用会让每个元素都使用 或共用同一个 grid cell 的 reset。 中说明了原因。
*text-box: trimtext-rendering: optimizeLegibilitydisplay: contentsreferences/foundations.mdBrowser support
浏览器支持
Most entries end with a line. This skill sets no browser floor. Weigh the line against the browsers the project targets, and tell the user when something you used is missing from one of them.
Support:大多数条目末尾都有 行。本 skill 不设浏览器支持下限。根据项目面向的浏览器权衡该行内容;如果所使用的某项功能在目标浏览器中缺失,应告知用户。
Support:Motion
Motion
Whether something should animate, the design or review of motion, springs, gestures and drag, and checks on a real phone belong to Emil Kowalski's skills , , , and . When they are installed, use them for those jobs, and where one disagrees with a value here, use its value. When they are not, use the entries as written and add no motion beyond what an entry or the task calls for.
animatereview-animationsimprove-animationsfind-animation-opportunitiesmobile-native是否应该添加动画、motion 的设计或审查、spring、gesture 和 drag,以及在真实手机上的检查,均应交由 Emil Kowalski 的 skills 、、、 和 处理。安装这些 skill 后,应将相关工作交给它们;如果其中某个 skill 的取值与此处不一致,以该 skill 的取值为准。如果尚未安装,则按条目原文使用,并且不添加条目或任务未要求的 motion。
animatereview-animationsimprove-animationsfind-animation-opportunitiesmobile-native