frontend-tailwind-best-practices

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Tailwind CSS Best Practices

Tailwind CSS 最佳实践

Styling patterns and conventions for frontend applications. Contains 10 rules covering layout utilities, affordances, color schemes, responsive design, and className handling.
适用于前端应用的样式设计模式与规范,包含10条规则,覆盖布局工具、视觉交互、配色方案、响应式设计以及className处理等内容。

When to Apply

适用场景

Reference these guidelines when:
  • Writing component styles with Tailwind
  • Creating layouts (stacks, grids, centering)
  • Handling responsive design
  • Working with color schemes
  • Merging className props
在以下场景中可参考这些指南:
  • 使用Tailwind编写组件样式时
  • 创建布局(堆叠、网格、居中)时
  • 处理响应式设计时
  • 配置配色方案时
  • 合并className属性时

Rules Summary

规则摘要

Layout Utilities (CRITICAL)

布局工具(CRITICAL)

layout-stack-utilities - @rules/layout-stack-utilities.md

layout-stack-utilities - @rules/layout-stack-utilities.md

Use custom stack utilities instead of flex classes.
tsx
// Bad
<div className="flex flex-col gap-4">
<div className="flex flex-row gap-4">

// Good
<div className="v-stack gap-4">
<div className="h-stack gap-4">
Available utilities:
  • v-stack
    - Vertical stack (flex column)
  • h-stack
    - Horizontal stack (flex row)
  • v-stack-reverse
    - Reversed vertical stack
  • h-stack-reverse
    - Reversed horizontal stack
  • z-stack
    - Overlapping stack (grid-based, centers children on top of each other)
  • center
    - Center content both horizontally and vertically
  • spacer
    - Flexible spacer that fills available space
  • circle
    - Perfect circle with aspect-ratio 1/1
使用自定义堆叠工具类替代flex类。
tsx
// 不推荐
<div className="flex flex-col gap-4">
<div className="flex flex-row gap-4">

// 推荐
<div className="v-stack gap-4">
<div className="h-stack gap-4">
可用工具类:
  • v-stack
    - 垂直堆叠(flex column)
  • h-stack
    - 水平堆叠(flex row)
  • v-stack-reverse
    - 反向垂直堆叠
  • h-stack-reverse
    - 反向水平堆叠
  • z-stack
    - 重叠堆叠(基于grid,子元素居中叠加)
  • center
    - 内容水平垂直居中
  • spacer
    - 可灵活填充可用空间的间隔元素
  • circle
    - 宽高比1/1的完美圆形

layout-prefer-gaps - @rules/layout-prefer-gaps.md

layout-prefer-gaps - @rules/layout-prefer-gaps.md

Use
gap-*
on parents instead of child margins.
tsx
// Bad
<div>
  <Item className="mb-4" />
  <Item className="mb-4" />
</div>

// Good
<div className="flex flex-col gap-4">
  <Item />
  <Item />
</div>
在父元素上使用
gap-*
替代子元素的margin。
tsx
// 不推荐
<div>
  <Item className="mb-4" />
  <Item className="mb-4" />
</div>

// 推荐
<div className="flex flex-col gap-4">
  <Item />
  <Item />
</div>

layout-responsive-stacks - @rules/layout-responsive-stacks.md

layout-responsive-stacks - @rules/layout-responsive-stacks.md

Switch layout direction at breakpoints.
tsx
// Mobile: vertical, Desktop: horizontal
<div className="v-stack lg:h-stack gap-4">
  <main className="grow">...</main>
  <aside className="shrink-0 lg:w-80">...</aside>
</div>

// Mobile: horizontal, Desktop: vertical
<div className="h-stack md:v-stack">
在断点处切换布局方向。
tsx
// 移动端:垂直,桌面端:水平
<div className="v-stack lg:h-stack gap-4">
  <main className="grow">...</main>
  <aside className="shrink-0 lg:w-80">...</aside>
</div>

// 移动端:水平,桌面端:垂直
<div className="h-stack md:v-stack">

Color Schemes (CRITICAL)

配色方案(CRITICAL)

color-schemes - @rules/color-schemes.md

color-schemes - @rules/color-schemes.md

Use class-based color schemes with a custom
dark
variant.
tsx
<button className="rounded-full bg-gray-900 px-4 py-2 text-white dark:bg-gray-100 dark:text-gray-900">
  Toggle
</button>
使用基于类的配色方案,并搭配自定义
dark
变体。
tsx
<button className="rounded-full bg-gray-900 px-4 py-2 text-white dark:bg-gray-100 dark:text-gray-900">
  切换
</button>

className Handling (CRITICAL)

className处理(CRITICAL)

classname-cn-utility - @rules/classname-cn-utility.md

classname-cn-utility - @rules/classname-cn-utility.md

Always use
cn()
to merge classNames in components.
tsx
import { cn } from "~/lib/cn";

function Button({ className, variant }: Props) {
  return (
    <button
      className={cn(
        "base-classes",
        {
          "variant-primary": variant === "primary",
          "variant-secondary": variant === "secondary",
        },
        className, // external className always last
      )}
    />
  );
}
在组件中始终使用
cn()
来合并className。
tsx
import { cn } from "~/lib/cn";

function Button({ className, variant }: Props) {
  return (
    <button
      className={cn(
        "base-classes",
        {
          "variant-primary": variant === "primary",
          "variant-secondary": variant === "secondary",
        },
        className, // 外部className始终放在最后
      )}
    />
  );
}

classname-prop-types - @rules/classname-prop-types.md

classname-prop-types - @rules/classname-prop-types.md

Use proper types for className props.
tsx
import type { ClassName, ClassNameRecord } from "~/lib/cn";

// Single element
type Props = {
  className?: ClassName;
};

// Multiple elements
type Props = {
  className?: ClassNameRecord<"root" | "label" | "input">;
};

// Usage
<Input className={{ root: "w-full", label: "font-bold" }} />;
为className属性使用正确的类型定义。
tsx
import type { ClassName, ClassNameRecord } from "~/lib/cn";

// 单个元素
type Props = {
  className?: ClassName;
};

// 多个元素
type Props = {
  className?: ClassNameRecord<"root" | "label" | "input">;
};

// 使用示例
<Input className={{ root: "w-full", label: "font-bold" }} />;

Affordances (HIGH)

视觉交互(HIGH)

affordance-classes - @rules/affordance-classes.md

affordance-classes - @rules/affordance-classes.md

Define element-agnostic visual patterns that compose with utilities.
tsx
<label className="ui-button" htmlFor="document-upload">
  Choose file
</label>
定义与元素无关的视觉模式,可与工具类组合使用。
tsx
<label className="ui-button" htmlFor="document-upload">
  选择文件
</label>

Responsive Design (MEDIUM)

响应式设计(MEDIUM)

responsive-breakpoints - @rules/responsive-breakpoints.md

responsive-breakpoints - @rules/responsive-breakpoints.md

Use responsive prefixes with Tailwind defaults.
tsx
// Standard breakpoints (min-width)
<div className="px-4 md:px-8 lg:px-12">

// Show/hide with standard breakpoints
<div className="hidden md:block">Desktop only</div>
<div className="md:hidden">Mobile only</div>
结合Tailwind默认值使用响应式前缀。
tsx
// 标准断点(最小宽度)
<div className="px-4 md:px-8 lg:px-12">

// 根据标准断点显示/隐藏元素
<div className="hidden md:block">仅桌面端可见</div>
<div className="md:hidden">仅移动端可见</div>

responsive-text - @rules/responsive-text.md

responsive-text - @rules/responsive-text.md

Scale text responsively.
tsx
// Responsive font size
<h1 className="text-2xl md:text-3xl lg:text-4xl">

// Responsive line height with text
<p className="text-sm leading-5 md:text-base md:leading-6">
实现文本的响应式缩放。
tsx
// 响应式字体大小
<h1 className="text-2xl md:text-3xl lg:text-4xl">

// 文本搭配响应式行高
<p className="text-sm leading-5 md:text-base md:leading-6">

responsive-capabilities - @rules/responsive-capabilities.md

responsive-capabilities - @rules/responsive-capabilities.md

Design for input capabilities (pointer/hover) instead of device labels.
tsx
<button className="h-10 w-10 pointer-coarse:h-12 pointer-coarse:w-12">
  <Icon />
</button>
针对输入方式(指针/悬停)而非设备类型进行设计。
tsx
<button className="h-10 w-10 pointer-coarse:h-12 pointer-coarse:w-12">
  <Icon />
</button>

Anti-Patterns

反模式

Don'tDo
flex flex-col
v-stack
flex flex-row
h-stack
flex items-center justify-center
center
bg-gray-100
bg-neutral-100
bg-[#hex]
Use design tokens
className="..."
without
cn()
cn("...", className)
Inline
style
for responsive
Tailwind prefixes
不推荐做法推荐做法
flex flex-col
v-stack
flex flex-row
h-stack
flex items-center justify-center
center
bg-gray-100
bg-neutral-100
bg-[#hex]
使用设计令牌
className="..."
不搭配
cn()
使用
cn("...", className)
使用内联
style
实现响应式效果
使用Tailwind前缀

Key Files

关键文件

FilePurpose
tailwind.config.js
Config, custom utilities, colors
app/styles/global.css
Color scheme CSS variables
app/styles/tailwind.css
Additional utilities
app/utils/cn.ts
className merge utility
文件路径用途
tailwind.config.js
配置文件、自定义工具类、配色定义
app/styles/global.css
配色方案CSS变量定义
app/styles/tailwind.css
额外工具类定义
app/utils/cn.ts
className合并工具类