前言
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 预处理器为现代样式开发提供了强大的工具:
- 丰富的编程特性:变量、函数、混入、循环等提升开发效率
- 完美的浏览器兼容性:编译后的 CSS 兼容所有浏览器
- 强大的代码组织能力:模块化、嵌套、继承等特性
- 活跃的生态系统:丰富的库、框架和工具支持
- 渐进式现代化:与现代 CSS 特性良好集成
选择建议:
- Sass/SCSS:功能最全面,社区最活跃,推荐大型项目使用
- Less:语法简单,适合中小型项目和 CSS 初学者
- Stylus:语法灵活,适合追求表达能力的开发者
- PostCSS:现代化选择,与现有工具链集成度高
最佳实践:
- 建立统一的设计系统和命名规范
- 合理使用混入避免代码重复
- 利用函数实现复杂的样式计算
- 配合现代构建工具优化开发体验