|
|
@@ -0,0 +1,917 @@
|
|
|
+# SCSS 使用指南
|
|
|
+
|
|
|
+## 📚 目录
|
|
|
+
|
|
|
+1. [基础语法](#基础语法)
|
|
|
+2. [变量](#变量)
|
|
|
+3. [嵌套](#嵌套)
|
|
|
+4. [混入(Mixin)](#混入mixin)
|
|
|
+5. [函数](#函数)
|
|
|
+6. [继承](#继承)
|
|
|
+7. [模块化](#模块化)
|
|
|
+8. [实际应用示例](#实际应用示例)
|
|
|
+9. [最佳实践](#最佳实践)
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 基础语法
|
|
|
+
|
|
|
+### 文件扩展名
|
|
|
+- SCSS 文件使用 `.scss` 扩展名
|
|
|
+- 在组件中导入:`import './style.scss'`
|
|
|
+
|
|
|
+### 注释
|
|
|
+```scss
|
|
|
+// 单行注释(不会编译到 CSS)
|
|
|
+/* 多行注释(会编译到 CSS) */
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 变量
|
|
|
+
|
|
|
+### 定义变量
|
|
|
+```scss
|
|
|
+// 颜色变量
|
|
|
+$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;
|
|
|
+```
|
|
|
+
|
|
|
+### 使用变量
|
|
|
+```scss
|
|
|
+.button {
|
|
|
+ background-color: $primary-color;
|
|
|
+ padding: $spacing-md;
|
|
|
+ font-size: $font-size-base;
|
|
|
+ color: $text-color;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 变量作用域
|
|
|
+```scss
|
|
|
+$global-color: #000; // 全局变量
|
|
|
+
|
|
|
+.container {
|
|
|
+ $local-color: #fff; // 局部变量,只在 .container 内可用
|
|
|
+
|
|
|
+ color: $local-color;
|
|
|
+ border-color: $global-color;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 默认值
|
|
|
+```scss
|
|
|
+// 如果变量未定义,使用默认值
|
|
|
+$primary-color: #0769fb !default;
|
|
|
+
|
|
|
+.button {
|
|
|
+ background-color: $primary-color; // 如果未定义,使用 #0769fb
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 嵌套
|
|
|
+
|
|
|
+### 基本嵌套
|
|
|
+```scss
|
|
|
+// 传统 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;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### & 符号(父选择器引用)
|
|
|
+```scss
|
|
|
+.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
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 属性嵌套
|
|
|
+```scss
|
|
|
+// 传统写法
|
|
|
+.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;
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 媒体查询嵌套
|
|
|
+```scss
|
|
|
+.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)
|
|
|
+
|
|
|
+### 基础混入
|
|
|
+```scss
|
|
|
+// 定义混入
|
|
|
+@mixin flex-center {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+}
|
|
|
+
|
|
|
+// 使用混入
|
|
|
+.container {
|
|
|
+ @include flex-center;
|
|
|
+ height: 100vh;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 带参数的混入
|
|
|
+```scss
|
|
|
+// 定义带参数的混入
|
|
|
+@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);
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 带默认参数的混入
|
|
|
+```scss
|
|
|
+@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); // 自定义参数
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 内容块混入
|
|
|
+```scss
|
|
|
+@mixin responsive($breakpoint) {
|
|
|
+ @media (max-width: $breakpoint) {
|
|
|
+ @content; // 插入传入的内容
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.container {
|
|
|
+ width: 100%;
|
|
|
+
|
|
|
+ @include responsive(768px) {
|
|
|
+ width: 100%;
|
|
|
+ padding: 10px;
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 函数
|
|
|
+
|
|
|
+### 内置函数
|
|
|
+
|
|
|
+#### 颜色函数
|
|
|
+```scss
|
|
|
+$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);
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+#### 字符串函数
|
|
|
+```scss
|
|
|
+$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');
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+#### 数学函数
|
|
|
+```scss
|
|
|
+.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
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 自定义函数
|
|
|
+```scss
|
|
|
+// 计算 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);
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 继承
|
|
|
+
|
|
|
+### 基础继承
|
|
|
+```scss
|
|
|
+// 定义占位符选择器(%)
|
|
|
+%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 混入
|
|
|
+```scss
|
|
|
+// 混入:会复制代码到每个类中
|
|
|
+@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(旧方式,已废弃)
|
|
|
+```scss
|
|
|
+@import 'variables';
|
|
|
+@import 'mixins';
|
|
|
+```
|
|
|
+
|
|
|
+### @use(推荐方式)
|
|
|
+```scss
|
|
|
+// _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(转发模块)
|
|
|
+```scss
|
|
|
+// _all.scss
|
|
|
+@forward 'variables';
|
|
|
+@forward 'mixins';
|
|
|
+
|
|
|
+// main.scss
|
|
|
+@use 'all';
|
|
|
+
|
|
|
+.container {
|
|
|
+ color: all.$primary-color;
|
|
|
+ @include all.flex-center;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 实际应用示例
|
|
|
+
|
|
|
+### 1. 按钮组件系统
|
|
|
+```scss
|
|
|
+// _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. 响应式网格系统
|
|
|
+```scss
|
|
|
+// _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. 主题切换系统
|
|
|
+```scss
|
|
|
+// _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. 动画系统
|
|
|
+```scss
|
|
|
+// _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. 命名规范
|
|
|
+```scss
|
|
|
+// 变量:使用 kebab-case
|
|
|
+$primary-color: #0769fb;
|
|
|
+$spacing-base: 8px;
|
|
|
+
|
|
|
+// 混入:使用 kebab-case
|
|
|
+@mixin flex-center { }
|
|
|
+@mixin button-variant { }
|
|
|
+
|
|
|
+// 函数:使用 kebab-case
|
|
|
+@function calculate-rem { }
|
|
|
+```
|
|
|
+
|
|
|
+### 3. 避免过度嵌套
|
|
|
+```scss
|
|
|
+// ❌ 不好:嵌套太深
|
|
|
+.container {
|
|
|
+ .wrapper {
|
|
|
+ .content {
|
|
|
+ .title {
|
|
|
+ .text {
|
|
|
+ color: red;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// ✅ 好:保持 3-4 层以内
|
|
|
+.container {
|
|
|
+ .content {
|
|
|
+ .title {
|
|
|
+ color: red;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 4. 使用变量统一管理
|
|
|
+```scss
|
|
|
+// ✅ 好:使用变量
|
|
|
+$primary: #0769fb;
|
|
|
+.button { background: $primary; }
|
|
|
+
|
|
|
+// ❌ 不好:硬编码
|
|
|
+.button { background: #0769fb; }
|
|
|
+```
|
|
|
+
|
|
|
+### 5. 合理使用混入和继承
|
|
|
+```scss
|
|
|
+// 混入:用于需要参数的样式
|
|
|
+@mixin button($color) {
|
|
|
+ background: $color;
|
|
|
+}
|
|
|
+
|
|
|
+// 继承:用于不需要参数的通用样式
|
|
|
+%reset-list {
|
|
|
+ margin: 0;
|
|
|
+ padding: 0;
|
|
|
+ list-style: none;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 6. 使用 @use 替代 @import
|
|
|
+```scss
|
|
|
+// ✅ 推荐
|
|
|
+@use 'variables';
|
|
|
+
|
|
|
+// ❌ 已废弃
|
|
|
+@import 'variables';
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 常用代码片段
|
|
|
+
|
|
|
+### 清除浮动
|
|
|
+```scss
|
|
|
+@mixin clearfix {
|
|
|
+ &::after {
|
|
|
+ content: '';
|
|
|
+ display: table;
|
|
|
+ clear: both;
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 文本省略
|
|
|
+```scss
|
|
|
+@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;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 居中布局
|
|
|
+```scss
|
|
|
+@mixin flex-center {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+}
|
|
|
+
|
|
|
+@mixin absolute-center {
|
|
|
+ position: absolute;
|
|
|
+ top: 50%;
|
|
|
+ left: 50%;
|
|
|
+ transform: translate(-50%, -50%);
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 响应式断点
|
|
|
+```scss
|
|
|
+$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
|
|
|
+```scss
|
|
|
+$width: 100px;
|
|
|
+@debug "Width is: #{$width}";
|
|
|
+```
|
|
|
+
|
|
|
+### 2. 使用 @warn
|
|
|
+```scss
|
|
|
+@function calculate-rem($pixels) {
|
|
|
+ @if unit($pixels) != 'px' {
|
|
|
+ @warn "Expected pixels, got #{unit($pixels)}";
|
|
|
+ }
|
|
|
+ @return $pixels / 16px * 1rem;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 3. 检查变量值
|
|
|
+```scss
|
|
|
+@mixin debug-variable($var) {
|
|
|
+ &::before {
|
|
|
+ content: '#{$var}';
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 总结
|
|
|
+
|
|
|
+SCSS 的核心优势:
|
|
|
+1. ✅ **变量** - 统一管理值
|
|
|
+2. ✅ **嵌套** - 代码更清晰
|
|
|
+3. ✅ **混入** - 复用样式块
|
|
|
+4. ✅ **函数** - 计算和转换
|
|
|
+5. ✅ **继承** - 减少重复代码
|
|
|
+6. ✅ **模块化** - 代码组织更清晰
|
|
|
+
|
|
|
+记住:**功能强大,但要适度使用,保持代码简洁易读!**
|