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