Sass高级特性
Sass高级特性
条件语句与循环
条件语句
Sass 提供@if
、@else if
和@else
指令进行条件控制。
// 基本条件语句
$theme: "dark";
body {
@if $theme == "light" {
background-color: #fff;
color: #000;
} @else if $theme == "dark" {
background-color: #333;
color: #fff;
} @else {
background-color: #f5f5f5;
color: #333;
}
}
// 使用条件表达式
@mixin text-color($bg-color) {
@if lightness($bg-color) > 50% {
color: #000; // 深色文本用于浅色背景
} @else {
color: #fff; // 浅色文本用于深色背景
}
}
.button {
background-color: #3498db;
@include text-color(#3498db);
}
与 Python 条件语句对比:
# Python条件语句
theme = 'dark'
if theme == 'light':
background_color = '#fff'
text_color = '#000'
elif theme == 'dark':
background_color = '#333'
text_color = '#fff'
else:
background_color = '#f5f5f5'
text_color = '#333'
循环语句
Sass 提供三种循环方式:@for
、@each
和@while
。
@for 循环
// 从1到3的循环
@for $i from 1 through 3 {
.col-#{$i} {
width: 100% / 3 * $i;
}
}
// 编译结果
.col-1 {
width: 33.3333%;
}
.col-2 {
width: 66.6667%;
}
.col-3 {
width: 100%;
}
// 从0到2的循环
@for $i from 0 to 3 {
.m-#{$i} {
margin: #{$i}rem;
}
}
// 编译结果
.m-0 {
margin: 0rem;
}
.m-1 {
margin: 1rem;
}
.m-2 {
margin: 2rem;
}
@each 循环
// 遍历列表
$colors: red, green, blue;
@each $color in $colors {
.text-#{$color} {
color: $color;
}
}
// 编译结果
.text-red {
color: red;
}
.text-green {
color: green;
}
.text-blue {
color: blue;
}
// 遍历映射
$theme-colors: (
"primary": #3498db,
"success": #2ecc71,
"danger": #e74c3c,
);
@each $name, $color in $theme-colors {
.btn-#{$name} {
background-color: $color;
&:hover {
background-color: darken($color, 10%);
}
}
}
// 编译结果
.btn-primary {
background-color: #3498db;
}
.btn-primary:hover {
background-color: #217dbb;
}
.btn-success {
background-color: #2ecc71;
}
.btn-success:hover {
background-color: #25a25a;
}
.btn-danger {
background-color: #e74c3c;
}
.btn-danger:hover {
background-color: #d62c1a;
}
@while 循环
$i: 1;
@while $i <= 3 {
.item-#{$i} {
width: 100% / $i;
}
$i: $i + 1;
}
// 编译结果
.item-1 {
width: 100%;
}
.item-2 {
width: 50%;
}
.item-3 {
width: 33.3333%;
}
与 Python 循环对比:
# Python for循环
for i in range(1, 4): # 1到3
print(f".col-{i} {{ width: {100/3*i}%; }}")
# Python列表循环
colors = ["red", "green", "blue"]
for color in colors:
print(f".text-{color} {{ color: {color}; }}")
# Python字典循环
theme_colors = {
"primary": "#3498db",
"success": "#2ecc71",
"danger": "#e74c3c"
}
for name, color in theme_colors.items():
print(f".btn-{name} {{ background-color: {color}; }}")
# Python while循环
i = 1
while i <= 3:
print(f".item-{i} {{ width: {100/i}%; }}")
i += 1
模块化与导入系统
@import 指令
Sass 的@import
允许将多个 Sass 文件组合成一个文件。
// 基本导入
@import "variables";
@import "mixins";
// 多文件导入
@import "reset", "typography", "buttons";
// 嵌套导入
.sidebar {
@import "sidebar-styles";
}
@use 指令(Sass 3.6+)
@use
是@import
的现代替代品,提供了命名空间和模块化功能。
// _colors.scss
$primary: #3498db;
$secondary: #2ecc71;
@mixin theme($light-theme: true) {
@if $light-theme {
background-color: white;
color: black;
} @else {
background-color: black;
color: white;
}
}
// main.scss
@use "colors";
.button {
background-color: colors.$primary;
color: white;
}
.container {
@include colors.theme(false);
}
@forward 指令(Sass 3.6+)
@forward
允许从一个模块加载并重新导出样式,便于创建统一的入口点。
// _variables.scss
$primary-color: #3498db;
$secondary-color: #2ecc71;
// _functions.scss
@function calculate-width($col, $total: 12) {
@return percentage($col / $total);
}
// _index.scss
@forward "variables";
@forward "functions";
// main.scss
@use "index" as *;
.element {
color: $primary-color;
width: calculate-width(6);
}
模块配置
使用with
关键字配置模块默认值。
// _theme.scss
$primary: #3498db !default;
$secondary: #2ecc71 !default;
.button {
background-color: $primary;
color: white;
}
// main.scss
@use "theme" with (
$primary: #9b59b6,
$secondary: #f1c40f
);
与 Python 模块系统对比:
# Python模块导入
import colors
from colors import primary, secondary
from utils import *
# Python模块配置
import config
config.DEBUG = True
最佳实践与架构模式
7-1 模式
将 Sass 文件组织为 7 个文件夹和 1 个主文件。
sass/
|-- abstracts/ # 工具和辅助函数
| |-- _variables.scss
| |-- _functions.scss
| |-- _mixins.scss
|-- base/ # 基础样式
| |-- _reset.scss
| |-- _typography.scss
|-- components/ # 组件样式
| |-- _buttons.scss
| |-- _cards.scss
|-- layout/ # 布局样式
| |-- _header.scss
| |-- _footer.scss
|-- pages/ # 页面特定样式
| |-- _home.scss
| |-- _about.scss
|-- themes/ # 主题样式
| |-- _default.scss
| |-- _dark.scss
|-- vendors/ # 第三方样式
| |-- _bootstrap.scss
|-- main.scss # 主文件
BEM 命名约定
BEM(Block Element Modifier)是一种 CSS 命名约定。
// Block
.card {
// ...
// Element
&__header {
// ...
}
&__body {
// ...
}
// Modifier
&--featured {
// ...
}
}
// 编译结果
.card { ... }
.card__header { ... }
.card__body { ... }
.card--featured { ... }
ITCSS 架构
Inverted Triangle CSS 是一种从通用到特定的 CSS 组织方法。
1. Settings - 变量和配置
2. Tools - 混合和函数
3. Generic - 重置和标准化
4. Elements - 无类元素样式
5. Objects - 布局和结构
6. Components - UI组件
7. Utilities - 辅助类
Sass 与现代前端框架的集成
Vue 与 Sass
<template>
<div class="component">
<button class="component__button">点击我</button>
</div>
</template>
<style lang="scss">
// 全局样式
</style>
<style lang="scss" scoped>
// 组件局部样式
$primary-color: #3498db;
.component {
padding: 20px;
&__button {
background-color: $primary-color;
color: white;
padding: 10px 15px;
border: none;
border-radius: 4px;
&:hover {
background-color: darken($primary-color, 10%);
}
}
}
</style>
React 与 Sass
使用 CSS 模块:
// Button.jsx
import React from "react";
import styles from "./Button.module.scss";
const Button = ({ children, variant = "primary" }) => {
return (
<button className={`${styles.button} ${styles[`button--${variant}`]}`}>
{children}
</button>
);
};
export default Button;
// Button.module.scss
$primary-color: #3498db;
$success-color: #2ecc71;
$danger-color: #e74c3c;
.button {
padding: 10px 15px;
border: none;
border-radius: 4px;
cursor: pointer;
&--primary {
background-color: $primary-color;
color: white;
&:hover {
background-color: darken($primary-color, 10%);
}
}
&--success {
background-color: $success-color;
color: white;
&:hover {
background-color: darken($success-color, 10%);
}
}
&--danger {
background-color: $danger-color;
color: white;
&:hover {
background-color: darken($danger-color, 10%);
}
}
}
Angular 与 Sass
// button.component.ts
import { Component, Input } from "@angular/core";
@Component({
selector: "app-button",
templateUrl: "./button.component.html",
styleUrls: ["./button.component.scss"],
})
export class ButtonComponent {
@Input() variant: "primary" | "success" | "danger" = "primary";
}
<!-- button.component.html -->
<button class="button" [ngClass]="'button--' + variant">
<ng-content></ng-content>
</button>
// button.component.scss
$primary-color: #3498db;
$success-color: #2ecc71;
$danger-color: #e74c3c;
@mixin button-variant($color) {
background-color: $color;
color: white;
&:hover {
background-color: darken($color, 10%);
}
}
.button {
padding: 10px 15px;
border: none;
border-radius: 4px;
cursor: pointer;
&--primary {
@include button-variant($primary-color);
}
&--success {
@include button-variant($success-color);
}
&--danger {
@include button-variant($danger-color);
}
}
实战示例:高级主题系统
// _theme-config.scss
$themes: (
light: (
bg-primary: #ffffff,
bg-secondary: #f5f5f5,
text-primary: #333333,
text-secondary: #666666,
border: #dddddd,
primary: #3498db,
success: #2ecc71,
warning: #f39c12,
danger: #e74c3c,
),
dark: (
bg-primary: #222222,
bg-secondary: #333333,
text-primary: #ffffff,
text-secondary: #cccccc,
border: #444444,
primary: #3498db,
success: #2ecc71,
warning: #f39c12,
danger: #e74c3c,
),
);
// _theme-functions.scss
@function theme-get($key, $theme-name: "light") {
$theme: map-get($themes, $theme-name);
@return map-get($theme, $key);
}
// _theme-mixins.scss
@mixin themed() {
@each $theme-name, $theme in $themes {
.theme-#{$theme-name} & {
@content ($theme-name, $theme);
}
}
}
@mixin theme-aware($property, $key) {
@include themed {
#{$property}: theme-get($key, $theme-name);
}
}
// _buttons.scss
.button {
padding: 10px 15px;
border: none;
border-radius: 4px;
cursor: pointer;
transition: all 0.3s ease;
@include themed using ($theme-name, $theme) {
background-color: map-get($theme, primary);
color: map-get($theme, bg-primary);
&:hover {
background-color: darken(map-get($theme, primary), 10%);
}
}
&--success {
@include themed using ($theme-name, $theme) {
background-color: map-get($theme, success);
&:hover {
background-color: darken(map-get($theme, success), 10%);
}
}
}
&--danger {
@include themed using ($theme-name, $theme) {
background-color: map-get($theme, danger);
&:hover {
background-color: darken(map-get($theme, danger), 10%);
}
}
}
}
// _cards.scss
.card {
border-radius: 8px;
overflow: hidden;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
@include theme-aware("background-color", "bg-primary");
@include theme-aware("color", "text-primary");
@include theme-aware("border", "border");
&__header {
padding: 15px;
@include theme-aware("border-bottom", "border");
h3 {
margin: 0;
@include theme-aware("color", "primary");
}
}
&__body {
padding: 15px;
p {
@include theme-aware("color", "text-secondary");
}
}
&__footer {
padding: 15px;
@include theme-aware("border-top", "border");
@include theme-aware("background-color", "bg-secondary");
}
}
// main.scss
@import "theme-config";
@import "theme-functions";
@import "theme-mixins";
@import "buttons";
@import "cards";
// 默认使用亮色主题
body {
@extend .theme-light;
}
// 主题切换
.theme-toggle {
position: fixed;
top: 20px;
right: 20px;
z-index: 1000;
}
HTML 使用示例:
<div class="theme-light">
<!-- 或 class="theme-dark" -->
<div class="card">
<div class="card__header">
<h3>卡片标题</h3>
</div>
<div class="card__body">
<p>这是卡片内容,展示了主题系统的应用。</p>
</div>
<div class="card__footer">
<button class="button">默认按钮</button>
<button class="button button--success">成功按钮</button>
<button class="button button--danger">危险按钮</button>
</div>
</div>
</div>
<button
class="theme-toggle"
onclick="document.body.classList.toggle('theme-dark')"
>
切换主题
</button>
这个高级主题系统示例展示了如何使用 Sass 的条件语句、循环、函数和混合来创建一个灵活、可扩展的主题切换系统。