SCSS - 设计深浅主题 scss 结构

我将设计一个支持深浅主题的 SCSS 结构,采用模块化、可扩展的方式,通过变量、混合宏和控制指令实现主题切换。设计将包括全局配置、主题定义、组件样式和响应式支持,确保代码清晰、易于维护,并支持动态主题切换。

// 1. 全局变量 - 基础配置
$breakpoints: (
  mobile: 768px,
  tablet: 1024px,
  desktop: 1200px,
);

$spacing: (
  small: 8px,
  medium: 16px,
  large: 24px,
);

// 2. 主题配置 - 深浅主题颜色
$themes: (
  light: (
    background: #ffffff,
    text: #333333,
    primary: #007bff,
    secondary: #6c757d,
    accent: #28a745,
    border: #dee2e6,
  ),
  dark: (
    background: #1a1a1a,
    text: #ffffff,
    primary: #66b0ff,
    secondary: #adb5bd,
    accent: #51cf66,
    border: #495057,
  ),
);

// 3. 混合宏 - 主题样式和响应式
@mixin apply-theme($theme-name) {
  @if map-has-key($themes, $theme-name) {
    $theme: map-get($themes, $theme-name);

    background: map-get($theme, background);
    color: map-get($theme, text);
    --primary: #{map-get($theme, primary)};
    --secondary: #{map-get($theme, secondary)};
    --accent: #{map-get($theme, accent)};
    --border: #{map-get($theme, border)};
  } @else {
    @error "Invalid theme: #{$theme-name}. Available: #{map-keys($themes)}";
  }
}

@mixin respond-to($breakpoint) {
  @if map-has-key($breakpoints, $breakpoint) {
    @media (max-width: map-get($breakpoints, $breakpoint)) {
      @content;
    }
  } @else {
    @error "Invalid breakpoint: #{$breakpoint}. Available: #{map-keys($breakpoints)}";
  }
}

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

// 4. 全局样式 - 重置和基础设置
:root {
  font-family: Arial, sans-serif;
  font-size: 16px;
  transition: background 0.3s, color 0.3s;
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

// 5. 主题应用 - 深浅主题切换
.theme-light {
  @include apply-theme(light);
}

.theme-dark {
  @include apply-theme(dark);
}

// 6. 组件样式 - 主题化组件
.header {
  padding: map-get($spacing, medium);
  border-bottom: 1px solid var(--border);

  &__logo {
    font-size: 1.5rem;
    color: var(--primary);
  }

  &__nav {
    @include flex-center;
    gap: map-get($spacing, medium);

    a {
      color: var(--text);
      text-decoration: none;

      &:hover {
        color: var(--accent);
      }
    }
  }

  @include respond-to(mobile) {
    padding: map-get($spacing, small);
    flex-direction: column;

    &__nav {
      flex-direction: column;
      gap: map-get($spacing, small);
    }
  }
}

.card {
  padding: map-get($spacing, medium);
  margin: map-get($spacing, medium);
  background: var(--background);
  border: 1px solid var(--border);
  border-radius: 8px;

  &__title {
    font-size: 1.25rem;
    color: var(--primary);
  }

  &__content {
    color: var(--text);
    margin-top: map-get($spacing, small);
  }

  &__button {
    padding: map-get($spacing, small) map-get($spacing, medium);
    background: var(--accent);
    color: var(--text);
    border: none;
    border-radius: 4px;
    cursor: pointer;

    &:hover {
      background: darken(var(--accent), 10%);
    }
  }

  @include respond-to(mobile) {
    margin: map-get($spacing, small);
    padding: map-get($spacing, small);
  }
}

// 7. 工具类 - 通用样式
.text-center {
  text-align: center;
}

.margin-bottom {
  margin-bottom: map-get($spacing, medium);

  @include respond-to(mobile) {
    margin-bottom: map-get($spacing, small);
  }
}

// 8. 动画效果 - 主题切换过渡
@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

.fade-in {
  animation: fadeIn 0.5s ease-in;
}

设计特点和使用说明

1. 主题配置

  • 方法:使用 map 存储深浅主题的颜色配置($themes),通过 map-get 获取具体值。
  • 优势:集中管理颜色,易于扩展新主题(如高对比度主题)。
  • 使用场景:通过 CSS 自定义属性(--variable)和 apply-theme 混合宏动态应用主题,结合 JavaScript 切换类(如 .theme-light.theme-dark)实现主题切换。

2. CSS 自定义属性

  • 方法:将主题颜色定义为 CSS 自定义属性(--primary 等),在组件中直接引用。
  • 优势:支持动态主题切换,减少 SCSS 编译时的重复代码;便于 JavaScript 操作(如动态调整颜色)。
  • 使用场景:在需要动态修改样式的场景(如用户自定义主题)中使用。

3. 模块化结构

  • 方法:按功能组织代码(全局变量、主题配置、组件样式、工具类)。
  • 优势:提高可维护性,方便添加新组件或主题。
  • 使用场景:大型项目中,可将组件样式拆分为单独文件,使用 @use 引入。

4. 响应式支持

  • 方法:通过 @mixin respond-to$breakpoints 管理媒体查询。
  • 优势:统一断点管理,简化响应式样式编写。
  • 使用场景:适配 PC 和移动端,确保深浅主题在不同设备上表现一致。

5. 错误处理

  • 方法:使用 @error 检查无效主题或断点。
  • 优势:提高代码健壮性,方便调试。
  • 使用场景:开发阶段捕获配置错误,避免运行时问题。

6. 动画效果

  • 方法:为主题切换添加过渡效果(如 transition)和动画(如 fadeIn)。
  • 优势:提升用户体验,平滑切换主题。
  • 使用场景:页面加载或主题切换时的视觉效果。

使用方法

1. HTML 结构

<body class="theme-light">
  <header class="header">
    <div class="header__logo">Logo</div>
    <nav class="header__nav">
      <a href="#">Home</a>
      <a href="#">About</a>
    </nav>
  </header>
  <div class="card">
    <h2 class="card__title">Card Title</h2>
    <p class="card__content">Card content here.</p>
    <button class="card__button">Click Me</button>
  </div>
</body>

2. 主题切换

  • 使用 JavaScript 切换 body 的类:
document.body.classList.toggle("theme-dark"); // 切换到深色主题
document.body.classList.toggle("theme-light"); // 切换到浅色主题

3. 扩展主题

  • $themes 中添加新主题(如 high-contrast),只需扩展 map:
$themes: (
  light: (
    ...,
  ),
  dark: (
    ...,
  ),
  high-contrast: (
    background: #000000,
    text: #ffffff,
    primary: #ffff00,
    ...,
  ),
);
.theme-high-contrast {
  @include apply-theme(high-contrast);
}

优势总结

  • 灵活性:通过 map 和 CSS 自定义属性支持动态主题切换。
  • 可维护性:模块化结构和集中配置便于修改和扩展。
  • 响应式:结合媒体查询确保深浅主题在不同设备上表现良好。
  • 用户体验:过渡动画和错误处理提升开发和使用体验。

这个设计适合需要深浅主题切换的现代 Web 应用,可轻松扩展到更多主题或复杂组件,同时保持代码整洁和高效。