Appearance
Sass 内置函数库
Sass提供了丰富的内置函数库,涵盖了颜色操作、数值计算、字符串处理、列表操作等多个方面。本章将详细介绍Sass的各种内置函数及其用法。
颜色函数
颜色调节函数
scss
// 颜色定义
$base-color: #3498db;
// 明度调整
$lighter: lighten($base-color, 20%); // #80c5e6 - 变亮20%
$darker: darken($base-color, 20%); // #1d689e - 变暗20%
// 饱和度调整
$more-saturated: saturate($base-color, 20%); // 增加饱和度
$less-saturated: desaturate($base-color, 20%); // 降低饱和度
$grayscale: grayscale($base-color); // 灰度化
// 透明度调整
$semi-transparent: fade-in(rgba($base-color, 0.3), 0.2); // 增加透明度 -> rgba(#3498db, 0.5)
$more-transparent: fade-out(rgba($base-color, 0.8), 0.3); // 降低透明度 -> rgba(#3498db, 0.5)
$set-alpha: fade(rgba($base-color, 0.7), 0.5); // 设置透明度 -> rgba(#3498db, 0.5)
// 色调调整
$shifted-hue: adjust-hue($base-color, 30deg); // 调整色调30度
$opposite: complement($base-color); // 互补色
// 颜色反转
$inverted: invert($base-color); // 颜色反转
// 示例:创建颜色变体
$primary: #007bff;
.color-palette {
@for $i from 1 through 10 {
$amount: ($i - 1) * 10;
&--light-#{$amount} {
background-color: if($i <= 5,
lighten($primary, (6 - $i) * 10%),
darken($primary, ($i - 5) * 10%)
);
}
}
}
颜色创建和分解函数
scss
// 颜色创建
$hsl-color: hsl(240, 100%, 50%); // HSL创建
$hsla-color: hsla(240, 100%, 50%, 0.8); // HSLA创建
$rgb-color: rgb(52, 152, 219); // RGB创建
$rgba-color: rgba(52, 152, 219, 0.8); // RGBA创建
// 颜色分量提取
$red: red(#ff6b6b); // 255 (红色分量)
$green: green(#ff6b6b); // 107 (绿色分量)
$blue: blue(#ff6b6b); // 107 (蓝色分量)
$hue: hue(hsl(240, 100%, 50%)); // 240deg (色调)
$saturation: saturation(hsl(240, 100%, 50%)); // 100% (饱和度)
$lightness: lightness(hsl(240, 100%, 50%)); // 50% (明度)
$alpha: alpha(rgba(255, 0, 0, 0.5)); // 0.5 (透明度)
// 颜色操作
$mixed: mix(#ff0000, #0000ff, 30%); // 混合颜色,30%红色,70%蓝色
$adjust-red: adjust-color(#ff6b6b, $red: -50); // 调整红色分量
$scale-color: scale-color(#ff6b6b, $lightness: 20%); // 按比例调整明度
$change-color: change-color(#ff6b6b, $hue: 180); // 改变色调
// 颜色验证
$is-light: lightness(#f0f0f0) > 50%; // true
$is-dark: lightness(#333) < 50%; // true
// 创建配色方案
@function analogous-colors($color, $angle: 30deg) {
@return (
'analogous1': adjust-hue($color, -$angle),
'analogous2': adjust-hue($color, $angle),
'triadic1': adjust-hue($color, 120deg),
'triadic2': adjust-hue($color, 240deg)
);
}
$base-color: #3498db;
$color-scheme: analogous-colors($base-color);
.analogous-colors {
.color1 { background-color: map-get($color-scheme, 'analogous1'); }
.color2 { background-color: map-get($color-scheme, 'analogous2'); }
.triadic1 { background-color: map-get($color-scheme, 'triadic1'); }
.triadic2 { background-color: map-get($color-scheme, 'triadic2'); }
}
数值函数
基本数值函数
scss
// 四舍五入函数
$rounded: round(10.7); // 11
$floored: floor(10.7); // 10
$ceiled: ceil(10.1); // 11
// 绝对值
$abs-val: abs(-15); // 15
// 最大值和最小值
$max-val: max(10, 20, 15); // 20
$min-val: min(10, 20, 15); // 10
// 百分比转换
$ratio: 50px / 100px; // 0.5
$percent: percentage($ratio); // 50%
// 随机数
$rand-float: random(); // 0到1之间的随机数
$rand-int: random(100); // 1到100之间的随机整数
// 数值运算示例
$base-font: 16px;
$multiplier: 1.25;
$calculated: $base-font * $multiplier; // 20px
.element {
font-size: $calculated;
margin: ($base-font / 2) 0; // 8px 0
}
// 创建动态计算函数
@function fibonacci($n) {
@if $n <= 1 {
@return $n;
}
@return fibonacci($n - 1) + fibonacci($n - 2);
}
// 黄金比例计算
@function golden-ratio($value, $increment: 1) {
$phi: 1.618033988749895;
@return $value * pow($phi, $increment);
}
@function pow($number, $exponent) {
@if $exponent == 0 { @return 1; }
$result: $number;
@for $i from 1 to abs($exponent) {
$result: $result * $number;
}
@if $exponent < 0 { $result: 1 / $result; }
@return $result;
}
.golden-typography {
h1 { font-size: golden-ratio(1rem, 3); } // ~4.236rem
h2 { font-size: golden-ratio(1rem, 2); } // ~2.618rem
h3 { font-size: golden-ratio(1rem, 1); } // ~1.618rem
h4 { font-size: golden-ratio(1rem, 0); } // 1rem
}
单位处理函数
scss
// 获取单位
$unit: unit(10px); // 'px'
$unitless: unitless(10); // true
$not-unitless: unitless(10px); // false
// 单位转换示例
@function convert-to-rem($px, $base: 16px) {
@if unitless($px) {
@warn '#{$px} has no units, assuming pixels.';
$px: $px * 1px;
}
@if unit($px) != 'px' {
@warn 'Expected pixels, got #{unit($px)}.';
}
@return ($px / $base) * 1rem;
}
// 使用单位转换函数
.typography {
font-size: convert-to-rem(18px); // 1.125rem
line-height: convert-to-rem(24px); // 1.5rem
margin: convert-to-rem(16px) 0; // 1rem 0
}
// 单位验证
$dimension: 2em;
$has-unit: not(unitless($dimension)); // true
字符串函数
基本字符串操作
scss
// 字符串拼接和插值
$prefix: 'btn';
$suffix: 'primary';
$full-class: '#{$prefix}-#{$suffix}'; // 'btn-primary'
// 大小写转换
$original: 'Hello World';
$upper: to-upper-case($original); // 'HELLO WORLD'
$lower: to-lower-case($original); // 'hello world'
// 字符串搜索
$search: str-index('Hello World', 'Wor'); // 7 (位置)
$not-found: str-index('Hello World', 'xyz'); // null
// 字符串截取
$slice: str-slice('Hello World', 1, 5); // 'Hello'
$rest: str-slice('Hello World', 7); // 'World'
// 字符串长度
$length: str-length('Hello'); // 5
// 实际应用示例
@function add-prefix($name, $prefix: 'my') {
@return '#{$prefix}-#{$name}';
}
$components: ('button', 'input', 'card');
@each $comp in $components {
.#{add-prefix($comp, 'ui')} {
padding: 1rem;
border: 1px solid #ddd;
}
}
// 生成带前缀的类名
.string-operations {
$base-class: 'component';
$modifier: 'active';
&__#{$base-class} {
background-color: #f8f9fa;
&--#{$modifier} {
background-color: #007bff;
color: white;
}
}
}
CSS标识符处理
scss
// 引号处理
$quoted: quote('Hello'); // 'Hello' (加上引号)
$unquoted: unquote('.class'); // .class (去掉引号)
// 用于CSS属性或选择器
$property: 'transform';
$value: 'rotate(45deg)';
.element {
#{$property}: #{$value}; // transform: rotate(45deg);
}
// 动态属性名
@mixin dynamic-property($prop, $value) {
#{$prop}: $value;
}
.animated {
@include dynamic-property('animation', 'spin 2s linear infinite');
@include dynamic-property('transform', 'rotate(45deg)');
}
列表函数
列表创建和访问
scss
// 列表定义
$colors: red, green, blue; // 逗号分隔
$dimensions: 10px 20px 30px 40px; // 空格分隔
$single-item: (single-item,); // 单元素列表
// 列表长度
$length: length($colors); // 3
// 获取特定元素
$first: nth($colors, 1); // red
$last: nth($colors, -1); // blue
// 检查列表分隔符
$separator: list-separator($colors); // comma
$space-sep: list-separator($dimensions); // space
// 列表操作
$extended: append($colors, yellow); // red, green, blue, yellow
$joined: join($colors, (purple, orange)); // red, green, blue, purple, orange
// 生成网格类
$grid-columns: 1 2 3 4 5 6 7 8 9 10 11 12;
@each $col in $grid-columns {
.col-#{$col} {
width: percentage($col / 12);
}
}
// 响应式网格
$breakpoints: (sm, md, lg, xl);
@each $bp in $breakpoints {
@each $col in $grid-columns {
.col-#{$bp}-#{$col} {
@media (min-width: map-get((sm: 576px, md: 768px, lg: 992px, xl: 1200px), $bp)) {
width: percentage($col / 12);
}
}
}
}
高级列表操作
scss
// 索引查找
$colors: red, green, blue, green;
$index: index($colors, blue); // 3
$first-green: index($colors, green); // 2 (第一个匹配项)
// 列表替换
@function replace-in-list($list, $old, $new) {
$result: ();
@for $i from 1 through length($list) {
$current: nth($list, $i);
$result: append($result, if($current == $old, $new, $current));
}
@return $result;
}
$original: red, blue, green, blue;
$modified: replace-in-list($original, blue, yellow); // red, yellow, green, yellow
// 列表筛选函数
@function filter-list($list, $callback) {
$result: ();
@for $i from 1 through length($list) {
$item: nth($list, $i);
@if call($callback, $item) {
$result: append($result, $item);
}
}
@return $result;
}
// 生成按钮变体
$button-types: (primary, secondary, success, danger, warning, info);
@each $type in $button-types {
.btn-#{$type} {
@if $type == 'primary' {
background-color: #007bff;
border-color: #007bff;
} @else if $type == 'secondary' {
background-color: #6c757d;
border-color: #6c757d;
} @else if $type == 'success' {
background-color: #28a745;
border-color: #28a745;
} @else if $type == 'danger' {
background-color: #dc3545;
border-color: #dc3545;
} @else if $type == 'warning' {
background-color: #ffc107;
border-color: #ffc107;
color: #212529;
} @else {
background-color: #17a2b8;
border-color: #17a2b8;
}
color: if(index('warning info', $type), #212529, white);
&:hover {
@if $type == 'primary' {
background-color: darken(#007bff, 10%);
border-color: darken(#007bff, 10%);
} @else if $type == 'secondary' {
background-color: darken(#6c757d, 10%);
border-color: darken(#6c757d, 10%);
} @else if $type == 'success' {
background-color: darken(#28a745, 10%);
border-color: darken(#28a745, 10%);
} @else if $type == 'danger' {
background-color: darken(#dc3545, 10%);
border-color: darken(#dc3545, 10%);
} @else if $type == 'warning' {
background-color: darken(#ffc107, 10%);
border-color: darken(#ffc107, 10%);
} @else {
background-color: darken(#17a2b8, 10%);
border-color: darken(#17a2b8, 10%);
}
}
}
}
映射函数
映射操作
scss
// 映射定义
$theme: (
colors: (
primary: #007bff,
secondary: #6c757d,
success: #28a745,
danger: #dc3545
),
spacing: (
xs: 0.25rem,
sm: 0.5rem,
md: 1rem,
lg: 1.5rem,
xl: 2rem
),
breakpoints: (
sm: 576px,
md: 768px,
lg: 992px,
xl: 1200px
)
);
// 映射访问
$primary-color: map-get(map-get($theme, colors), primary); // #007bff
$large-spacing: map-get(map-get($theme, spacing), lg); // 1.5rem
// 安全访问函数
@function safe-get($map, $keys...) {
@each $key in $keys {
$map: map-get($map, $key);
@if $map == null {
@return null;
}
}
@return $map;
}
$safe-color: safe-get($theme, colors, primary); // #007bff
$missing-color: safe-get($theme, colors, missing); // null
// 映射键和值
$color-keys: map-keys(map-get($theme, colors)); // primary, secondary, success, danger
$color-values: map-values(map-get($theme, colors)); // #007bff, #6c757d, #28a745, #dc3545
// 映射合并
$additional-colors: (
warning: #ffc107,
info: #17a2b8
);
$merged-colors: map-merge(map-get($theme, colors), $additional-colors);
// 键存在检查
$has-primary: map-has-key(map-get($theme, colors), primary); // true
$has-missing: map-has-key(map-get($theme, colors), missing); // false
// 遍历映射
@each $name, $color in map-get($theme, colors) {
.text-#{$name} {
color: $color;
}
.bg-#{$name} {
background-color: $color;
}
.border-#{$name} {
border-color: $color;
}
}
映射实用工具
scss
// 映射转换函数
@function map-reverse($map) {
$result: ();
@each $key, $value in $map {
$result: map-merge($result, ($value: $key));
}
@return $result;
}
$color-map: (
'primary': #007bff,
'secondary': #6c757d,
'success': #28a745
);
$reversed: map-reverse($color-map); // (#007bff: 'primary', #6c757d: 'secondary', #28a745: 'success')
// 映射过滤函数
@function map-filter($map, $predicate) {
$result: ();
@each $key, $value in $map {
@if call($predicate, $key, $value) {
$result: map-merge($result, ($key: $value));
}
}
@return $result;
}
$all-colors: (
'primary': #007bff,
'secondary': #6c757d,
'light': #f8f9fa,
'dark': #343a40
);
// 只保留暗色
@function is-dark-color($key, $color) {
@return lightness($color) < 50%;
}
$dark-colors: map-filter($all-colors, is-dark-color); // ('secondary': #6c757d, 'dark': #343a40)
// 生成响应式类
@each $name, $breakpoint in map-get($theme, breakpoints) {
.hidden-#{$name}-up {
@media (min-width: $breakpoint) {
display: none !important;
}
}
.visible-#{$name}-up {
@media (min-width: $breakpoint) {
display: block !important;
}
}
}
类型检查函数
类型检测
scss
// 检查值的类型
@function get-type($value) {
@return type-of($value);
}
$test-values: (
'number': 123,
'string': 'hello',
'color': #ff0000,
'bool': true,
'list': (1, 2, 3),
'map': (key: value),
'null': null
);
// 类型检查示例
@each $name, $value in $test-values {
$type: type-of($value);
.type-#{$name} {
content: 'Type: #{$type}';
}
}
// 实用类型检查函数
@function is-number($value) {
@return type-of($value) == 'number';
}
@function is-string($value) {
@return type-of($value) == 'string';
}
@function is-color($value) {
@return type-of($value) == 'color';
}
@function is-list($value) {
@return type-of($value) == 'list';
}
@function is-map($value) {
@return type-of($value) == 'map';
}
@function is-boolean($value) {
@return type-of($value) == 'bool';
}
@function is-null($value) {
@return type-of($value) == 'null';
}
// 类型安全的计算函数
@function safe-add($a, $b) {
@if is-number($a) and is-number($b) {
@return $a + $b;
} @else {
@error 'Both arguments must be numbers';
}
}
// 使用类型检查
$dimension1: 10px;
$dimension2: 20px;
.calculation {
result: safe-add($dimension1, $dimension2); // 30px
}
综合应用示例
主题系统
scss
// 创建完整的主题系统
$themes: (
light: (
colors: (
primary: #007bff,
secondary: #6c757d,
success: #28a745,
danger: #dc3545,
background: #ffffff,
text: #212529,
border: #dee2e6
),
spacing: (
xs: 0.25rem,
sm: 0.5rem,
md: 1rem,
lg: 1.5rem,
xl: 2rem
)
),
dark: (
colors: (
primary: #0d6efd,
secondary: #6c757d,
success: #198754,
danger: #dc3545,
background: #212529,
text: #f8f9fa,
border: #495057
),
spacing: (
xs: 0.25rem,
sm: 0.5rem,
md: 1rem,
lg: 1.5rem,
xl: 2rem
)
)
);
// 获取主题值的函数
@function theme-get($theme, $category, $key) {
$theme-map: map-get($themes, $theme);
$category-map: map-get($theme-map, $category);
@return map-get($category-map, $key);
}
// 应用主题
@each $theme-name, $theme-config in $themes {
.theme-#{$theme-name} {
background-color: theme-get($theme-name, colors, background);
color: theme-get($theme-name, colors, text);
border-color: theme-get($theme-name, colors, border);
.card {
background-color: theme-get($theme-name, colors, background);
border: 1px solid theme-get($theme-name, colors, border);
.card-header {
border-bottom: 1px solid theme-get($theme-name, colors, border);
}
}
.btn-primary {
background-color: theme-get($theme-name, colors, primary);
border-color: theme-get($theme-name, colors, primary);
color: if(lightness(theme-get($theme-name, colors, primary)) > 50, #212529, #fff);
&:hover {
background-color: darken(theme-get($theme-name, colors, primary), 10%);
border-color: darken(theme-get($theme-name, colors, primary), 10%);
}
}
}
}
Sass的内置函数库提供了强大的功能,可以帮助您创建动态、灵活和可维护的样式系统。