CSS 预处理器深入应用:提升开发效率的利器

前言

CSS 预处理器为样式开发带来了革命性的变化,它们提供了变量、嵌套、混入、函数等编程特性,让 CSS 的编写更加高效和可维护。虽然现代 CSS 已经原生支持了变量等特性,但预处理器依然在复杂项目中发挥着重要作用。本文将深入探讨 Sass、Less 和 Stylus 的高级应用技巧,帮助你构建更加强大和灵活的样式系统。

1. CSS 预处理器 API 详解

1.1 Sass/SCSS 语法特性

变量系统:

css 复制代码
// 基础变量类型
$primary-color: #3b82f6; // 颜色
$base-font-size: 16px; // 数值
$font-family: 'Inter', sans-serif; // 字符串
$enable-gradients: true; // 布尔值
$shadow-levels: null; // 空值
​
// 列表和映射
$font-sizes: 12px, 14px, 16px, 18px, 24px; // 列表
$breakpoints: (
  // 映射
  'mobile': 480px,
  'tablet': 768px,
  'desktop': 1024px,
  'wide': 1400px
);
​
// 变量作用域
$global-var: 'global' !global; // 全局变量
$local-var: 'local' !default; // 默认值(可被覆盖)
​
// 插值语法
$prefix: 'app';
.#{$prefix}-header {
  background: var(--#{$prefix}-bg-color);
}

嵌套规则:

css 复制代码
// 基础嵌套
.navbar {
  background: white;
  padding: 1rem;
​
  &__brand {
    font-weight: bold;
​
    &:hover {
      color: $primary-color;
    }
  }
​
  &__menu {
    display: flex;
​
    @media (max-width: 768px) {
      flex-direction: column;
    }
  }
​
  // 属性嵌套
  font: {
    family: $font-family;
    size: 1rem;
    weight: 500;
  }
​
  // 伪类嵌套
  &:hover,
  &:focus {
    outline: none;
  }
}

混入(Mixins):

css 复制代码
// 基础混入
@mixin button-style($bg-color, $text-color: white) {
  background: $bg-color;
  color: $text-color;
  border: none;
  padding: 0.5rem 1rem;
  border-radius: 4px;
  cursor: pointer;
​
  &:hover {
    background: darken($bg-color, 10%);
  }
}
​
// 带内容块的混入
@mixin media-query($breakpoint) {
  @if map-has-key($breakpoints, $breakpoint) {
    @media (min-width: map-get($breakpoints, $breakpoint)) {
      @content;
    }
  }
}
​
// 可变参数混入
@mixin box-shadow($shadows...) {
  box-shadow: $shadows;
}
​
// 使用混入
.primary-button {
  @include button-style($primary-color);
  @include box-shadow(
    0 2px 4px rgba(0, 0, 0, 0.1),
    0 4px 8px rgba(0, 0, 0, 0.05)
  );
​
  @include media-query('tablet') {
    padding: 0.75rem 1.5rem;
  }
}

函数定义:

js 复制代码
// 自定义函数
@function strip-unit($number) {
  @if type-of($number) == 'number' and not unitless($number) {
    @return $number / ($number * 0 + 1);
  }
  @return $number;
}
​
@function px-to-rem($px-value, $base-font-size: 16px) {
  @return (strip-unit($px-value) / strip-unit($base-font-size)) * 1rem;
}
​
@function color-contrast($color, $light: white, $dark: black, $threshold: 50%) {
  @if lightness($color) > $threshold {
    @return $dark;
  } @else {
    @return $light;
  }
}
​
// 使用函数
.element {
  font-size: px-to-rem(18px); // 1.125rem
  color: color-contrast($primary-color);
}

1.2 Less 语法特性

变量和操作:

css 复制代码
// 变量定义
@primary-color: #3b82f6;
@base-font-size: 16px;
@border-radius: 4px;
​
// 变量操作
@computed-size: @base-font-size * 1.5; // 24px
@lighter-color: lighten(@primary-color, 20%);
@darker-color: darken(@primary-color, 10%);
​
// 变量插值
@prefix: app;
.@{prefix}-component {
  border-radius: @border-radius;
}
​
// 属性变量
@property: color;
.element {
  @{property}: @primary-color;
}

混入特性:

css 复制代码
// 基础混入
.button-base() {
  border: none;
  padding: 0.5rem 1rem;
  border-radius: @border-radius;
  cursor: pointer;
  transition: all 0.3s ease;
}
​
// 参数化混入
.button-variant(@bg-color; @text-color: white) {
  .button-base();
  background: @bg-color;
  color: @text-color;
​
  &:hover {
    background: darken(@bg-color, 10%);
  }
}
​
// 模式匹配混入
.border-radius(@radius) when (@radius > 0) {
  border-radius: @radius;
}
​
.border-radius(@radius) when (@radius = 0) {
  border-radius: 0;
}
​
// 守卫条件
.responsive-font(@size) when (@size >= 18px) {
  font-size: @size;
  line-height: 1.4;
}
​
.responsive-font(@size) when (@size < 18px) {
  font-size: @size;
  line-height: 1.6;
}

1.3 Stylus 语法特性

灵活语法:

css 复制代码
// 变量定义
primary-color = #3b82f6
base-font-size = 16px
font-stack = 'Inter', sans-serif
​
// 函数定义
px-to-rem(value, base = base-font-size)
  unit(value / base, 'rem')
​
button-style(bg-color, text-color = white)
  background bg-color
  color text-color
  border none
  padding 0.5rem 1rem
  border-radius 4px
  cursor pointer
​
  &:hover
    background darken(bg-color, 10%)
​
// 使用
.primary-button
  button-style(primary-color)
  font-size px-to-rem(18px)
​
  @media (max-width: 768px)
    padding 0.25rem 0.5rem

2. 浏览器兼容性分析

2.1 编译输出兼容性

CSS 预处理器支持度:

特性 编译后兼容性 构建工具支持 开发体验
Sass/SCSS 完美 ✅ 优秀 ✅ 优秀 ✅
Less 完美 ✅ 良好 ✅ 良好 ✅
Stylus 完美 ✅ 良好 ✅ 良好 ✅
PostCSS 完美 ✅ 优秀 ✅ 优秀 ✅
原生 CSS 嵌套 Chrome 112+ 部分 ⚠️ 较新 ⚠️
原生 CSS 变量 IE 不支持 良好 ✅ 优秀 ✅

编译工具生态:

工具链 Sass Less Stylus 特点
Webpack 完整生态支持
Vite 现代构建工具
Parcel 零配置构建
Node-sass 高性能 Sass 编译
Dart Sass 官方 Sass 实现
PostCSS 插件 插件 插件 可扩展 CSS 处理器

2.2 现代化迁移策略

渐进式现代化:

css 复制代码
// 兼容现代CSS变量的Sass
:root {
  @each $name, $value in $color-palette {
    --color-#{$name}: #{$value};
  }
}
​
// 同时支持Sass变量和CSS变量
@mixin use-css-vars($use-css-vars: true) {
  @if $use-css-vars {
    color: var(--color-primary, #{$primary-color});
  } @else {
    color: $primary-color;
  }
}
​
// 条件编译支持
@supports (color: var(--test)) {
  .modern-component {
    @include use-css-vars(true);
  }
}
​
@supports not (color: var(--test)) {
  .legacy-component {
    @include use-css-vars(false);
  }
}

PostCSS 集成:

js 复制代码
// postcss.config.js
module.exports = {
  plugins: [
    require('postcss-import'),
    require('postcss-nested'), // Sass风格嵌套
    require('postcss-custom-properties'), // CSS变量处理
    require('postcss-custom-media'), // 自定义媒体查询
    require('autoprefixer'),
    require('cssnano')({
      preset: 'default',
    }),
  ],
};

3. 实战演示:企业级样式系统

3.1 完整的设计系统构建

html 复制代码
<!DOCTYPE html>
<html lang="zh">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>CSS 预处理器深入应用</title>
    <style>
      /* 编译后的CSS - 模拟Sass编译结果 */
​
      /* 设计系统基础变量 */
      :root {
        --color-primary: #3b82f6;
        --color-primary-light: #60a5fa;
        --color-primary-dark: #2563eb;
        --color-success: #10b981;
        --color-warning: #f59e0b;
        --color-error: #ef4444;
        --color-gray-50: #f9fafb;
        --color-gray-100: #f3f4f6;
        --color-gray-900: #111827;
​
        --font-family-sans: 'Inter', system-ui, sans-serif;
        --font-family-mono: 'Fira Code', monospace;
​
        --font-size-xs: 0.75rem;
        --font-size-sm: 0.875rem;
        --font-size-base: 1rem;
        --font-size-lg: 1.125rem;
        --font-size-xl: 1.25rem;
        --font-size-2xl: 1.5rem;
​
        --spacing-1: 0.25rem;
        --spacing-2: 0.5rem;
        --spacing-3: 0.75rem;
        --spacing-4: 1rem;
        --spacing-6: 1.5rem;
        --spacing-8: 2rem;
​
        --border-radius-sm: 0.25rem;
        --border-radius: 0.375rem;
        --border-radius-lg: 0.5rem;
        --border-radius-xl: 0.75rem;
​
        --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
        --shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
        --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0
                0 / 0.1);
​
        --transition-fast: 150ms ease;
        --transition-normal: 300ms ease;
        --transition-slow: 500ms ease;
      }
​
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
​
      body {
        font-family: var(--font-family-sans);
        line-height: 1.6;
        color: var(--color-gray-900);
        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        min-height: 100vh;
      }
​
      .container {
        max-width: 1200px;
        margin: 0 auto;
        padding: var(--spacing-8) var(--spacing-4);
      }
​
      /* 页面标题组件 */
      .page-header {
        text-align: center;
        color: white;
        margin-bottom: var(--spacing-8);
      }
​
      .page-title {
        font-size: clamp(2rem, 5vw, 3rem);
        font-weight: 700;
        margin-bottom: var(--spacing-2);
        text-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
      }
​
      .page-subtitle {
        font-size: var(--font-size-lg);
        opacity: 0.9;
      }
​
      /* 按钮组件系统 - 模拟Sass混入编译结果 */
      .btn {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        gap: var(--spacing-2);
        border: none;
        border-radius: var(--border-radius);
        font-family: inherit;
        font-weight: 500;
        text-decoration: none;
        cursor: pointer;
        transition: all var(--transition-fast);
        user-select: none;
​
        /* 基础尺寸 */
        padding: var(--spacing-2) var(--spacing-4);
        font-size: var(--font-size-base);
        min-height: 2.5rem;
      }
​
      .btn:focus {
        outline: none;
        box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.5);
      }
​
      .btn:disabled {
        opacity: 0.5;
        cursor: not-allowed;
        transform: none !important;
      }
​
      /* 按钮变体 */
      .btn--primary {
        background: var(--color-primary);
        color: white;
      }
​
      .btn--primary:hover:not(:disabled) {
        background: var(--color-primary-dark);
        transform: translateY(-1px);
        box-shadow: var(--shadow-lg);
      }
​
      .btn--secondary {
        background: var(--color-gray-100);
        color: var(--color-gray-900);
      }
​
      .btn--secondary:hover:not(:disabled) {
        background: var(--color-gray-50);
        transform: translateY(-1px);
      }
​
      .btn--outline {
        background: transparent;
        color: var(--color-primary);
        border: 2px solid var(--color-primary);
      }
​
      .btn--outline:hover:not(:disabled) {
        background: var(--color-primary);
        color: white;
      }
​
      /* 按钮尺寸 */
      .btn--sm {
        padding: var(--spacing-1) var(--spacing-3);
        font-size: var(--font-size-sm);
        min-height: 2rem;
      }
​
      .btn--lg {
        padding: var(--spacing-3) var(--spacing-6);
        font-size: var(--font-size-lg);
        min-height: 3rem;
      }
​
      /* 卡片组件系统 */
      .card {
        background: white;
        border-radius: var(--border-radius-lg);
        box-shadow: var(--shadow);
        overflow: hidden;
        transition: all var(--transition-normal);
      }
​
      .card:hover {
        transform: translateY(-2px);
        box-shadow: var(--shadow-lg);
      }
​
      .card__header {
        padding: var(--spacing-6);
        border-bottom: 1px solid var(--color-gray-100);
      }
​
      .card__title {
        font-size: var(--font-size-xl);
        font-weight: 600;
        color: var(--color-gray-900);
        margin-bottom: var(--spacing-2);
      }
​
      .card__subtitle {
        color: var(--color-gray-900);
        opacity: 0.7;
      }
​
      .card__body {
        padding: var(--spacing-6);
      }
​
      .card__footer {
        padding: var(--spacing-6);
        background: var(--color-gray-50);
        border-top: 1px solid var(--color-gray-100);
        display: flex;
        justify-content: flex-end;
        gap: var(--spacing-3);
      }
​
      /* 网格布局系统 */
      .grid {
        display: grid;
        gap: var(--spacing-6);
      }
​
      .grid--1 {
        grid-template-columns: 1fr;
      }
      .grid--2 {
        grid-template-columns: repeat(2, 1fr);
      }
      .grid--3 {
        grid-template-columns: repeat(3, 1fr);
      }
      .grid--4 {
        grid-template-columns: repeat(4, 1fr);
      }
​
      .grid--responsive {
        grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
      }
​
      /* 工具类系统 */
      .text-center {
        text-align: center;
      }
      .text-left {
        text-align: left;
      }
      .text-right {
        text-align: right;
      }
​
      .mb-2 {
        margin-bottom: var(--spacing-2);
      }
      .mb-4 {
        margin-bottom: var(--spacing-4);
      }
      .mb-6 {
        margin-bottom: var(--spacing-6);
      }
      .mb-8 {
        margin-bottom: var(--spacing-8);
      }
​
      .p-4 {
        padding: var(--spacing-4);
      }
      .p-6 {
        padding: var(--spacing-6);
      }
​
      /* 表单组件 */
      .form-group {
        margin-bottom: var(--spacing-4);
      }
​
      .form-label {
        display: block;
        font-weight: 500;
        color: var(--color-gray-900);
        margin-bottom: var(--spacing-2);
      }
​
      .form-input {
        width: 100%;
        padding: var(--spacing-3);
        border: 1px solid #d1d5db;
        border-radius: var(--border-radius);
        font-family: inherit;
        font-size: var(--font-size-base);
        transition: all var(--transition-fast);
      }
​
      .form-input:focus {
        outline: none;
        border-color: var(--color-primary);
        box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
      }
​
      .form-input--error {
        border-color: var(--color-error);
      }
​
      .form-input--error:focus {
        box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.1);
      }
​
      /* 代码展示组件 */
      .code-block {
        background: var(--color-gray-900);
        color: #e5e7eb;
        padding: var(--spacing-4);
        border-radius: var(--border-radius);
        font-family: var(--font-family-mono);
        font-size: var(--font-size-sm);
        overflow-x: auto;
        margin: var(--spacing-4) 0;
      }
​
      .code-block__header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: var(--spacing-3);
        padding-bottom: var(--spacing-3);
        border-bottom: 1px solid #374151;
      }
​
      .code-block__title {
        color: #9ca3af;
        font-size: var(--font-size-xs);
        text-transform: uppercase;
        letter-spacing: 0.05em;
      }
​
      .code-block__copy {
        background: #374151;
        color: #d1d5db;
        border: none;
        padding: var(--spacing-1) var(--spacing-2);
        border-radius: var(--border-radius-sm);
        font-size: var(--font-size-xs);
        cursor: pointer;
        transition: background var(--transition-fast);
      }
​
      .code-block__copy:hover {
        background: #4b5563;
      }
​
      /* 状态指示器 */
      .badge {
        display: inline-flex;
        align-items: center;
        padding: var(--spacing-1) var(--spacing-2);
        border-radius: var(--border-radius-xl);
        font-size: var(--font-size-xs);
        font-weight: 500;
        text-transform: uppercase;
        letter-spacing: 0.05em;
      }
​
      .badge--success {
        background: #d1fae5;
        color: #065f46;
      }
​
      .badge--warning {
        background: #fef3c7;
        color: #92400e;
      }
​
      .badge--info {
        background: #dbeafe;
        color: #1e40af;
      }
​
      /* 响应式设计 */
      @media (max-width: 768px) {
        .container {
          padding: var(--spacing-4) var(--spacing-2);
        }
​
        .grid--2,
        .grid--3,
        .grid--4 {
          grid-template-columns: 1fr;
        }
​
        .card__header,
        .card__body,
        .card__footer {
          padding: var(--spacing-4);
        }
​
        .btn {
          width: 100%;
          justify-content: center;
        }
      }
​
      /* 深色模式支持 */
      @media (prefers-color-scheme: dark) {
        :root {
          --color-gray-50: #111827;
          --color-gray-100: #1f2937;
          --color-gray-900: #f9fafb;
        }
​
        .card {
          background: #1f2937;
          color: #f9fafb;
        }
​
        .card__footer {
          background: #111827;
        }
      }
​
      /* 动画禁用支持 */
      @media (prefers-reduced-motion: reduce) {
        *,
        *::before,
        *::after {
          animation-duration: 0.01ms !important;
          animation-iteration-count: 1 !important;
          transition-duration: 0.01ms !important;
        }
      }
    </style>
  </head>
  <body>
    <div class="container">
      <!-- 页面标题 -->
      <header class="page-header">
        <h1 class="page-title">CSS 预处理器深入应用</h1>
        <p class="page-subtitle">构建可维护的企业级样式系统</p>
      </header>
​
      <!-- 按钮组件展示 -->
      <section class="card mb-8">
        <div class="card__header">
          <h2 class="card__title">按钮组件系统</h2>
          <p class="card__subtitle">展示通过 Sass 混入构建的按钮组件变体</p>
        </div>
        <div class="card__body">
          <div class="grid grid--responsive mb-6">
            <div class="text-center">
              <h4 class="mb-4">主要按钮</h4>
              <div
                style="display: flex; flex-direction: column; gap: 1rem; align-items: center;"
              >
                <button class="btn btn--primary btn--sm">小尺寸</button>
                <button class="btn btn--primary">标准尺寸</button>
                <button class="btn btn--primary btn--lg">大尺寸</button>
              </div>
            </div>
​
            <div class="text-center">
              <h4 class="mb-4">次要按钮</h4>
              <div
                style="display: flex; flex-direction: column; gap: 1rem; align-items: center;"
              >
                <button class="btn btn--secondary btn--sm">小尺寸</button>
                <button class="btn btn--secondary">标准尺寸</button>
                <button class="btn btn--secondary btn--lg">大尺寸</button>
              </div>
            </div>
​
            <div class="text-center">
              <h4 class="mb-4">轮廓按钮</h4>
              <div
                style="display: flex; flex-direction: column; gap: 1rem; align-items: center;"
              >
                <button class="btn btn--outline btn--sm">小尺寸</button>
                <button class="btn btn--outline">标准尺寸</button>
                <button class="btn btn--outline btn--lg">大尺寸</button>
              </div>
            </div>
          </div>
        </div>
      </section>
​
      <!-- 代码示例 -->
      <section class="grid grid--responsive mb-8">
        <div class="card">
          <div class="card__header">
            <h3 class="card__title">Sass 混入示例</h3>
            <span class="badge badge--info">SCSS</span>
          </div>
          <div class="card__body">
            <div class="code-block">
              <div class="code-block__header">
                <span class="code-block__title">button.scss</span>
                <button class="code-block__copy" onclick="copyCode(this)">
                  复制
                </button>
              </div>
              <pre><code>@mixin button-variant($bg, $text: white) {
  background: $bg;
  color: $text;
  border: none;
  padding: 0.5rem 1rem;
  border-radius: 0.375rem;
  cursor: pointer;
  
  &:hover {
    background: darken($bg, 10%);
    transform: translateY(-1px);
  }
}</code></pre>
            </div>
          </div>
        </div>
​
        <div class="card">
          <div class="card__header">
            <h3 class="card__title">Less 混入示例</h3>
            <span class="badge badge--warning">Less</span>
          </div>
          <div class="card__body">
            <div class="code-block">
              <div class="code-block__header">
                <span class="code-block__title">button.less</span>
                <button class="code-block__copy" onclick="copyCode(this)">
                  复制
                </button>
              </div>
              <pre><code>.button-variant(@bg; @text: white) {
  background: @bg;
  color: @text;
  border: none;
  padding: 0.5rem 1rem;
  border-radius: 0.375rem;
  cursor: pointer;
  
  &:hover {
    background: darken(@bg, 10%);
    transform: translateY(-1px);
  }
}</code></pre>
            </div>
          </div>
        </div>
      </section>
​
      <!-- 表单组件 -->
      <section class="card mb-8">
        <div class="card__header">
          <h2 class="card__title">表单组件系统</h2>
          <p class="card__subtitle">展示预处理器生成的表单样式</p>
        </div>
        <div class="card__body">
          <div class="grid grid--2">
            <div class="form-group">
              <label class="form-label">用户名</label>
              <input
                type="text"
                class="form-input"
                placeholder="请输入用户名"
              />
            </div>
​
            <div class="form-group">
              <label class="form-label">邮箱地址</label>
              <input
                type="email"
                class="form-input"
                placeholder="user@example.com"
              />
            </div>
​
            <div class="form-group">
              <label class="form-label">密码</label>
              <input
                type="password"
                class="form-input"
                placeholder="请输入密码"
              />
            </div>
​
            <div class="form-group">
              <label class="form-label">确认密码 (错误状态)</label>
              <input
                type="password"
                class="form-input form-input--error"
                placeholder="请确认密码"
              />
            </div>
          </div>
        </div>
        <div class="card__footer">
          <button class="btn btn--secondary">重置</button>
          <button class="btn btn--primary">提交</button>
        </div>
      </section>
​
      <!-- 预处理器对比 -->
      <section class="grid grid--3 mb-8">
        <div class="card">
          <div class="card__header">
            <h3 class="card__title">Sass/SCSS</h3>
            <span class="badge badge--success">推荐</span>
          </div>
          <div class="card__body">
            <ul style="list-style: none; padding: 0;">
              <li style="margin-bottom: 0.5rem;">✅ 功能最丰富</li>
              <li style="margin-bottom: 0.5rem;">✅ 社区生态最好</li>
              <li style="margin-bottom: 0.5rem;">✅ 两种语法可选</li>
              <li style="margin-bottom: 0.5rem;">✅ 官方维护</li>
              <li style="margin-bottom: 0.5rem;">⚠️ 学习成本较高</li>
            </ul>
          </div>
        </div>
​
        <div class="card">
          <div class="card__header">
            <h3 class="card__title">Less</h3>
            <span class="badge badge--info">流行</span>
          </div>
          <div class="card__body">
            <ul style="list-style: none; padding: 0;">
              <li style="margin-bottom: 0.5rem;">✅ 语法简单</li>
              <li style="margin-bottom: 0.5rem;">✅ 接近CSS</li>
              <li style="margin-bottom: 0.5rem;">✅ Bootstrap使用</li>
              <li style="margin-bottom: 0.5rem;">⚠️ 功能相对有限</li>
              <li style="margin-bottom: 0.5rem;">⚠️ 更新较慢</li>
            </ul>
          </div>
        </div>
​
        <div class="card">
          <div class="card__header">
            <h3 class="card__title">Stylus</h3>
            <span class="badge badge--warning">小众</span>
          </div>
          <div class="card__body">
            <ul style="list-style: none; padding: 0;">
              <li style="margin-bottom: 0.5rem;">✅ 语法灵活</li>
              <li style="margin-bottom: 0.5rem;">✅ 表达能力强</li>
              <li style="margin-bottom: 0.5rem;">⚠️ 学习成本高</li>
              <li style="margin-bottom: 0.5rem;">⚠️ 社区较小</li>
              <li style="margin-bottom: 0.5rem;">⚠️ 工具支持有限</li>
            </ul>
          </div>
        </div>
      </section>
    </div>
​
    <script>
      // 复制代码功能
      function copyCode(button) {
        const codeBlock = button.closest('.code-block');
        const code = codeBlock.querySelector('code').textContent;
​
        navigator.clipboard
          .writeText(code)
          .then(() => {
            const originalText = button.textContent;
            button.textContent = '已复制!';
            button.style.background = 'var(--color-success)';
​
            setTimeout(() => {
              button.textContent = originalText;
              button.style.background = '';
            }, 2000);
          })
          .catch(() => {
            console.error('复制失败');
          });
      }
​
      // 按钮交互效果
      document.querySelectorAll('.btn').forEach((button) => {
        button.addEventListener('click', function () {
          if (!this.disabled) {
            this.style.transform = 'scale(0.95)';
            setTimeout(() => {
              this.style.transform = '';
            }, 150);
          }
        });
      });
​
      // 表单验证演示
      document.querySelectorAll('.form-input').forEach((input) => {
        input.addEventListener('blur', function () {
          if (
            this.value.trim() === '' &&
            !this.classList.contains('form-input--error')
          ) {
            this.style.borderColor = 'var(--color-warning)';
          } else if (this.value.trim() !== '') {
            this.style.borderColor = '';
          }
        });
​
        input.addEventListener('focus', function () {
          this.style.borderColor = '';
        });
      });
​
      // 深色模式切换演示
      const prefersDark = window.matchMedia('(prefers-color-scheme: dark)');
​
      function updateTheme(e) {
        console.log('主题模式:', e.matches ? '深色' : '浅色');
      }
​
      prefersDark.addEventListener('change', updateTheme);
      updateTheme(prefersDark);
​
      // 性能监控
      window.addEventListener('load', () => {
        const cssFiles = document.querySelectorAll(
          'link[rel="stylesheet"], style'
        );
        console.log(`样式文件数量: ${cssFiles.length}`);
​
        // 模拟预处理器构建信息
        const buildInfo = {
          preprocessor: 'Sass/SCSS',
          sourceFiles: 12,
          compiledSize: '45.2KB',
          gzippedSize: '8.7KB',
          buildTime: '1.23s',
        };
​
        console.log('构建信息:', buildInfo);
      });
    </script>
  </body>
</html>

效果展示:这个完整的样式系统演示了 CSS 预处理器的强大功能。包括组件系统、设计规范、响应式布局等。所有样式都通过预处理器的混入、变量、函数等特性构建,展现了企业级样式系统的最佳实践。

4. 高级预处理器技巧

4.1 动态样式生成

css 复制代码
// 动态主题生成
$themes: (
  'light': (
    'bg': #ffffff,
    'text': #333333,
    'primary': #3b82f6,
  ),
  'dark': (
    'bg': #1a1a1a,
    'text': #ffffff,
    'primary': #60a5fa,
  ),
);

@each $theme-name, $theme-colors in $themes {
  [data-theme='#{$theme-name}'] {
    @each $property, $color in $theme-colors {
      --color-#{$property}: #{$color};
    }
  }
}

// 响应式断点生成
$breakpoints: (
  'sm': 640px,
  'md': 768px,
  'lg': 1024px,
  'xl': 1280px,
);

@each $name, $size in $breakpoints {
  @media (min-width: $size) {
    .#{$name}:text-center {
      text-align: center;
    }

    .#{$name}:hidden {
      display: none;
    }
  }
}

4.2 高级函数库

js 复制代码
// 数学函数
@function pow($base, $exponent) {
  $result: 1;
  @for $i from 1 through $exponent {
    $result: $result * $base;
  }
  @return $result;
}

// 颜色工具函数
@function color-luminance($color) {
  $rgb: red($color), green($color), blue($color);
  $luminance: 0;

  @each $value in $rgb {
    $value: $value / 255;
    @if $value < 0.03928 {
      $value: $value / 12.92;
    } @else {
      $value: pow(($value + 0.055) / 1.055, 2.4);
    }
    $luminance: $luminance + $value;
  }

  @return $luminance;
}

// 智能对比色选择
@function smart-contrast($background, $threshold: 0.5) {
  $luminance: color-luminance($background);
  @if $luminance > $threshold {
    @return #000000; // 深色文字
  } @else {
    @return #ffffff; // 浅色文字
  }
}

4.3 组件架构模式

css 复制代码
// BEM 命名约定自动化
@mixin bem-element($element) {
  &__#{$element} {
    @content;
  }
}

@mixin bem-modifier($modifier) {
  &--#{$modifier} {
    @content;
  }
}

// 使用示例
.card {
  background: white;
  border-radius: 8px;

  @include bem-element('header') {
    padding: 1rem;
    border-bottom: 1px solid #eee;
  }

  @include bem-element('body') {
    padding: 1rem;
  }

  @include bem-modifier('featured') {
    border: 2px solid #3b82f6;
    box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3);
  }
}

总结

CSS 预处理器为现代样式开发提供了强大的工具:

  1. 丰富的编程特性:变量、函数、混入、循环等提升开发效率
  2. 完美的浏览器兼容性:编译后的 CSS 兼容所有浏览器
  3. 强大的代码组织能力:模块化、嵌套、继承等特性
  4. 活跃的生态系统:丰富的库、框架和工具支持
  5. 渐进式现代化:与现代 CSS 特性良好集成

选择建议

  • Sass/SCSS:功能最全面,社区最活跃,推荐大型项目使用
  • Less:语法简单,适合中小型项目和 CSS 初学者
  • Stylus:语法灵活,适合追求表达能力的开发者
  • PostCSS:现代化选择,与现有工具链集成度高

最佳实践

  • 建立统一的设计系统和命名规范
  • 合理使用混入避免代码重复
  • 利用函数实现复杂的样式计算
  • 配合现代构建工具优化开发体验
相关推荐
浩瀚地学3 分钟前
【面试算法笔记】0106-数组-区间和
笔记·算法·面试
To_OC8 小时前
别再串行写 await 了,Promise.all 才是并行请求的正确打开方式
前端·javascript·promise
vipbic8 小时前
中后台越做越乱后,我用插件化把它救回来了
前端·vue.js
Hyyy8 小时前
Computer Use 适合做什么,不适合做什么——一次真实使用后的思考
前端
小和尚同志9 小时前
前端 AI 单元测试思考与落地
前端·人工智能·aigc
invicinble10 小时前
c端系统,其实更像一个信息展示平台
前端
李姆斯11 小时前
管理是否可以被完全量化
前端·产品经理·团队管理
名字还没想好☜11 小时前
Next.js 中间件实战:鉴权、重定向与 A/B 分流
开发语言·前端·javascript·中间件·react·next.js
广州灵眸科技有限公司12 小时前
瑞芯微RV1126B开发板(EASY-EAI-PI2) INI文件操作
java·前端·javascript·网络·人工智能
kaiking_g12 小时前
vue项目中,静态导入 vs 动态导入 详解
前端·javascript·vue.js