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 小时前
Vue3组件二次封装终极指南:动态组件+h函数的优雅实现
前端·vue.js
皮皮虾我们跑3 小时前
前端HTML常用基础标
前端·javascript·html
Yeats_Liao3 小时前
Go Web 编程快速入门 01 - 环境准备与第一个 Web 应用
开发语言·前端·golang
卓码软件测评3 小时前
第三方CMA软件测试机构:页面JavaScript动态渲染生成内容对网站SEO的影响
开发语言·前端·javascript·ecmascript
Mintopia4 小时前
📚 Next.js 分页 & 模糊搜索:在无限数据海里优雅地翻页
前端·javascript·全栈
Mintopia4 小时前
⚖️ AIGC版权确权技术:Web内容的AI生成标识与法律适配
前端·javascript·aigc
周家大小姐.4 小时前
vue实现模拟deepseekAI功能
前端·javascript·vue.js
我是华为OD~HR~栗栗呀4 小时前
华为OD-23届考研-测试面经
java·c++·python·华为od·华为·面试·单元测试