Что такое layouts в Astro и как они используются со свойством layout во frontmatter?
Layout в Astro — компонент с <slot />, который оборачивает контент страниц; в .md/.mdx файлах он указывается через свойство layout во frontmatter, и тогда всё содержимое Markdown подставляется в слот.
Layouts в Astro
Layout в Astro — это обычный .astro-компонент, который оборачивает контент страниц. Он содержит повторяющиеся элементы: <html>, <head>, навигацию, футер. Дочерний контент вставляется через компонент <slot />.
Создание layout-компонента
---
// src/layouts/BaseLayout.astro
const { title, description = 'Мой сайт' } = Astro.props;
---
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<meta name="description" content={description} />
<title>{title}</title>
</head>
<body>
<nav>...</nav>
<main>
<slot /> <!-- Сюда подставляется контент страницы -->
</main>
<footer>...</footer>
</body>
</html>
Использование layout в .astro-странице
---
// src/pages/about.astro
import BaseLayout from '../layouts/BaseLayout.astro';
---
<BaseLayout title="О нас" description="Страница о компании">
<h1>О нас</h1>
<p>Добро пожаловать!</p>
</BaseLayout>
Использование layout в Markdown через frontmatter
В .md и .mdx файлах layout указывается в свойстве layout во frontmatter. Astro автоматически оборачивает содержимое файла в указанный компонент.
---
# src/content/blog/my-post.md
layout: ../../layouts/BlogPostLayout.astro
title: Мой первый пост
date: 2024-01-15
author: Иван Иванов
---
# Заголовок поста
Текст статьи в формате Markdown.
Layout для Markdown получает все frontmatter-данные через Astro.props.frontmatter:
---
// src/layouts/BlogPostLayout.astro
const { frontmatter } = Astro.props;
// frontmatter.title, frontmatter.date, frontmatter.author
---
<html lang="ru">
<head>
<title>{frontmatter.title}</title>
</head>
<body>
<article>
<h1>{frontmatter.title}</h1>
<time>{frontmatter.date}</time>
<slot /> <!-- Отрендеренный Markdown попадёт сюда -->
</article>
</body>
</html>
Именованные слоты
Layout может содержать несколько именованных слотов:
---
// src/layouts/TwoColumn.astro
---
<div class="layout">
<aside><slot name="sidebar" /></aside>
<main><slot /><!-- default slot --></main>
</div>
---
// src/pages/dashboard.astro
import TwoColumn from '../layouts/TwoColumn.astro';
---
<TwoColumn>
<nav slot="sidebar">Навигация</nav>
<h1>Главный контент</h1>
</TwoColumn>
Вложенные layouts
Layouts можно вкладывать: BlogLayout использует BaseLayout внутри себя, создавая иерархию шаблонов.
Подводные камни
- frontmatter.layout — строка-путь, не импорт — в Markdown нужно указывать относительный путь к файлу, а не имя компонента; неверный путь приведёт к ошибке сборки.
- Astro.props.frontmatter только в Markdown-layouts — в обычных страницах
frontmatterв props не приходит; данные передаются явно через атрибуты. - Дублирование тега html — если layout уже содержит
<html>, а страница тоже добавляет его через другой layout, получится невалидный HTML. - Слот по умолчанию без имени — содержимое без
slot="name"попадает в<slot />без атрибута; если его нет в layout, контент будет проигнорирован. - Styles в layout применяются глобально —
<style>внутри layout безis:globalвсё равно scoped; для глобальных стилей нужен<style is:global>. - MDX и layout — в
.mdxфайлах можно также экспортироватьexport const layoutвместо frontmatter, но два подхода одновременно конфликтуют.
Common mistakes
- Ждать, что
layoutво frontmatter сработает для Content Collections. - Не использовать именованные слоты и копировать одинаковую структуру.
- Тащить бизнес-логику в layout, делая его непредсказуемым.
What the interviewer is testing
- Знает, что layout это обычный
.astroсо<slot />. - Различает применение в
.astroи в Markdown frontmatter. - Понимает ограничения для Content Collections.