Перейти к содержимому

11. Стилизация (CSS, Modules)

Astro предлагает несколько подходов к стилизации: от scoped стилей по умолчанию до CSS Modules, глобальных стилей и интеграции с препроцессорами. Каждый метод имеет свои преимущества в зависимости от задачи.

Стили внутри <style> в .astro файлах по умолчанию scoped — они применяются только к текущему компоненту. Astro добавляет уникальный атрибут data-astro-cid-xxxxxxxx к элементам.

src/components/Button.astro
---
const { variant = 'primary' } = Astro.props;
---
<button class={`btn btn-${variant}`}>
<slot />
</button>
<style>
/* Эти стили применяются ТОЛЬКО к этому компоненту */
.btn {
padding: 8px 16px;
border-radius: 6px;
border: none;
cursor: pointer;
font-weight: 600;
}
.btn-primary {
background: #FF5D01;
color: white;
}
.btn-secondary {
background: #1e293b;
color: #e2e8f0;
}
</style>

Скомпилированный вывод:

<!-- Astro добавляет уникальный атрибут -->
<button class="btn btn-primary" data-astro-cid-abc123>
Нажми меня
</button>
<style>
/* CSS трансформируется в */
.btn[data-astro-cid-abc123] { ... }
.btn-primary[data-astro-cid-abc123] { ... }
</style>

Директива is:global отключает scoping для отдельных правил или всего блока стилей:

<style>
/* Scoped — применяется только здесь */
.card { padding: 16px; }
/* Global — применяется везде */
:global(body) {
margin: 0;
font-family: system-ui, sans-serif;
}
:global(.highlight) {
background: yellow;
}
</style>

Или весь блок как глобальный:

<style is:global>
/* Все стили здесь глобальные */
h1, h2, h3 {
line-height: 1.3;
}
.prose p {
margin-bottom: 1em;
}
</style>

Для компонентов, требующих изоляции в .jsx/.tsx файлах:

src/components/Card.module.css
.card {
background: #1e293b;
border-radius: 12px;
padding: 20px;
}
.title {
color: #e2e8f0;
font-size: 1.2rem;
}
.badge {
background: #FF5D01;
color: white;
border-radius: 4px;
padding: 2px 8px;
font-size: 0.75rem;
}
src/components/Card.jsx
import styles from './Card.module.css';
export default function Card({ title, badge }) {
return (
<div className={styles.card}>
<h2 className={styles.title}>{title}</h2>
<span className={styles.badge}>{badge}</span>
</div>
);
}
src/layouts/BaseLayout.astro
<html>
<head>
<style is:global>
:root {
--color-brand: #FF5D01;
--color-bg: #0f172a;
--color-card: #1e293b;
--color-text: #e2e8f0;
--color-muted: #64748b;
--radius-md: 8px;
--radius-lg: 12px;
--spacing-sm: 8px;
--spacing-md: 16px;
}
[data-theme="light"] {
--color-bg: #f8fafc;
--color-card: #ffffff;
--color-text: #1e293b;
}
</style>
</head>
<body>
<slot />
</body>
</html>
<style>
/* Использование CSS переменных в компоненте */
.card {
background: var(--color-card);
border-radius: var(--radius-lg);
padding: var(--spacing-md);
color: var(--color-text);
}
</style>
---
// В frontmatter — импортируется в бандл
import '../styles/global.css';
import '../styles/typography.css';
---
<!-- В HTML теге — внешняя таблица стилей -->
<link rel="stylesheet" href="/styles/vendor.css" />

Для SCSS установите sass:

Окно терминала
npm install sass
<style lang="scss">
$brand: #FF5D01;
$bg: #0f172a;
.card {
background: $bg;
&:hover {
border-color: $brand;
}
&__title {
color: lighten($brand, 20%);
}
@media (max-width: 768px) {
padding: 12px;
}
}
</style>