# Рамка: один макет на все шаблоны

Все главы  [1 Перед началом](https://eile.site/cookbook/nachalo)[2 Установка](https://eile.site/cookbook/ustanovka)[3 Страницы](https://eile.site/cookbook/stranitsy)[4 Первый шаблон](https://eile.site/cookbook/pervyi-shablon)[5 Компоненты](https://eile.site/cookbook/komponenty)[6 Рамка сайта](https://eile.site/cookbook/ramka)[7 Поля страниц](https://eile.site/cookbook/polya)[8 Списки страниц](https://eile.site/cookbook/spiski)[9 Свои настройки](https://eile.site/cookbook/nastroiki)[10 Заявка на замер](https://eile.site/cookbook/forma)[11 Живые части](https://eile.site/cookbook/zhivye-chasti)[12 В интернет](https://eile.site/cookbook/v-internet)[13 Что дальше](https://eile.site/cookbook/dalshe)

# Рамка: один макет на все шаблоны

Скоро шаблонов станет несколько. Чтобы не повторять в каждом шапку, подвал и стили, соберём их в рамку, а шаблоны будут класть внутрь только своё.

Глава 6 из 13 · 2 минуты чтения

## Что повторяется

Посмотрите на Base. В нём заголовок вкладки, шапка, подвал и стили страницы. Всё это понадобится и шаблону кухни, и шаблону проектов. Отличается только середина: у кухни фото и цена, у проектов список работ.

Значит, вынесем всё общее в компонент-рамку. Рамка нарисует шапку и подвал, а в середину вставит то, что ей передал шаблон.

## Компонент Layout

Создайте компонент `Layout`:

Компонент Layout

```
<!-- @component
Рамка сайта: заголовок вкладки, шапка, подвал и общие стили. Шаблон кладёт внутрь свою часть.
-->
<script>
  import Footer from '$components/Footer';
  import Header from '$components/Header';
  import { site } from '$core';

  let { page, children } = $props();
</script>

<svelte:head>
  <title>{page.longTitle || page.title} — {site().name}</title>
</svelte:head>

<Header />

<main>
  {@render children()}
</main>

<Footer note="кухни по вашим размерам" />

<style>
  :global(body) {
    margin: 0;
    background: #f1efeb;
    color: #1f1e1c;
    font: 18px/1.6 system-ui, sans-serif;
  }

  :global(h1) {
    font-size: 2.75rem;
    line-height: 1.05;
    letter-spacing: -0.02em;
  }

  :global(img) {
    max-width: 100%;
    height: auto;
  }

  main {
    max-width: 48rem;
    margin: 0 auto;
    padding: 0 1.5rem 2rem;
  }
</style>
```

Главное здесь две вещи.

- `let { page, children } = $props();`: рамка получает страницу (для заголовка вкладки) и `children`, то есть всё, что шаблон положит между открывающим и закрывающим тегом рамки.
- `{@render children()}`: «нарисуй здесь то, что передали внутрь». Именно на этом месте окажется середина каждого шаблона.

Стили заголовков и картинок стоят в `:global(…)`: так они действуют на всю страницу. Без него стили рамки касались бы только её собственной разметки.

## Base внутри рамки

Замените код Base:

Шаблон Base

```
<script>
  import Content from '$core/Content';
  import Layout from '$components/Layout';

  let { page } = $props();
</script>

<Layout {page}>
  <h1>{page.longTitle || page.title}</h1>
  <Content of={page} />
</Layout>
```

Восемь строк вместо пятидесяти. `<Layout {page}>` это короткая запись `<Layout page={page}>`: когда имя параметра совпадает с именем значения, его можно не повторять.

Сайт выглядит точно так же, как в конце прошлой главы. Так и задумано: мы поменяли устройство, а не вид. Зато следующий шаблон займёт пару минут.