CSS样式 #

一、Scoped 样式 #

1.1 基本用法 #

Astro 组件内的 <style> 标签默认是作用域隔离的:

astro
---
// src/components/Button.astro
---

<button class="btn">
  <slot />
</button>

<style>
  .btn {
    padding: 0.5rem 1rem;
    background: #2563eb;
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
  }

  .btn:hover {
    background: #1d4ed8;
  }
</style>

1.2 样式隔离原理 #

Astro 为每个组件生成唯一的类名:

html
<!-- 编译前 -->
<button class="btn">按钮</button>
<style>.btn { color: blue; }</style>

<!-- 编译后 -->
<button class="btn astro-XXXXXX">按钮</button>
<style>.btn.astro-XXXXXX { color: blue; }</style>

二、全局样式 #

2.1 is:global 指令 #

astro
---
// src/components/Button.astro
---

<button class="btn">
  <slot />
</button>

<style is:global>
  .btn {
    padding: 0.5rem 1rem;
    background: #2563eb;
    color: white;
  }
</style>

2.2 :global() 选择器 #

astro
---
// src/components/Card.astro
---

<div class="card">
  <slot />
</div>

<style>
  .card {
    padding: 1rem;
    border: 1px solid #e5e7eb;
  }

  .card :global(h2) {
    font-size: 1.5rem;
    margin-bottom: 0.5rem;
  }

  .card :global(p) {
    color: #6b7280;
  }
</style>

2.3 全局样式文件 #

css
/* src/styles/global.css */
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  font-family: system-ui, -apple-system, sans-serif;
  line-height: 1.6;
}

a {
  color: #2563eb;
  text-decoration: none;
}

a:hover {
  text-decoration: underline;
}
astro
---
// src/layouts/Layout.astro
import '../styles/global.css';
---

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
  </head>
  <body>
    <slot />
  </body>
</html>

三、CSS 变量 #

3.1 定义变量 #

astro
---
// src/layouts/Layout.astro
---

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
  </head>
  <body>
    <slot />
  </body>
</html>

<style is:global>
  :root {
    --color-primary: #2563eb;
    --color-secondary: #6b7280;
    --color-success: #10b981;
    --color-danger: #ef4444;
    --color-warning: #f59e0b;
    
    --font-sans: system-ui, -apple-system, sans-serif;
    --font-mono: 'SF Mono', Monaco, monospace;
    
    --spacing-1: 0.25rem;
    --spacing-2: 0.5rem;
    --spacing-4: 1rem;
    --spacing-8: 2rem;
    
    --radius-sm: 4px;
    --radius-md: 8px;
    --radius-lg: 12px;
  }
</style>

3.2 使用变量 #

astro
---
// src/components/Button.astro
interface Props {
  variant?: 'primary' | 'secondary' | 'danger';
}

const { variant = 'primary' } = Astro.props;
---

<button class:list={['btn', `btn-${variant}`]}>
  <slot />
</button>

<style>
  .btn {
    padding: var(--spacing-2) var(--spacing-4);
    border: none;
    border-radius: var(--radius-sm);
    cursor: pointer;
    font-family: var(--font-sans);
  }

  .btn-primary {
    background: var(--color-primary);
    color: white;
  }

  .btn-secondary {
    background: var(--color-secondary);
    color: white;
  }

  .btn-danger {
    background: var(--color-danger);
    color: white;
  }
</style>

3.3 主题切换 #

astro
---
// src/layouts/Layout.astro
---

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
  </head>
  <body>
    <slot />
    <script>
      const theme = localStorage.getItem('theme') || 'light';
      document.documentElement.setAttribute('data-theme', theme);
    </script>
  </body>
</html>

<style is:global>
  :root {
    --bg-primary: #ffffff;
    --text-primary: #1f2937;
  }

  [data-theme="dark"] {
    --bg-primary: #1f2937;
    --text-primary: #f9fafb;
  }

  body {
    background: var(--bg-primary);
    color: var(--text-primary);
  }
</style>

四、内联样式 #

4.1 style 属性 #

astro
---
const bgColor = '#2563eb';
---

<div style={`background-color: ${bgColor};`}>
  内容
</div>

4.2 条件样式 #

astro
---
const isActive = true;
---

<button style={isActive ? 'background: blue;' : 'background: gray;'}>
  按钮
</button>

五、响应式设计 #

5.1 媒体查询 #

astro
---
// src/components/Container.astro
---

<div class="container">
  <slot />
</div>

<style>
  .container {
    width: 100%;
    padding: 0 1rem;
    margin: 0 auto;
  }

  @media (min-width: 640px) {
    .container {
      max-width: 640px;
    }
  }

  @media (min-width: 768px) {
    .container {
      max-width: 768px;
    }
  }

  @media (min-width: 1024px) {
    .container {
      max-width: 1024px;
    }
  }
</style>

5.2 响应式组件 #

astro
---
// src/components/Grid.astro
interface Props {
  columns?: number;
}

const { columns = 3 } = Astro.props;
---

<div class="grid" style={`--columns: ${columns};`}>
  <slot />
</div>

<style>
  .grid {
    display: grid;
    grid-template-columns: repeat(1, 1fr);
    gap: 1rem;
  }

  @media (min-width: 640px) {
    .grid {
      grid-template-columns: repeat(2, 1fr);
    }
  }

  @media (min-width: 1024px) {
    .grid {
      grid-template-columns: repeat(var(--columns), 1fr);
    }
  }
</style>

六、CSS 最佳实践 #

6.1 组件样式组织 #

astro
---
// src/components/Card.astro
interface Props {
  title: string;
  variant?: 'default' | 'featured';
}

const { title, variant = 'default' } = Astro.props;
---

<article class:list={['card', `card-${variant}`]}>
  <h3 class="card-title">{title}</h3>
  <div class="card-content">
    <slot />
  </div>
</article>

<style>
  .card {
    background: white;
    border: 1px solid #e5e7eb;
    border-radius: 8px;
    padding: 1.5rem;
  }

  .card-featured {
    border-color: var(--color-primary);
    box-shadow: 0 4px 12px rgba(37, 99, 235, 0.15);
  }

  .card-title {
    font-size: 1.25rem;
    margin-bottom: 1rem;
  }

  .card-content {
    color: #6b7280;
  }
</style>

6.2 样式复用 #

css
/* src/styles/utilities.css */
.flex {
  display: flex;
}

.flex-col {
  flex-direction: column;
}

.items-center {
  align-items: center;
}

.justify-between {
  justify-content: space-between;
}

.gap-4 {
  gap: 1rem;
}

七、总结 #

CSS 样式核心要点:

text
┌─────────────────────────────────────────────────────┐
│                 CSS 样式要点                         │
├─────────────────────────────────────────────────────┤
│                                                     │
│  🎨 Scoped 样式  组件级样式隔离                     │
│                                                     │
│  🌐 全局样式    is:global 或全局文件                │
│                                                     │
│  📦 CSS 变量    主题和设计系统                      │
│                                                     │
│  📱 响应式      媒体查询适配                        │
│                                                     │
│  🔧 内联样式    动态样式值                          │
│                                                     │
└─────────────────────────────────────────────────────┘

下一步,让我们学习 UI框架集成,在 Astro 中使用 React、Vue 等框架!

最后更新:2026-03-28