SCSS_USAGE_GUIDE.md 14 KB

SCSS 使用指南

📚 目录

  1. 基础语法
  2. 变量
  3. 嵌套
  4. 混入(Mixin)
  5. 函数
  6. 继承
  7. 模块化
  8. 实际应用示例
  9. 最佳实践

基础语法

文件扩展名

  • SCSS 文件使用 .scss 扩展名
  • 在组件中导入:import './style.scss'

注释

// 单行注释(不会编译到 CSS)
/* 多行注释(会编译到 CSS) */

变量

定义变量

// 颜色变量
$primary-color: #0769fb;
$secondary-color: #6c757d;
$text-color: #333;
$bg-color: #fff;

// 尺寸变量
$spacing-sm: 8px;
$spacing-md: 16px;
$spacing-lg: 24px;
$spacing-xl: 32px;

// 字体变量
$font-size-base: 16px;
$font-size-lg: 20px;
$font-size-sm: 14px;

// 布局变量
$container-width: 1200px;
$sidebar-width: 250px;

使用变量

.button {
  background-color: $primary-color;
  padding: $spacing-md;
  font-size: $font-size-base;
  color: $text-color;
}

变量作用域

$global-color: #000; // 全局变量

.container {
  $local-color: #fff; // 局部变量,只在 .container 内可用
  
  color: $local-color;
  border-color: $global-color;
}

默认值

// 如果变量未定义,使用默认值
$primary-color: #0769fb !default;

.button {
  background-color: $primary-color; // 如果未定义,使用 #0769fb
}

嵌套

基本嵌套

// 传统 CSS
.container {
  width: 100%;
}
.container .title {
  font-size: 20px;
}
.container .title:hover {
  color: red;
}

// SCSS 嵌套
.container {
  width: 100%;
  
  .title {
    font-size: 20px;
    
    &:hover {
      color: red;
    }
  }
}

& 符号(父选择器引用)

.button {
  background: blue;
  
  // &:hover 编译为 .button:hover
  &:hover {
    background: darkblue;
  }
  
  // &.active 编译为 .button.active
  &.active {
    background: green;
  }
  
  // &::before 编译为 .button::before
  &::before {
    content: '';
  }
  
  // 嵌套中的 & 引用
  .icon {
    // .button .icon 中的 & 仍然是 .button
    &:hover {
      // 编译为 .button .icon:hover
    }
  }
}

属性嵌套

// 传统写法
.box {
  border-width: 1px;
  border-style: solid;
  border-color: #ddd;
}

// SCSS 属性嵌套
.box {
  border: {
    width: 1px;
    style: solid;
    color: #ddd;
  }
  
  // 也可以嵌套伪类
  font: {
    family: Arial;
    size: 16px;
    weight: bold;
  }
}

媒体查询嵌套

.container {
  width: 100%;
  
  @media (max-width: 768px) {
    width: 100%;
    padding: 10px;
    
    .title {
      font-size: 18px;
    }
  }
  
  @media (min-width: 1200px) {
    max-width: 1200px;
    margin: 0 auto;
  }
}

混入(Mixin)

基础混入

// 定义混入
@mixin flex-center {
  display: flex;
  align-items: center;
  justify-content: center;
}

// 使用混入
.container {
  @include flex-center;
  height: 100vh;
}

带参数的混入

// 定义带参数的混入
@mixin button($bg-color, $text-color: white) {
  background-color: $bg-color;
  color: $text-color;
  padding: 12px 24px;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.3s;
  
  &:hover {
    background-color: darken($bg-color, 10%);
  }
}

// 使用
.btn-primary {
  @include button(#0769fb);
}

.btn-danger {
  @include button(#dc3545);
}

.btn-custom {
  @include button(#28a745, #fff);
}

带默认参数的混入

@mixin card($padding: 16px, $shadow: true) {
  padding: $padding;
  border-radius: 8px;
  
  @if $shadow {
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  }
}

.card {
  @include card; // 使用默认值
}

.card-large {
  @include card(24px, false); // 自定义参数
}

内容块混入

@mixin responsive($breakpoint) {
  @media (max-width: $breakpoint) {
    @content; // 插入传入的内容
  }
}

.container {
  width: 100%;
  
  @include responsive(768px) {
    width: 100%;
    padding: 10px;
  }
}

函数

内置函数

颜色函数

$primary: #0769fb;

.button {
  // 变亮/变暗
  background: lighten($primary, 20%);
  border-color: darken($primary, 10%);
  
  // 调整饱和度
  background: saturate($primary, 20%);
  background: desaturate($primary, 20%);
  
  // 调整透明度
  background: rgba($primary, 0.8);
  background: fade-in($primary, 0.2);
  background: fade-out($primary, 0.2);
  
  // 混合颜色
  background: mix($primary, white, 50%);
  
  // 调整色调
  background: adjust-hue($primary, 30deg);
  
  // 互补色
  border-color: complement($primary);
}

字符串函数

$font-family: 'Arial';

.text {
  // 转大写
  text-transform: to-upper-case($font-family);
  
  // 转小写
  text-transform: to-lower-case($font-family);
  
  // 引用字符串
  content: quote('Hello');
  
  // 取消引用
  font-family: unquote('Arial');
}

数学函数

.container {
  // 百分比
  width: percentage(2/3); // 66.666667%
  
  // 四舍五入
  font-size: round(18.7px); // 19px
  
  // 向上取整
  padding: ceil(18.2px); // 19px
  
  // 向下取整
  margin: floor(18.9px); // 18px
  
  // 绝对值
  left: abs(-10px); // 10px
  
  // 最小值/最大值
  width: min(100px, 200px); // 100px
  height: max(50px, 100px); // 100px
}

自定义函数

// 计算 rem
@function calculate-rem($pixels) {
  @return $pixels / 16px * 1rem;
}

.title {
  font-size: calculate-rem(24px); // 1.5rem
}

// 间距函数
@function spacing($multiplier) {
  @return $multiplier * 8px;
}

.container {
  padding: spacing(2); // 16px
  margin: spacing(3); // 24px
}

// 颜色对比度函数
@function get-text-color($bg-color) {
  @if lightness($bg-color) > 50% {
    @return #000; // 浅色背景用黑色文字
  } @else {
    @return #fff; // 深色背景用白色文字
  }
}

.button {
  background: $primary-color;
  color: get-text-color($primary-color);
}

继承

基础继承

// 定义占位符选择器(%)
%button-base {
  padding: 12px 24px;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.3s;
  border: none;
}

// 继承
.btn-primary {
  @extend %button-base;
  background-color: #0769fb;
  color: white;
}

.btn-secondary {
  @extend %button-base;
  background-color: #6c757d;
  color: white;
}

继承 vs 混入

// 混入:会复制代码到每个类中
@mixin button-mixin {
  padding: 12px;
}

.btn1 { @include button-mixin; }
.btn2 { @include button-mixin; }
// 编译后:两个类都有 padding: 12px

// 继承:会合并选择器
%button-extend {
  padding: 12px;
}

.btn1 { @extend %button-extend; }
.btn2 { @extend %button-extend; }
// 编译后:.btn1, .btn2 { padding: 12px; }

模块化

@import(旧方式,已废弃)

@import 'variables';
@import 'mixins';

@use(推荐方式)

// _variables.scss
$primary-color: #0769fb;
$spacing: 16px;

// _mixins.scss
@mixin flex-center {
  display: flex;
  align-items: center;
  justify-content: center;
}

// main.scss
@use 'variables' as vars;
@use 'mixins' as mix;

.container {
  color: vars.$primary-color;
  padding: vars.$spacing;
  @include mix.flex-center;
}

// 或者不使用命名空间
@use 'variables';
@use 'mixins';

.container {
  color: variables.$primary-color;
  @include mixins.flex-center;
}

@forward(转发模块)

// _all.scss
@forward 'variables';
@forward 'mixins';

// main.scss
@use 'all';

.container {
  color: all.$primary-color;
  @include all.flex-center;
}

实际应用示例

1. 按钮组件系统

// _variables.scss
$button-colors: (
  'primary': #0769fb,
  'success': #28a745,
  'danger': #dc3545,
  'warning': #ffc107
);

$button-padding: 12px 24px;
$button-radius: 4px;

// _mixins.scss
@mixin button-base {
  padding: $button-padding;
  border-radius: $button-radius;
  border: none;
  cursor: pointer;
  font-size: 16px;
  transition: all 0.3s;
  
  &:hover {
    transform: translateY(-2px);
  }
  
  &:active {
    transform: translateY(0);
  }
}

@mixin button-variant($color-name) {
  $color: map-get($button-colors, $color-name);
  
  background-color: $color;
  color: white;
  
  &:hover {
    background-color: darken($color, 10%);
  }
  
  &:active {
    background-color: darken($color, 15%);
  }
}

// buttons.scss
@use 'variables' as vars;
@use 'mixins' as mix;

.button {
  @include mix.button-base;
  
  @each $name, $color in vars.$button-colors {
    &.#{$name} {
      @include mix.button-variant($name);
    }
  }
}

2. 响应式网格系统

// _variables.scss
$breakpoints: (
  'sm': 576px,
  'md': 768px,
  'lg': 992px,
  'xl': 1200px
);

$grid-columns: 12;

// _mixins.scss
@mixin respond-to($breakpoint) {
  $value: map-get($breakpoints, $breakpoint);
  
  @if $value {
    @media (min-width: $value) {
      @content;
    }
  }
}

@mixin grid-column($columns) {
  width: percentage($columns / $grid-columns);
  
  @include respond-to('md') {
    width: percentage($columns / $grid-columns);
  }
}

// grid.scss
@use 'variables' as vars;
@use 'mixins' as mix;

.container {
  display: flex;
  flex-wrap: wrap;
  
  @include respond-to('md') {
    display: grid;
    grid-template-columns: repeat(12, 1fr);
    gap: 16px;
  }
}

@for $i from 1 through vars.$grid-columns {
  .col-#{$i} {
    @include mix.grid-column($i);
  }
}

3. 主题切换系统

// _themes.scss
$themes: (
  'light': (
    'bg': #fff,
    'text': #333,
    'primary': #0769fb
  ),
  'dark': (
    'bg': #1a1a1a,
    'text': #fff,
    'primary': #4a9eff
  )
);

@function theme($theme-name, $key) {
  $theme: map-get($themes, $theme-name);
  @return map-get($theme, $key);
}

// main.scss
@use 'themes' as t;

body {
  background-color: t.theme('light', 'bg');
  color: t.theme('light', 'text');
  
  &.dark-theme {
    background-color: t.theme('dark', 'bg');
    color: t.theme('dark', 'text');
  }
}

.button {
  background-color: t.theme('light', 'primary');
  
  .dark-theme & {
    background-color: t.theme('dark', 'primary');
  }
}

4. 动画系统

// _animations.scss
@mixin fade-in($duration: 0.3s) {
  animation: fadeIn $duration ease-in-out;
  
  @keyframes fadeIn {
    from {
      opacity: 0;
    }
    to {
      opacity: 1;
    }
  }
}

@mixin slide-in($direction: left, $distance: 100px, $duration: 0.3s) {
  $transform: null;
  
  @if $direction == 'left' {
    $transform: translateX(-$distance);
  } @else if $direction == 'right' {
    $transform: translateX($distance);
  } @else if $direction == 'up' {
    $transform: translateY(-$distance);
  } @else {
    $transform: translateY($distance);
  }
  
  animation: slideIn $duration ease-out;
  
  @keyframes slideIn {
    from {
      transform: $transform;
      opacity: 0;
    }
    to {
      transform: translate(0, 0);
      opacity: 1;
    }
  }
}

// 使用
.modal {
  @include fade-in(0.5s);
}

.sidebar {
  @include slide-in('left', 200px, 0.4s);
}

最佳实践

1. 文件组织

styles/
├── _variables.scss    # 变量
├── _mixins.scss       # 混入
├── _functions.scss    # 函数
├── _base.scss         # 基础样式
├── _components.scss   # 组件样式
└── main.scss          # 主文件

2. 命名规范

// 变量:使用 kebab-case
$primary-color: #0769fb;
$spacing-base: 8px;

// 混入:使用 kebab-case
@mixin flex-center { }
@mixin button-variant { }

// 函数:使用 kebab-case
@function calculate-rem { }

3. 避免过度嵌套

// ❌ 不好:嵌套太深
.container {
  .wrapper {
    .content {
      .title {
        .text {
          color: red;
        }
      }
    }
  }
}

// ✅ 好:保持 3-4 层以内
.container {
  .content {
    .title {
      color: red;
    }
  }
}

4. 使用变量统一管理

// ✅ 好:使用变量
$primary: #0769fb;
.button { background: $primary; }

// ❌ 不好:硬编码
.button { background: #0769fb; }

5. 合理使用混入和继承

// 混入:用于需要参数的样式
@mixin button($color) {
  background: $color;
}

// 继承:用于不需要参数的通用样式
%reset-list {
  margin: 0;
  padding: 0;
  list-style: none;
}

6. 使用 @use 替代 @import

// ✅ 推荐
@use 'variables';

// ❌ 已废弃
@import 'variables';

常用代码片段

清除浮动

@mixin clearfix {
  &::after {
    content: '';
    display: table;
    clear: both;
  }
}

文本省略

@mixin text-ellipsis {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

@mixin text-ellipsis-multi($lines: 2) {
  display: -webkit-box;
  -webkit-line-clamp: $lines;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

居中布局

@mixin flex-center {
  display: flex;
  align-items: center;
  justify-content: center;
}

@mixin absolute-center {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

响应式断点

$breakpoints: (
  'sm': 576px,
  'md': 768px,
  'lg': 992px,
  'xl': 1200px
);

@mixin respond-to($breakpoint) {
  $value: map-get($breakpoints, $breakpoint);
  
  @if $value {
    @media (min-width: $value) {
      @content;
    }
  }
}

调试技巧

1. 使用 @debug

$width: 100px;
@debug "Width is: #{$width}";

2. 使用 @warn

@function calculate-rem($pixels) {
  @if unit($pixels) != 'px' {
    @warn "Expected pixels, got #{unit($pixels)}";
  }
  @return $pixels / 16px * 1rem;
}

3. 检查变量值

@mixin debug-variable($var) {
  &::before {
    content: '#{$var}';
  }
}

总结

SCSS 的核心优势:

  1. 变量 - 统一管理值
  2. 嵌套 - 代码更清晰
  3. 混入 - 复用样式块
  4. 函数 - 计算和转换
  5. 继承 - 减少重复代码
  6. 模块化 - 代码组织更清晰

记住:功能强大,但要适度使用,保持代码简洁易读!