Appearance
Sass 控制指令
Sass提供了强大的控制指令,包括条件判断、循环和条件赋值等,使您能够编写动态和智能的样式代码。本章将详细介绍Sass中的各种控制指令。
@if, @else if, @else 指令
条件指令允许您根据条件来决定应用哪些样式。
基本条件判断
scss
// 简单条件判断
$theme: dark;
.element {
@if $theme == dark {
background-color: #333;
color: white;
} @else {
background-color: white;
color: #333;
}
}
// 多重条件判断
$size: large;
.button {
@if $size == small {
padding: 5px 10px;
font-size: 12px;
} @else if $size == medium {
padding: 10px 20px;
font-size: 14px;
} @else if $size == large {
padding: 15px 30px;
font-size: 16px;
} @else {
padding: 12px 24px;
font-size: 15px;
}
}
复杂条件判断
scss
// 嵌套条件判断
$theme: dark;
$has-border: true;
$border-width: 2px;
.card {
@if $theme == dark {
background-color: #333;
color: white;
@if $has-border {
border: $border-width solid #555;
}
} @else {
background-color: white;
color: #333;
@if $has-border {
border: $border-width solid #ddd;
}
}
}
// 使用函数进行条件判断
@function is-light($color) {
@return lightness($color) > 50%;
}
$primary-color: #3498db;
.element {
background-color: $primary-color;
@if is-light($primary-color) {
color: #333;
} @else {
color: white;
}
}
布尔条件
scss
// 布尔值条件判断
$enable-animations: true;
$enable-rtl: false;
$has-shadow: true;
.component {
@if $enable-animations {
animation: fadeIn 0.3s ease-in-out;
}
@if $has-shadow {
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
direction: if($enable-rtl, rtl, ltr);
}
// 组合条件
$has-header: true;
$has-footer: false;
$layout-type: 'sidebar';
.container {
@if $has-header and $has-footer {
padding: 2rem 0;
} @else if $has-header or $has-footer {
padding: 1rem 0;
} @else {
padding: 0;
}
@if $layout-type == 'sidebar' and $has-header {
display: grid;
grid-template-areas:
"header header"
"sidebar content";
}
}
@for 指令
@for指令用于创建循环,可以指定范围来生成重复的样式。
基本@for循环
scss
// 从1到5的循环
@for $i from 1 through 5 {
.col-#{$i} {
width: 20% * $i;
}
}
// 从0到4的循环
@for $i from 0 to 5 {
.item-#{$i} {
margin-left: 10px * $i;
z-index: 10 - $i;
}
}
// 生成网格系统
$grid-columns: 12;
@for $i from 1 through $grid-columns {
.col-#{$i} {
width: percentage($i / $grid-columns);
}
}
@for $i from 1 through 6 {
h#{$i} {
font-size: 2rem - ($i - 1) * 0.2rem;
margin-bottom: 1rem - ($i - 1) * 0.1rem;
}
}
高级@for用法
scss
// 使用@for生成响应式类
$breakpoints: (320px, 480px, 768px, 1024px, 1200px);
@for $i from 1 through length($breakpoints) {
$bp: nth($breakpoints, $i);
.breakpoint-#{$i} {
@media (min-width: $bp) {
display: block;
}
}
}
// 生成阴影深度
@for $i from 1 through 5 {
.shadow-#{$i} {
box-shadow: 0 ($i * 2px) ($i * 4px) rgba(0,0,0, 0.1 * $i);
}
}
// 生成透明度类
@for $i from 1 through 10 {
.opacity-#{$i * 10} {
opacity: $i * 0.1;
}
}
@each 指令
@each指令用于遍历列表或映射,是处理集合数据的最佳选择。
遍历列表
scss
// 遍历颜色列表
$colors: red, blue, green, yellow, purple;
@each $color in $colors {
.bg-#{$color} {
background-color: $color;
}
.text-#{$color} {
color: $color;
}
}
// 遍历尺寸列表
$sizes: small, medium, large;
@each $size in $sizes {
.btn-#{$size} {
@if $size == small {
padding: 5px 10px;
font-size: 12px;
} @else if $size == medium {
padding: 10px 20px;
font-size: 14px;
} @else {
padding: 15px 30px;
font-size: 16px;
}
}
}
遍历映射
scss
// 遍历主题颜色映射
$theme-colors: (
"primary": #007bff,
"secondary": #6c757d,
"success": #28a745,
"danger": #dc3545,
"warning": #ffc107,
"info": #17a2b8,
"light": #f8f9fa,
"dark": #343a40
);
@each $name, $color in $theme-colors {
.bg-#{$name} {
background-color: $color;
}
.text-#{$name} {
color: $color;
}
.border-#{$name} {
border-color: $color;
}
.btn-#{$name} {
background-color: $color;
border-color: $color;
color: if(lightness($color) > 50, #212529, #fff);
&:hover {
background-color: darken($color, 10%);
border-color: darken($color, 10%);
}
}
}
// 遍历断点映射
$breakpoints: (
"xs": 0,
"sm": 576px,
"md": 768px,
"lg": 992px,
"xl": 1200px,
"xxl": 1400px
);
@each $name, $breakpoint in $breakpoints {
@if $name != "xs" {
.d-#{$name}-none {
@media (min-width: $breakpoint) {
display: none !important;
}
}
.container-#{$name} {
@media (min-width: $breakpoint) {
max-width: $breakpoint + 200px;
}
}
}
}
嵌套@each循环
scss
// 嵌套遍历生成颜色变体
$colors: (primary: #007bff, secondary: #6c757d);
$variants: (light, normal, dark);
@each $color-name, $color in $colors {
@each $variant in $variants {
.#{$color-name}-#{$variant} {
@if $variant == light {
background-color: lighten($color, 20%);
} @else if $variant == dark {
background-color: darken($color, 20%);
} @else {
background-color: $color;
}
}
}
}
@while 指令
@while指令提供基于条件的循环,当条件为真时继续执行。
基本@while循环
scss
// 使用@while生成序列
$i: 1;
@while $i <= 5 {
.item-#{$i} {
width: 20px * $i;
height: 20px * $i;
}
$i: $i + 1;
}
// 生成递增的字体大小
$factor: 1;
@while $factor <= 3 {
.scale-#{$factor} {
transform: scale($factor);
font-size: 1rem * $factor;
}
$factor: $factor + 0.5;
}
复杂@while应用
scss
// 使用@while创建递减的透明度
$opacity: 1;
@while $opacity > 0 {
.fade-#{round($opacity * 100)} {
opacity: $opacity;
}
$opacity: $opacity - 0.1;
}
// 生成递减的边距
$margin: 50px;
@while $margin >= 5px {
.m-#{round($margin / 1px)} {
margin: $margin;
}
$margin: $margin * 0.8; // 每次减少20%
}
综合应用示例
响应式网格系统
scss
// 定义断点和列数
$breakpoints: (
"mobile": 480px,
"tablet": 768px,
"desktop": 1024px
);
$columns: 12;
// 生成基础网格类
@for $i from 1 through $columns {
.col-#{$i} {
width: percentage($i / $columns);
}
}
// 为每个断点生成响应式类
@each $name, $breakpoint in $breakpoints {
@media (min-width: $breakpoint) {
@for $i from 1 through $columns {
.col-#{$name}-#{$i} {
width: percentage($i / $columns);
}
}
}
}
主题变体生成
scss
// 定义主题配置
$themes: (
light: (
bg-color: #ffffff,
text-color: #333333,
border-color: #dddddd
),
dark: (
bg-color: #2d2d2d,
text-color: #ffffff,
border-color: #555555
),
blue: (
bg-color: #e3f2fd,
text-color: #1a237e,
border-color: #1e88e5
)
);
// 生成主题类
@each $theme-name, $theme-map in $themes {
.theme-#{$theme-name} {
background-color: map-get($theme-map, bg-color);
color: map-get($theme-map, text-color);
border: 1px solid map-get($theme-map, border-color);
// 为每个主题生成变体
@each $element, $property in (header, nav, sidebar, footer) {
&__#{$element} {
@if $element == "header" or $element == "nav" {
background-color: darken(map-get($theme-map, bg-color), 5%);
} @else {
background-color: lighten(map-get($theme-map, bg-color), 2%);
}
}
}
}
}
动画序列生成
scss
// 定义动画配置
$animations: (
"fadeIn": (0, 1),
"slideInLeft": (-100%, 0),
"slideInRight": (100%, 0),
"zoomIn": (0.5, 1)
);
// 生成动画类
@each $name, $values in $animations {
@keyframes #{$name} {
0% {
@if $name == "fadeIn" {
opacity: nth($values, 1);
} @else if str-index($name, "slide") {
transform: translateX(nth($values, 1));
} @else if str-index($name, "zoom") {
transform: scale(nth($values, 1));
opacity: 0.5;
}
}
100% {
@if $name == "fadeIn" {
opacity: nth($values, 2);
} @else if str-index($name, "slide") {
transform: translateX(nth($values, 2));
} @else if str-index($name, "zoom") {
transform: scale(nth($values, 2));
opacity: 1;
}
}
}
.animate-#{$name} {
animation: #{$name} 0.3s ease-in-out;
}
}
条件样式生成
scss
// 配置变量
$include-animations: true;
$include-shadows: true;
$enable-rtl: false;
// 条件性地包含样式
.card {
padding: 1rem;
border-radius: 8px;
@if $include-shadows {
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
@if $include-animations {
transition: all 0.3s ease-in-out;
&:hover {
@if $include-shadows {
box-shadow: 0 4px 8px rgba(0,0,0,0.15);
}
transform: translateY(-2px);
}
}
@if $enable-rtl {
text-align: right;
margin: 0 1rem 0 0;
} @else {
text-align: left;
margin: 0 0 0 1rem;
}
}
最佳实践
1. 避免过度复杂的条件
scss
// 不推荐:过于复杂的嵌套条件
.element {
@if $condition1 {
@if $condition2 {
@if $condition3 {
// 太深的嵌套难以维护
}
}
}
}
// 推荐:提取复杂逻辑到函数
@function get-style($c1, $c2, $c3) {
@if $c1 and $c2 and $c3 {
@return complex-value;
}
@return default-value;
}
.element {
property: get-style($condition1, $condition2, $condition3);
}
2. 合理使用循环
scss
// 注意性能:避免生成过多的CSS
// 推荐:设置合理的循环范围
@for $i from 1 through 12 {
.col-#{$i} { width: percentage($i / 12); }
}
// 而不是
// @for $i from 1 through 100 { ... }
3. 有意义的变量命名
scss
// 好的命名
@for $column-count from 1 through 12 {
.grid-span-#{$column-count} {
grid-column: span $column-count;
}
}
// 避免模糊的命名
@for $i from 1 through 12 {
.class-#{$i} {
// 不清楚$i代表什么
}
}
Sass的控制指令提供了强大的逻辑处理能力,使您能够创建动态、灵活和可维护的样式系统。