深度解析

Functions in CSS?! 原来 CSS 也能这么强大

深入探索 CSS 函数的强大能力,从内置函数到即将到来的自定义函数,重新认识现代 CSS

2025年12月6日18 分钟1140 阅读
CSS函数式编程现代CSSCSS Houdini
Functions in CSS?! 原来 CSS 也能这么强大

Functions in CSS?! 原来 CSS 也能这么强大

CSS 早已不是简单的样式声明语言。随着现代 CSS 的发展,函数式编程的思想已经深入 CSS 的各个角落。从计算函数到颜色函数,从自定义属性到即将到来的 @function 规则,CSS 正在变得越来越强大。

CSS 函数概览

CSS 函数是一种特殊的值类型,它接受参数并返回计算后的结果。现代 CSS 已经拥有超过 50 个内置函数:

css
/* CSS 函数的基本形式 */
property: function-name(argument1, argument2, ...);

/* 函数可以嵌套使用 */
property: outer-function(inner-function(value));

函数分类速览

类别函数用途
数学函数calc(), min(), max(), clamp()动态计算值
颜色函数rgb(), hsl(), oklch(), color-mix()颜色定义与混合
图形函数linear-gradient(), radial-gradient()渐变背景
变换函数translate(), rotate(), scale()元素变换
滤镜函数blur(), brightness(), contrast()视觉效果
形状函数circle(), polygon(), path()裁剪路径
引用函数var(), attr(), url()值引用

数学函数:动态计算的基石

calc() - 万能计算器

calc() 是 CSS 中最常用的函数,支持混合单位计算:

css
.container {
  /* 混合单位计算 */
  width: calc(100% - 2rem);
  
  /* 嵌套计算 */
  padding: calc(var(--base-spacing) * 2);
  
  /* 复杂表达式 */
  margin-top: calc((100vh - var(--header-height)) / 2);
}

/* 响应式字体大小 */
.fluid-text {
  /* 基础大小 + 视口相关增量 */
  font-size: calc(1rem + 0.5vw);
}

/* 网格布局计算 */
.grid-item {
  /* 考虑间距的列宽 */
  width: calc((100% - 3 * var(--gap)) / 4);
}

min() 和 max() - 响应式边界

css
.responsive-container {
  /* 最大不超过 1200px,最小不小于内容宽度 */
  width: min(100% - 2rem, 1200px);
  
  /* 确保最小可读性 */
  font-size: max(16px, 1vw);
  
  /* 嵌套使用 */
  padding: min(max(1rem, 3vw), 3rem);
}

/* 响应式间距 */
.section {
  padding-block: min(10vh, 100px);
  gap: max(1rem, 2vw);
}

clamp() - 一函数搞定响应式

clamp(min, preferred, max) 是响应式设计的利器:

css
/* 流体排版系统 */
:root {
  /* 标题:24px - 5vw - 48px */
  --heading-1: clamp(1.5rem, 4vw + 1rem, 3rem);
  --heading-2: clamp(1.25rem, 3vw + 0.5rem, 2.25rem);
  --heading-3: clamp(1.125rem, 2vw + 0.5rem, 1.75rem);
  
  /* 正文 */
  --body-text: clamp(1rem, 1vw + 0.75rem, 1.25rem);
  
  /* 间距 */
  --space-sm: clamp(0.5rem, 1vw, 1rem);
  --space-md: clamp(1rem, 3vw, 2rem);
  --space-lg: clamp(2rem, 5vw, 4rem);
}

h1 { font-size: var(--heading-1); }
h2 { font-size: var(--heading-2); }
p { font-size: var(--body-text); }

/* 响应式容器 */
.container {
  width: clamp(320px, 90vw, 1400px);
  padding-inline: clamp(1rem, 5vw, 3rem);
}

高级数学函数(CSS Values Level 4)

css
/* 三角函数 */
.circular-motion {
  --angle: 45deg;
  transform: translate(
    calc(cos(var(--angle)) * 100px),
    calc(sin(var(--angle)) * 100px)
  );
}

/* 指数和对数 */
.exponential-scale {
  --level: 3;
  font-size: calc(1rem * pow(1.25, var(--level)));
}

/* 取整函数 */
.grid-aligned {
  width: round(nearest, 100%, 8px); /* 对齐到 8px 网格 */
}

/* 符号和绝对值 */
.dynamic-spacing {
  --offset: -20px;
  margin: abs(var(--offset)); /* 始终为正值 */
}

颜色函数:从 RGB 到 OKLCH

传统颜色函数

css
.traditional-colors {
  /* RGB/RGBA */
  color: rgb(59, 130, 246);
  background: rgba(59, 130, 246, 0.5);
  
  /* HSL/HSLA - 更直观的颜色模型 */
  color: hsl(217, 91%, 60%);
  background: hsla(217, 91%, 60%, 0.5);
  
  /* 现代语法(空格分隔 + 斜杠透明度)*/
  color: rgb(59 130 246);
  background: rgb(59 130 246 / 0.5);
  color: hsl(217 91% 60% / 0.8);
}

现代颜色空间

css
/* OKLCH - 感知均匀的颜色空间 */
:root {
  /* oklch(亮度 色度 色相 / 透明度) */
  --primary: oklch(0.6 0.15 250);      /* 蓝色 */
  --primary-light: oklch(0.8 0.1 250); /* 浅蓝 */
  --primary-dark: oklch(0.4 0.15 250); /* 深蓝 */
  
  /* 通过调整亮度生成色阶 */
  --gray-100: oklch(0.95 0 0);
  --gray-200: oklch(0.90 0 0);
  --gray-300: oklch(0.80 0 0);
  --gray-400: oklch(0.70 0 0);
  --gray-500: oklch(0.60 0 0);
  --gray-600: oklch(0.50 0 0);
  --gray-700: oklch(0.40 0 0);
  --gray-800: oklch(0.30 0 0);
  --gray-900: oklch(0.20 0 0);
}

/* Lab 颜色空间 */
.lab-colors {
  background: lab(50% 40 60);
  color: lch(70% 50 180);
}

color-mix() - 颜色混合

css
/* 基础混合 */
.color-mixing {
  /* 在 sRGB 空间混合 */
  background: color-mix(in srgb, #3b82f6, white 20%);
  
  /* 在 OKLCH 空间混合(更平滑的过渡)*/
  background: color-mix(in oklch, var(--primary), black 30%);
}

/* 动态主题色阶 */
:root {
  --brand: #3b82f6;
  
  --brand-50: color-mix(in oklch, var(--brand), white 90%);
  --brand-100: color-mix(in oklch, var(--brand), white 80%);
  --brand-200: color-mix(in oklch, var(--brand), white 60%);
  --brand-300: color-mix(in oklch, var(--brand), white 40%);
  --brand-400: color-mix(in oklch, var(--brand), white 20%);
  --brand-500: var(--brand);
  --brand-600: color-mix(in oklch, var(--brand), black 20%);
  --brand-700: color-mix(in oklch, var(--brand), black 40%);
  --brand-800: color-mix(in oklch, var(--brand), black 60%);
  --brand-900: color-mix(in oklch, var(--brand), black 80%);
}

/* 悬停效果 */
.button {
  background: var(--brand-500);
  
  &:hover {
    background: color-mix(in oklch, var(--brand-500), white 15%);
  }
  
  &:active {
    background: color-mix(in oklch, var(--brand-500), black 15%);
  }
}

相对颜色语法

css
/* 基于现有颜色创建变体 */
:root {
  --primary: #3b82f6;
  
  /* 调整亮度 */
  --primary-light: oklch(from var(--primary) calc(l + 0.2) c h);
  --primary-dark: oklch(from var(--primary) calc(l - 0.2) c h);
  
  /* 调整饱和度 */
  --primary-muted: oklch(from var(--primary) l calc(c * 0.5) h);
  --primary-vivid: oklch(from var(--primary) l calc(c * 1.5) h);
  
  /* 调整透明度 */
  --primary-transparent: oklch(from var(--primary) l c h / 0.5);
  
  /* 色相旋转 */
  --complement: oklch(from var(--primary) l c calc(h + 180));
  --triadic-1: oklch(from var(--primary) l c calc(h + 120));
  --triadic-2: oklch(from var(--primary) l c calc(h + 240));
}

自定义属性函数:var() 的高级用法

基础用法与回退值

css
:root {
  --primary: #3b82f6;
  --spacing: 1rem;
}

.component {
  /* 基础使用 */
  color: var(--primary);
  
  /* 带回退值 */
  background: var(--bg-color, white);
  
  /* 嵌套回退 */
  padding: var(--custom-padding, var(--spacing, 16px));
}

动态计算系统

css
/* 基于变量的设计系统 */
:root {
  --base-size: 4px;
  --scale-ratio: 1.25;
}

/* 间距系统 */
.spacing-system {
  --space-1: var(--base-size);
  --space-2: calc(var(--base-size) * 2);
  --space-3: calc(var(--base-size) * 3);
  --space-4: calc(var(--base-size) * 4);
  --space-6: calc(var(--base-size) * 6);
  --space-8: calc(var(--base-size) * 8);
  --space-12: calc(var(--base-size) * 12);
  --space-16: calc(var(--base-size) * 16);
}

/* 类型比例尺 */
.type-scale {
  --text-xs: calc(1rem / var(--scale-ratio) / var(--scale-ratio));
  --text-sm: calc(1rem / var(--scale-ratio));
  --text-base: 1rem;
  --text-lg: calc(1rem * var(--scale-ratio));
  --text-xl: calc(1rem * var(--scale-ratio) * var(--scale-ratio));
  --text-2xl: calc(1rem * var(--scale-ratio) * var(--scale-ratio) * var(--scale-ratio));
}

条件样式与状态管理

css
/* 使用空间切换技巧实现条件样式 */
.toggle-button {
  --is-active: 0; /* 0 = false, 1 = true */
  
  background: hsl(
    calc(200 + var(--is-active) * 20)
    calc(50% + var(--is-active) * 30%)
    calc(50% + var(--is-active) * 10%)
  );
  
  transform: scale(calc(1 + var(--is-active) * 0.05));
}

.toggle-button[aria-pressed="true"] {
  --is-active: 1;
}

/* 主题切换 */
:root {
  --is-dark: 0;
  
  --bg: hsl(0 0% calc(100% - var(--is-dark) * 90%));
  --text: hsl(0 0% calc(var(--is-dark) * 90%));
}

[data-theme="dark"] {
  --is-dark: 1;
}

渐变函数:视觉魔法

线性渐变高级技巧

css
/* 多色渐变 */
.multi-color {
  background: linear-gradient(
    135deg,
    #667eea 0%,
    #764ba2 25%,
    #f093fb 50%,
    #f5576c 75%,
    #ffd93d 100%
  );
}

/* 硬边渐变(条纹)*/
.stripes {
  background: linear-gradient(
    45deg,
    #3b82f6 25%,
    transparent 25%,
    transparent 50%,
    #3b82f6 50%,
    #3b82f6 75%,
    transparent 75%
  );
  background-size: 20px 20px;
}

/* 渐变文字 */
.gradient-text {
  background: linear-gradient(135deg, #667eea, #764ba2);
  background-clip: text;
  -webkit-background-clip: text;
  color: transparent;
}

径向和锥形渐变

css
/* 径向渐变 */
.radial-examples {
  /* 聚光灯效果 */
  background: radial-gradient(
    circle at 30% 30%,
    rgba(255,255,255,0.3) 0%,
    transparent 60%
  );
  
  /* 椭圆渐变 */
  background: radial-gradient(
    ellipse 80% 50% at center,
    #3b82f6,
    transparent
  );
}

/* 锥形渐变 */
.conic-examples {
  /* 饼图效果 */
  background: conic-gradient(
    #3b82f6 0deg 120deg,
    #10b981 120deg 240deg,
    #f59e0b 240deg 360deg
  );
  
  /* 彩虹圆环 */
  background: conic-gradient(
    from 45deg,
    red, orange, yellow, green, blue, purple, red
  );
  
  /* 扫描效果 */
  background: conic-gradient(
    from var(--angle),
    transparent 0deg,
    #3b82f6 30deg,
    transparent 60deg
  );
}

变换函数:2D 和 3D

css
/* 2D 变换 */
.transform-2d {
  /* 单独使用 */
  transform: translateX(100px);
  transform: rotate(45deg);
  transform: scale(1.5);
  transform: skewX(10deg);
  
  /* 组合变换(顺序重要!)*/
  transform: translate(-50%, -50%) rotate(45deg) scale(1.2);
}

/* 3D 变换 */
.transform-3d {
  transform-style: preserve-3d;
  perspective: 1000px;
  
  transform: 
    rotateX(30deg)
    rotateY(45deg)
    translateZ(100px);
}

/* 翻转卡片效果 */
.flip-card {
  perspective: 1000px;
  
  .card-inner {
    transform-style: preserve-3d;
    transition: transform 0.6s;
  }
  
  &:hover .card-inner {
    transform: rotateY(180deg);
  }
  
  .card-front,
  .card-back {
    backface-visibility: hidden;
  }
  
  .card-back {
    transform: rotateY(180deg);
  }
}

滤镜函数:图像处理

css
/* 单个滤镜 */
.filter-single {
  filter: blur(5px);
  filter: brightness(1.2);
  filter: contrast(1.5);
  filter: grayscale(100%);
  filter: hue-rotate(90deg);
  filter: saturate(2);
  filter: sepia(100%);
  filter: drop-shadow(0 4px 6px rgba(0,0,0,0.3));
}

/* 组合滤镜 */
.filter-combo {
  filter: 
    brightness(1.1)
    contrast(1.1)
    saturate(1.2);
}

/* 实用滤镜预设 */
.vintage {
  filter: sepia(0.4) contrast(1.1) brightness(0.9) saturate(0.8);
}

.cinematic {
  filter: contrast(1.2) saturate(0.8) brightness(0.95);
}

.dreamy {
  filter: blur(1px) brightness(1.1) saturate(1.3);
}

/* 背景模糊 */
.glass-effect {
  backdrop-filter: blur(10px) saturate(180%);
  background: rgba(255, 255, 255, 0.2);
}

即将到来:@function 自定义函数

CSS 正在引入真正的自定义函数能力,这将彻底改变 CSS 的编写方式:

css
/* CSS 自定义函数(提案阶段)*/
@function --fluid-size(--min, --max, --min-vw: 320px, --max-vw: 1200px) {
  --slope: calc((var(--max) - var(--min)) / (var(--max-vw) - var(--min-vw)));
  --intercept: calc(var(--min) - var(--slope) * var(--min-vw));
  
  @return clamp(
    var(--min),
    calc(var(--intercept) + var(--slope) * 100vw),
    var(--max)
  );
}

/* 使用自定义函数 */
h1 {
  font-size: --fluid-size(24px, 48px);
}

/* 颜色操作函数 */
@function --lighten(--color, --amount: 10%) {
  @return color-mix(in oklch, var(--color), white var(--amount));
}

@function --darken(--color, --amount: 10%) {
  @return color-mix(in oklch, var(--color), black var(--amount));
}

.button {
  background: var(--primary);
  
  &:hover {
    background: --lighten(var(--primary), 15%);
  }
}

/* 间距计算函数 */
@function --space(--multiplier) {
  @return calc(var(--base-spacing, 4px) * var(--multiplier));
}

.card {
  padding: --space(4);
  margin-bottom: --space(6);
  gap: --space(2);
}

实战:构建设计系统

css
/* 完整的函数式设计系统 */
:root {
  /* 基础配置 */
  --base-size: 4px;
  --base-font: 16px;
  --scale: 1.25;
  
  /* 颜色系统 */
  --hue-primary: 220;
  --hue-success: 142;
  --hue-warning: 38;
  --hue-error: 0;
  
  /* 生成颜色 */
  --primary: oklch(0.55 0.15 var(--hue-primary));
  --success: oklch(0.55 0.15 var(--hue-success));
  --warning: oklch(0.55 0.15 var(--hue-warning));
  --error: oklch(0.55 0.15 var(--hue-error));
  
  /* 间距比例尺 */
  --space-1: var(--base-size);
  --space-2: calc(var(--base-size) * 2);
  --space-3: calc(var(--base-size) * 3);
  --space-4: calc(var(--base-size) * 4);
  --space-5: calc(var(--base-size) * 5);
  --space-6: calc(var(--base-size) * 6);
  --space-8: calc(var(--base-size) * 8);
  --space-10: calc(var(--base-size) * 10);
  --space-12: calc(var(--base-size) * 12);
  --space-16: calc(var(--base-size) * 16);
  
  /* 字体比例尺 */
  --text-xs: calc(var(--base-font) / var(--scale) / var(--scale));
  --text-sm: calc(var(--base-font) / var(--scale));
  --text-base: var(--base-font);
  --text-lg: calc(var(--base-font) * var(--scale));
  --text-xl: calc(var(--base-font) * var(--scale) * var(--scale));
  --text-2xl: calc(var(--base-font) * var(--scale) * var(--scale) * var(--scale));
  --text-3xl: calc(var(--base-font) * var(--scale) * var(--scale) * var(--scale) * var(--scale));
  
  /* 流体字体 */
  --fluid-sm: clamp(var(--text-xs), 0.8vw + 0.5rem, var(--text-sm));
  --fluid-base: clamp(var(--text-sm), 1vw + 0.5rem, var(--text-base));
  --fluid-lg: clamp(var(--text-base), 1.5vw + 0.5rem, var(--text-lg));
  --fluid-xl: clamp(var(--text-lg), 2vw + 0.5rem, var(--text-xl));
  --fluid-2xl: clamp(var(--text-xl), 3vw + 0.5rem, var(--text-2xl));
  
  /* 圆角 */
  --radius-sm: calc(var(--base-size) * 1);
  --radius-md: calc(var(--base-size) * 2);
  --radius-lg: calc(var(--base-size) * 3);
  --radius-xl: calc(var(--base-size) * 4);
  --radius-full: 9999px;
  
  /* 阴影 */
  --shadow-sm: 0 1px 2px color-mix(in oklch, black, transparent 95%);
  --shadow-md: 0 4px 6px color-mix(in oklch, black, transparent 90%);
  --shadow-lg: 0 10px 15px color-mix(in oklch, black, transparent 85%);
  --shadow-xl: 0 20px 25px color-mix(in oklch, black, transparent 80%);
}

/* 组件示例 */
.button {
  padding: var(--space-2) var(--space-4);
  font-size: var(--fluid-base);
  border-radius: var(--radius-md);
  background: var(--primary);
  color: white;
  box-shadow: var(--shadow-sm);
  transition: all 0.2s ease;
  
  &:hover {
    background: color-mix(in oklch, var(--primary), white 15%);
    box-shadow: var(--shadow-md);
    transform: translateY(-1px);
  }
  
  &:active {
    background: color-mix(in oklch, var(--primary), black 10%);
    transform: translateY(0);
  }
}

.card {
  padding: var(--space-6);
  border-radius: var(--radius-lg);
  background: white;
  box-shadow: var(--shadow-md);
  
  .card-title {
    font-size: var(--fluid-lg);
    margin-bottom: var(--space-2);
  }
  
  .card-content {
    font-size: var(--fluid-base);
    color: color-mix(in oklch, black, transparent 40%);
  }
}

浏览器兼容性与渐进增强

css
/* 使用 @supports 检测功能支持 */
.modern-color {
  /* 回退值 */
  background: #3b82f6;
  
  /* 现代浏览器 */
  @supports (background: oklch(0.5 0.15 250)) {
    background: oklch(0.5 0.15 250);
  }
}

/* color-mix 回退 */
.hover-effect {
  background: #3b82f6;
  
  &:hover {
    background: #60a5fa; /* 手动计算的回退值 */
    
    @supports (background: color-mix(in oklch, red, blue)) {
      background: color-mix(in oklch, #3b82f6, white 20%);
    }
  }
}

/* 相对颜色语法回退 */
:root {
  --primary: #3b82f6;
  --primary-light: #60a5fa; /* 回退值 */
  
  @supports (color: oklch(from red l c h)) {
    --primary-light: oklch(from var(--primary) calc(l + 0.15) c h);
  }
}

总结

"

CSS 函数已经从简单的 url() 和 rgb() 发展成为一个完整的函数式编程体系。掌握这些函数,你就能用更少的代码实现更强大、更灵活的样式系统。

CSS 函数的演进历程:

2010s: rgb(), url(), linear-gradient()
         ↓
2015s: calc(), var()
         ↓
2020s: min(), max(), clamp(), color-mix()
         ↓
2025+: @function, oklch(), 相对颜色语法

现代 CSS 已经不再是「只能写静态样式」的语言。通过合理运用函数,我们可以构建出响应式、可维护、高性能的设计系统。拥抱 CSS 函数,让你的样式代码更加优雅强大!

文章标签

# CSS# 函数式编程# 现代CSS# CSS Houdini
返回首页