跳至内容
CSS 扩展与预处理器

CSS 扩展与预处理器

本文在 CSS 基础之上,系统介绍 CSS Grid 布局CSS 自定义属性过渡与动画SCSS/Sass 预处理器,以及 Tailwind CSS 原子化方案,帮助你构建可维护的样式体系。

CSS Grid 布局

Grid 是二维布局系统,与 Flexbox(一维)互补。适合整体页面框架、卡片网格等需要行列同时控制的场景。

/* 容器:声明 Grid */
.grid-container {
  display: grid;

  /* 列定义:3 列等宽 */
  grid-template-columns: repeat(3, 1fr);

  /* 行定义:第一行 80px,其余自动 */
  grid-template-rows: 80px auto;

  /* 间距 */
  gap: 16px;            /* 行列统一 */
  column-gap: 24px;     /* 仅列间距 */
  row-gap: 12px;        /* 仅行间距 */
}

/* 子项:定位到具体格子 */
.item-header {
  grid-column: 1 / 4;       /* 跨第 1~3 列(span 写法:span 3) */
  grid-row: 1;
}

.item-sidebar {
  grid-column: 1;
  grid-row: 2 / 5;          /* 跨多行 */
}

.item-main {
  grid-column: 2 / 4;
  grid-row: 2;
}

命名模板区域

.layout {
  display: grid;
  grid-template-columns: 240px 1fr;
  grid-template-rows: 60px 1fr 50px;
  grid-template-areas:
    "header  header"
    "sidebar main"
    "footer  footer";
  min-height: 100vh;
}

.header  { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main    { grid-area: main; }
.footer  { grid-area: footer; }

常用函数与关键字

.responsive-grid {
  display: grid;

  /* auto-fill: 自动填充列数;minmax(200px, 1fr): 最小 200px,最大 1fr */
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));

  /* fr 单位:剩余空间比例 */
  /* 3 列:1:2:1 */
  grid-template-columns: 1fr 2fr 1fr;
}

/* 对齐 */
.grid {
  justify-items: center;     /* 单元格内水平 */
  align-items: center;       /* 单元格内垂直 */
  justify-content: space-between;  /* 容器内列的对齐 */
  align-content: start;            /* 容器内行的对齐 */
}

.item {
  justify-self: end;   /* 单个项目水平对齐 */
  align-self: center;  /* 单个项目垂直对齐 */
}

Grid vs Flexbox 选择

场景推荐
单行工具栏、导航项Flexbox
整体页面布局(行+列)Grid
卡片网格、图片墙Grid
未知数量的列表项居中Flexbox
表单字段标签对齐Grid

CSS 自定义属性(变量)

CSS 变量(--variable-name)是运行时值,可被 JavaScript 读写,作用域遵循 CSS 层叠规则。

/* 全局变量:通常挂在 :root */
:root {
  --color-primary: #3b82f6;
  --color-bg: #f8fafc;
  --spacing-base: 8px;
  --font-body: "Inter", sans-serif;
  --radius: 6px;
  --shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
}

/* 使用变量 */
.button {
  background-color: var(--color-primary);
  border-radius: var(--radius);
  padding: calc(var(--spacing-base) * 1.5) calc(var(--spacing-base) * 3);
  font-family: var(--font-body);
  box-shadow: var(--shadow);
}

/* 带默认值的 var() */
.card {
  color: var(--card-text, var(--color-primary));   /* 回退值 */
}

/* 局部作用域:覆盖特定组件的变量 */
.dark-card {
  --color-bg: #1e293b;
  --card-text: #f1f5f9;
  background-color: var(--color-bg);
  color: var(--card-text);
}

主题切换(暗色模式)

:root {
  --bg: #ffffff;
  --text: #1a1a1a;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #1a1a1a;
    --text: #f0f0f0;
  }
}

/* 或者用 data 属性手动切换 */
[data-theme="dark"] {
  --bg: #1a1a1a;
  --text: #f0f0f0;
}
// JavaScript 读写 CSS 变量
const root = document.documentElement
root.style.setProperty("--color-primary", "#ef4444")
getComputedStyle(root).getPropertyValue("--color-primary").trim()

// 切换主题
document.documentElement.setAttribute("data-theme", "dark")

CSS 过渡与动画

transition(过渡)

过渡让属性变化在指定时间内平滑完成,适合交互状态切换(hover、focus、active)。

.button {
  background-color: #3b82f6;
  transform: scale(1);
  opacity: 1;

  /* transition: 属性 持续时间 缓动函数 延迟 */
  transition:
    background-color 0.2s ease,
    transform 0.15s ease-out,
    opacity 0.2s ease;
}

.button:hover {
  background-color: #2563eb;
  transform: scale(1.03);
}

/* 常用缓动函数 */
/* ease(默认):慢快慢   ease-in:渐入   ease-out:渐出   linear:匀速 */
/* cubic-bezier(x1, y1, x2, y2):自定义曲线 */

/* 多属性简写 */
.card {
  transition: all 0.3s ease;   /* 所有变化属性(性能较差,不推荐生产) */
}

@keyframes(关键帧动画)

关键帧动画适合循环动画、入场/离场效果等复杂序列。

/* 定义动画 */
@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translateY(16px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes spin {
  0%   { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50%       { opacity: 0.5; }
}

/* 应用动画 */
.card {
  /* animation: 名称 持续时间 缓动 延迟 次数 方向 填充模式 */
  animation: fadeIn 0.4s ease-out 0.1s 1 normal forwards;
}

.loader {
  animation: spin 1s linear infinite;
}

.skeleton {
  animation: pulse 1.5s ease-in-out infinite;
}

/* 暂停/播放 */
.paused { animation-play-state: paused; }

性能优化原则

过渡和动画只对 transformopacity 是 GPU 加速的;修改 widthheighttopleft 会触发重排(reflow),性能代价高。

/* ✅ GPU 加速:transform + opacity */
.modal { transform: translateX(-100%); opacity: 0; }
.modal.open { transform: translateX(0); opacity: 1; }

/* ❌ 触发重排 */
.modal { left: -300px; }
.modal.open { left: 0; }

SCSS / Sass

Sass 是 CSS 的超集,支持变量、嵌套、Mixin、继承等功能。现代项目推荐使用 SCSS 语法(兼容标准 CSS 语法)。

安装与编译

# 安装 Dart Sass(官方推荐实现)
npm install -g sass

# 编译
sass styles.scss styles.css

# 监听变化
sass --watch styles.scss styles.css

# 项目中使用(Vite 内置支持,无需额外配置)
npm install -D sass

变量

// 变量使用 $ 前缀
$color-primary: #3b82f6;
$color-danger: #ef4444;
$font-size-base: 16px;
$border-radius: 6px;
$spacing: 8px;

.button {
  background-color: $color-primary;
  font-size: $font-size-base;
  padding: $spacing ($spacing * 2);
  border-radius: $border-radius;
}

嵌套

// 嵌套选择器(减少重复书写父选择器)
.navbar {
  display: flex;
  background: #1e293b;

  .nav-item {
    padding: 12px 16px;
    color: #94a3b8;

    &:hover {                 // & 代表父选择器(.navbar .nav-item:hover)
      color: white;
    }

    &.active {                // .navbar .nav-item.active
      color: #60a5fa;
      font-weight: 600;
    }

    &::after {                // 伪元素
      content: "";
    }
  }

  // 嵌套媒体查询(Sass 4.0+ / 新标准原生支持)
  @media (max-width: 768px) {
    flex-direction: column;
  }
}

@mixin 与 @include

Mixin 是可复用的样式块,支持参数和默认值。

// 定义 mixin
@mixin flex-center($direction: row) {
  display: flex;
  flex-direction: $direction;
  justify-content: center;
  align-items: center;
}

@mixin respond-to($breakpoint) {
  @if $breakpoint == "mobile" {
    @media (max-width: 640px) { @content; }
  } @else if $breakpoint == "tablet" {
    @media (max-width: 1024px) { @content; }
  }
}

@mixin button-variant($bg, $text: white) {
  background-color: $bg;
  color: $text;
  border: 1px solid darken($bg, 10%);

  &:hover {
    background-color: darken($bg, 8%);
  }
}

// 使用 mixin
.hero {
  @include flex-center(column);
  min-height: 100vh;
}

.card {
  @include respond-to("mobile") {
    padding: 12px;
  }
}

.btn-primary { @include button-variant(#3b82f6); }
.btn-danger  { @include button-variant(#ef4444); }

@extend(继承)

// 占位符选择器(% 开头,不会生成 CSS,仅供继承)
%card-base {
  border-radius: 8px;
  padding: 20px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.product-card {
  @extend %card-base;
  border: 1px solid #e2e8f0;
}

.alert-card {
  @extend %card-base;
  border-left: 4px solid #ef4444;
}
@extend vs @mixin@extend 合并选择器(输出更少 CSS),但不支持参数,且跨文件继承容易出问题。@mixin 更灵活安全,通常优先选 mixin。

@use 与 @forward(模块化)

现代 Sass 用 @use 替代已废弃的 @import,避免全局命名污染。

// _variables.scss
$color-primary: #3b82f6 !default;   // !default:允许调用方覆盖
$spacing-unit: 8px !default;

// _mixins.scss
@use "variables" as vars;

@mixin spacing($n: 1) {
  padding: vars.$spacing-unit * $n;
}

// styles.scss(入口)
// 配置变量(必须在 @use 的 with 子句中)
@use "variables" as vars with (
  $color-primary: #6366f1,
  $spacing-unit: 10px,
);
@use "mixins";

.button {
  color: vars.$color-primary;
  @include mixins.spacing(2);
}
// @forward:让 _index.scss 充当"桶文件",对外暴露多个分模块
// styles/_index.scss
@forward "variables";
@forward "mixins";
@forward "typography";

// 在其它文件只需一行引入
@use "styles";
.heading { font-size: styles.$font-size-lg; }

内置模块

@use "sass:color";
@use "sass:math";
@use "sass:string";
@use "sass:list";
@use "sass:map";

$blue: #3b82f6;

.card {
  background: color.scale($blue, $lightness: 80%);   // 调亮
  border:  1px solid color.adjust($blue, $lightness: -15%);  // 调暗
}

.layout {
  width: math.percentage(2 / 3);    // 66.6667%
  padding: math.round(12.7px);      // 13px
}

项目目录结构(7-1 模式简化版)

styles/
├── _variables.scss      # 全局变量
├── _mixins.scss         # Mixin
├── _base.scss           # 重置 / 基础样式
├── _typography.scss     # 字体
├── _layout.scss         # 网格/布局
├── components/
│   ├── _button.scss
│   └── _card.scss
└── main.scss            # 入口:@use 所有模块

Tailwind CSS

Tailwind 是原子化 CSS 框架:每个 class 只做一件事,样式直接写在 HTML 中,由构建工具按需生成最小 CSS。

安装(Vite 项目)

npm install tailwindcss @tailwindcss/vite

# vite.config.ts 中注册插件
# import tailwindcss from '@tailwindcss/vite'
# plugins: [vue(), tailwindcss()]

在 CSS 入口文件中引入:

/* src/style.css */
@import "tailwindcss";

常用工具类速查

<!-- 布局 -->
<div class="flex items-center justify-between gap-4">...</div>
<div class="grid grid-cols-3 gap-6">...</div>

<!-- 间距 (1 = 4px) -->
<div class="p-4 m-2 px-6 py-3 mt-8 space-x-4">...</div>

<!-- 尺寸 -->
<div class="w-full h-screen max-w-4xl min-h-0">...</div>
<div class="w-1/2 w-64 h-auto">...</div>

<!-- 字体 -->
<p class="text-base text-lg text-xl text-2xl font-bold font-medium">...</p>
<p class="text-gray-700 leading-relaxed tracking-wide">...</p>

<!-- 颜色 / 背景 -->
<div class="bg-blue-500 text-white hover:bg-blue-600">...</div>
<div class="bg-gradient-to-r from-blue-500 to-purple-600">...</div>

<!-- 边框 / 圆角 / 阴影 -->
<div class="border border-gray-200 rounded-lg shadow-md">...</div>
<div class="rounded-full border-2 border-blue-500">...</div>

<!-- 响应式(移动优先,sm/md/lg/xl/2xl) -->
<div class="w-full md:w-1/2 lg:w-1/3">...</div>
<p class="text-sm md:text-base lg:text-lg">...</p>

<!-- 暗色模式 -->
<div class="bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100">...</div>

<!-- 状态变体 -->
<button class="bg-blue-500 hover:bg-blue-600 focus:ring-2 active:scale-95 disabled:opacity-50">
  Click me
</button>

配置主题(tailwind.config.js / CSS)

Tailwind v4 支持在 CSS 中直接配置主题:

@import "tailwindcss";

@theme {
  /* 自定义颜色 */
  --color-brand: #6366f1;
  --color-brand-dark: #4f46e5;

  /* 自定义字体 */
  --font-sans: "Inter", sans-serif;

  /* 自定义断点 */
  --breakpoint-xs: 480px;
}
// tailwind.config.js(v3 写法)
export default {
  content: ["./src/**/*.{html,js,ts,vue,jsx,tsx}"],
  darkMode: "class",   // 或 "media"
  theme: {
    extend: {
      colors: {
        brand: { DEFAULT: "#6366f1", dark: "#4f46e5" },
      },
      fontFamily: {
        sans: ["Inter", "sans-serif"],
      },
      animation: {
        "fade-in": "fadeIn 0.3s ease-out",
      },
    },
  },
}

@apply(在组件中复用工具类)

/* 将常用工具类组合为语义化类(Vue SFC 中使用) */
.btn-primary {
  @apply inline-flex items-center px-4 py-2 rounded-lg
         bg-blue-500 text-white font-medium
         hover:bg-blue-600 transition-colors duration-200
         focus:outline-none focus:ring-2 focus:ring-blue-400;
}

Tailwind vs 自定义 CSS 选择

场景推荐
快速原型、管理后台Tailwind
高度定制化品牌组件库SCSS / CSS Modules
设计令牌(Design Token)管理CSS 自定义属性 + SCSS
已有 SCSS 项目扩展功能SCSS
Vue/React 组件库CSS Modules 或 Tailwind
最后更新于