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

HTML + CSS — готовые макеты

Готовые одностраничные шаблоны: скопировали код в файл index.html, открыли в браузере — макет уже работает. Если нужен разбор тегов и семантики целой страницы (без упора на CSS) — сначала HTML-страницы целиком. Подойдёт для урока информатики, лабораторной по вебу, домашнего задания, первого портфолио или когда в поиске нужны запросы вроде «html css центрировать блок», «flexbox шапка подвал», «адаптивная сетка карточек». Те же задачи через utility-классы — в соседней главе Tailwind — готовые блоки.

Под каждым примером — разбор строк: что делает свойство и зачем оно здесь. Сначала простые макеты, затем каркас сайта, лендинг, дашборд и адаптив.


Основы вёрстки

С чего начать

Теория — в HTML и CSS. Подробно про Flexbox и Grid — отдельная глава. Шпаргалка «что использовать / чего избегать» — Практические рекомендации по CSS.

Загрузка HTML-песочницы…

Вставьте любой пример из статьи в редактор выше — предпросмотр обновится через пару секунд. Так быстрее, чем каждый раз сохранять файл на диск.

Загрузка Flex/Grid…

Мини-симулятор показывает, как Flex и Grid по-разному раскладывают четыре блока. Перед сложными макетами полезно покрутить justify-content и align-items.


Базовые термины

ТерминПростыми словами
HTMLРазметка: заголовки, абзацы, кнопки, формы — «скелет» страницы
CSSСтили: цвета, отступы, сетка, расположение блоков
Макет (layout)Как блоки стоят относительно друг друга и экрана
FlexboxРаскладка в одну линию (ряд или столбец) с выравниванием
CSS GridРаскладка в таблицу из строк и колонок сразу
АдаптивСтраница подстраивается под ширину телефона и монитора
Медиазапрос @mediaДругие стили, когда экран уже или шире порога
remЕдиница от размера шрифта корня; удобна для отступов
viewportВидимая область браузера; без meta-тега на телефоне страница «мелкая»

Как работать с примерами

  1. Скопируйте весь блок кода (от <!DOCTYPE html> до </html>).
  2. Вставьте в файл макет.html (или index.html).
  3. Откройте двойным щелчком или перетащите в Chrome / Edge / Firefox.
  4. Меняйте текст, цвета, числа в padding — смотрите, что изменилось.
  5. Если сломали — верните исходник из статьи и меняйте по одному свойству.
Flex или Grid

Flexbox — меню в ряд, кнопки в форме, колонка «шапка — контент — подвал», выравнивание по центру.
Grid — каркас страницы (шапка, сайдбар, контент), сетка карточек одинаковой ширины, bento-блоки разного размера.
В реальных сайтах их комбинируют: Grid для страницы, Flex внутри карточки.


Обязательный каркас каждой страницы

Любой пример ниже можно собрать на этом фундаменте.

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Макет</title>
<style>
*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; font-family: system-ui, sans-serif; line-height: 1.5; }
img { max-width: 100%; height: auto; display: block; }
</style>
</head>
<body>
<!-- сюда ваша разметка -->
</body>
</html>

Разбор по строкам.

ФрагментСмысл
<!DOCTYPE html>Сообщает браузеру режим HTML5 (страница рисуется предсказуемо)
lang="ru"Язык страницы: озвучка скринридеров, переносы слов
<meta charset="UTF-8">Кириллица и emoji отображаются правильно
viewport + width=device-widthНа телефоне ширина макета = ширина экрана, без «уменьшенного десктопа»
<style>…</style>CSS в том же файле; для учёбы удобно, в проекте стили часто в .css
box-sizing: border-boxpadding и border входят в заявленную ширину блока — сетка не «плывёт»
body &#123; margin: 0 &#125;Убирает белую полоску по умолчанию у краёв окна
img &#123; max-width: 100% &#125;Картинка не вылезает за экран на узком телефоне

Типичные ошибки.

  • Забыли viewport — на мобильном всё мелкое, нужен зум пальцами.
  • Стили в <body> через атрибут style="" на каждом теге — править макет трудно.
  • Нет box-sizing: border-box — блоки с width: 50% в два столбца не помещаются в ряд.

Вынести CSS в файл (как в «взрослых» проектах):

<link rel="stylesheet" href="style.css">

Файл style.css лежит в той же папке, что и HTML.


Стартовые макеты

Простые задачи, которые чаще всего ищут в интернете.


Центрированная карточка

Задача. Окно входа, сообщение «скоро откроемся», одна карточка по центру экрана.

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Карточка по центру</title>
<style>
*, *::before, *::after { box-sizing: border-box; }
body {
margin: 0;
min-height: 100dvh;
display: grid;
place-items: center;
padding: 1rem;
font-family: system-ui, sans-serif;
background: #f0f4ff;
}
.card {
width: min(100%, 22rem);
padding: 1.5rem;
background: #fff;
border-radius: 12px;
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.1);
}
h1 { margin: 0 0 0.5rem; font-size: 1.35rem; }
p { margin: 0 0 1rem; color: #444; }
button {
width: 100%;
padding: 0.65rem;
border: none;
border-radius: 8px;
background: #4361ee;
color: #fff;
font-weight: 600;
cursor: pointer;
}
</style>
</head>
<body>
<article class="card">
<h1>Добро пожаловать</h1>
<p>Карточка по центру экрана.</p>
<button type="button">Продолжить</button>
</article>
</body>
</html>

Разбор CSS.

СвойствоЗачем здесь
min-height: 100dvhВысота не меньше окна; dvh учитывает панель адреса на телефоне
display: grid на bodyВключает сетку из одной «ячейки» на весь экран
place-items: centerСокращение: центр по горизонтали и вертикали сразу
padding: 1rem на bodyНа узком экране карточка не прилипает к краям
width: min(100%, 22rem)На телефоне — вся ширина минус отступы; на ПК — не шире ~352px
border-radius, box-shadowСкругление и лёгкая тень — визуально «карточка», а не просто белый прямоугольник
button &#123; width: 100% &#125;Кнопка на всю ширину карточки — привычный паттерн для форм

HTML. Тег <article> семантически означает самостоятельный блок контента (для курсовой и доступности лучше, чем голый <div>).

Типичные ошибки.

  • Центрируют через position: absolute; top: 50%; left: 50% без знания transform — на разной высоте контента блок съезжает.
  • Задают height: 100vh на мобильном — под карточкой появляется лишняя прокрутка из‑за адресной строки.

Попробуйте сами. Поменяйте place-items: center на start — карточка прижмётся к верху. Уберите box-shadow — плоский плоский дизайн.


Шапка и подвал — контент между ними (Flexbox)

Задача. Подвал всегда внизу окна, даже если текста в main мало («липкий footer»).

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Страница-столбец</title>
<style>
*, *::before, *::after { box-sizing: border-box; }
body {
margin: 0;
min-height: 100dvh;
display: flex;
flex-direction: column;
font-family: system-ui, sans-serif;
}
header, footer {
padding: 1rem 1.25rem;
background: #1e1e2e;
color: #cdd6f4;
}
main {
flex: 1;
padding: 1.25rem;
max-width: 48rem;
margin: 0 auto;
width: 100%;
}
nav { display: flex; gap: 1rem; flex-wrap: wrap; }
nav a { color: #89b4fa; text-decoration: none; }
</style>
</head>
<body>
<header>
<strong>Мой сайт</strong>
<nav>
<a href="#">Главная</a>
<a href="#">О проекте</a>
<a href="#">Контакты</a>
</nav>
</header>
<main>
<h1>Контент</h1>
<p>Мало текста — подвал всё равно внизу.</p>
</main>
<footer>© 2026</footer>
</body>
</html>

Разбор.

БлокИдея
body + flex + columnТри зоны друг под другом: шапка, середина, подвал
main &#123; flex: 1 &#125;Средняя часть забирает всё свободное место, выталкивая footer вниз
max-width + margin: 0 auto на mainТекст не растягивается на весь 4K-монитор — удобно читать
nav &#123; display: flex; gap: 1rem &#125;Ссылки в ряд с равномерным зазором без отступов на каждой ссылке
flex-wrap: wrapНа узком экране пункты меню переносятся на следующую строку

Типичные ошибки.

  • Пытаются прижать подвал через position: fixed — он перекрывает текст при прокрутке.
  • Нет min-height: 100dvh на body — при длинном контенте разницы нет, при коротком подвал «всплывает» вверх.

Попробуйте сами. Добавьте в main десять абзацев — подвал уйдёт за нижний край и появится прокрутка (это нормально).


Адаптивная сетка карточек

Задача. Каталог товаров, галерея проектов, карточки новостей — сами перестраиваются в 1–2–3–4 колонки.

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Сетка карточек</title>
<style>
*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; padding: 1.25rem; font-family: system-ui, sans-serif; background: #fafafa; }
h1 { margin-top: 0; }
.grid {
display: grid;
gap: 1rem;
grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
}
.card {
background: #fff;
border-radius: 10px;
padding: 1rem;
border: 1px solid #e5e5e5;
}
.card h2 { margin: 0 0 0.35rem; font-size: 1.1rem; }
.card p { margin: 0; color: #555; font-size: 0.95rem; }
</style>
</head>
<body>
<h1>Каталог</h1>
<div class="grid">
<article class="card"><h2>Товар A</h2><p>Описание.</p></article>
<article class="card"><h2>Товар B</h2><p>Описание.</p></article>
<article class="card"><h2>Товар C</h2><p>Описание.</p></article>
<article class="card"><h2>Товар D</h2><p>Описание.</p></article>
</div>
</body>
</html>

Разбор ключевой строки.

grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  • minmax(14rem, 1fr) — колонка не уже 14rem, но может растянуться (1fr).
  • auto-fit — браузер сам считает, сколько колонок влезает в ряд.
  • gap: 1rem — расстояние между карточками без margin на каждой.

Типичные ошибки.

  • Фиксируют grid-template-columns: repeat(4, 1fr) — на телефоне четыре узких полоски.
  • Делают отступы только через margin-right — у последней карточки в ряду отступ лишний; gap проще.

Попробуйте сами. Замените 14rem на 10rem — колонок станет больше. Добавьте пятую карточку в HTML — сетка пересчитается сама.


Две колонки — текст и картинка

Задача. Блок «о нас», лендинг, статья с иллюстрацией: на телефоне столбик, на планшете — две колонки.

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Две колонки</title>
<style>
*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; font-family: system-ui, sans-serif; }
.split {
display: grid;
gap: 1.5rem;
padding: 1.5rem;
max-width: 56rem;
margin: 0 auto;
}
@media (min-width: 40rem) {
.split { grid-template-columns: 1fr 1fr; align-items: center; }
}
.media {
aspect-ratio: 4 / 3;
border-radius: 12px;
background: linear-gradient(135deg, #667eea, #764ba2);
}
</style>
</head>
<body>
<section class="split">
<div>
<h1>Заголовок</h1>
<p>Узкий экран — блоки друг под другом. От 640px — в два столбца.</p>
</div>
<div class="media" aria-hidden="true"></div>
</section>
</body>
</html>

Разбор.

ЭлементСмысл
Без медиазапросаОдна колонка — mobile-first (сначала стили для телефона)
@media (min-width: 40rem)От ~640px включаются две равные колонки 1fr 1fr
align-items: centerТекст и «картинка» по вертикали по центру друг относительно друга
aspect-ratio: 4 / 3Прямоугольник держит пропорции, пока нет настоящего <img>
aria-hidden="true" на декоративном блокеСкринридер не озвучивает пустой градиент

Типичные ошибки.

  • Пишут max-width в медиазапросе для «десктопа» в новом проекте — путаница; для учёбы проще min-width от мобильной базы.
  • Ставят две колонки без медиазапроса — на телефоне текст и картинка слишком узкие.

Форма входа по центру

Задача. Страница логина, регистрации, восстановления пароля.

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Вход</title>
<style>
*, *::before, *::after { box-sizing: border-box; }
body {
margin: 0;
min-height: 100dvh;
display: flex;
align-items: center;
justify-content: center;
padding: 1rem;
font-family: system-ui, sans-serif;
background: #eef2ff;
}
form {
width: min(100%, 20rem);
display: flex;
flex-direction: column;
gap: 0.75rem;
padding: 1.5rem;
background: #fff;
border-radius: 12px;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
}
label { font-size: 0.9rem; color: #333; }
input {
width: 100%;
padding: 0.55rem 0.65rem;
border: 1px solid #ccc;
border-radius: 8px;
}
button {
margin-top: 0.25rem;
padding: 0.65rem;
border: none;
border-radius: 8px;
background: #2d6a4f;
color: #fff;
font-weight: 600;
cursor: pointer;
}
</style>
</head>
<body>
<form>
<h1 style="margin:0;font-size:1.25rem">Вход</h1>
<label>Email <input type="email" required placeholder="you@mail.ru"></label>
<label>Пароль <input type="password" required minlength="4"></label>
<button type="submit">Войти</button>
</form>
</body>
</html>

Разбор.

ПриёмЗачем
flex + align-items + justify-content на bodyЦентрирование формы (альтернатива grid + place-items)
flex-direction: column + gap на formПоля друг под другом с одинаковыми промежутками
input внутри labelКлик по тексту «Email» фокусирует поле — удобнее на телефоне
type="email", required, minlengthБазовая проверка в браузере без JavaScript
width: 100% у inputПоле на всю ширину формы при box-sizing: border-box

Типичные ошибки.

  • Забывают type="submit" у кнопки — Enter в поле может не отправить форму.
  • Нет name у полей — если позже подключите сервер (PHP и т.д.), данные не придут.

Попробуйте сами. Уберите required и отправьте пустую форму — браузер покажет подсказки (если не отключена валидация).


Готовые макеты страниц

Составные шаблоны для сайта, лендинга и панели администратора.


1. Каркас сайта на CSS Grid

1.1. Шапка, боковое меню, контент, подвал

Задача. Типичный учебный «сайт-визитка» или админка с меню слева.

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Каркас Grid</title>
<style>
*, *::before, *::after { box-sizing: border-box; }
body {
margin: 0;
min-height: 100dvh;
display: grid;
grid-template-columns: 12rem 1fr;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header"
"nav main"
"footer footer";
font-family: system-ui, sans-serif;
}
header { grid-area: header; padding: 1rem 1.25rem; background: #313244; color: #cdd6f4; }
nav {
grid-area: nav;
padding: 1rem;
background: #45475a;
color: #bac2de;
}
nav a { display: block; color: inherit; text-decoration: none; margin-bottom: 0.5rem; }
main { grid-area: main; padding: 1.25rem; }
footer {
grid-area: footer;
padding: 0.75rem 1.25rem;
background: #1e1e2e;
color: #a6adc8;
font-size: 0.9rem;
}
@media (max-width: 48rem) {
body {
grid-template-columns: 1fr;
grid-template-areas:
"header"
"nav"
"main"
"footer";
}
nav { display: flex; gap: 1rem; flex-wrap: wrap; }
nav a { margin: 0; }
}
</style>
</head>
<body>
<header><strong>Панель</strong></header>
<nav>
<a href="#">Раздел 1</a>
<a href="#">Раздел 2</a>
<a href="#">Раздел 3</a>
</nav>
<main>
<h1>Контент</h1>
<p>Сетка из именованных областей <code>grid-template-areas</code>.</p>
</main>
<footer>Подвал</footer>
</body>
</html>

Разбор grid-template-areas.

"header header" ← шапка на всю ширину (2 колонки)
"nav main" ← слева меню 12rem, справа контент
"footer footer" ← подвал на всю ширину

Каждый дочерний блок с grid-area: header (и т.д.) попадает в «клетку» схемы. Менять макет можно, переставив буквы в кавычках — без перестановки HTML.

На мобильном (max-width: 48rem)Что происходит
Одна колонкаОбласти идут столбиком: шапка → меню → текст → подвал
nav &#123; display: flex &#125;Пункты меню в ряд, а не столбиком слева

Типичные ошибки.

  • Опечатка в имени области ("heder" вместо "header") — блок исчезает из сетки.
  • Разное количество столбцов в строках areas — правило CSS не применится.

2. Лендинг и навигация

2.1. Герой-блок и три преимущества

Задача. Одностраничный промо-сайт: меню, большой заголовок, кнопка, карточки ниже.

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Лендинг</title>
<style>
*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; font-family: system-ui, sans-serif; color: #1e1e2e; }
.wrap { max-width: 64rem; margin: 0 auto; padding: 0 1.25rem; }
.top {
display: flex;
align-items: center;
justify-content: space-between;
gap: 1rem;
padding: 1rem 0;
flex-wrap: wrap;
}
.top nav { display: flex; gap: 1rem; }
.top a { color: #4361ee; text-decoration: none; font-weight: 500; }
.hero {
padding: 4rem 0;
text-align: center;
background: linear-gradient(180deg, #eef2ff 0%, #fff 70%);
}
.hero h1 { font-size: clamp(1.75rem, 4vw, 2.75rem); margin: 0 0 0.75rem; }
.hero p { max-width: 36rem; margin: 0 auto 1.5rem; color: #444; }
.cta {
display: inline-block;
padding: 0.75rem 1.5rem;
background: #4361ee;
color: #fff;
border-radius: 999px;
text-decoration: none;
font-weight: 600;
}
.features {
display: grid;
gap: 1.25rem;
grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
padding: 3rem 0;
}
.feat {
padding: 1rem;
border: 1px solid #e5e7eb;
border-radius: 10px;
}
</style>
</head>
<body>
<div class="wrap top">
<strong>Product</strong>
<nav>
<a href="#">Возможности</a>
<a href="#">Цены</a>
<a href="#">Контакты</a>
</nav>
</div>
<section class="hero wrap">
<h1>Сервис для команды</h1>
<p>Заголовок плавно растёт с шириной экрана.</p>
<a class="cta" href="#">Попробовать</a>
</section>
<section class="wrap features">
<div class="feat"><h2>Быстро</h2><p>Запуск за минуты.</p></div>
<div class="feat"><h2>Надёжно</h2><p>Резервные копии.</p></div>
<div class="feat"><h2>Просто</h2><p>Без лишней настройки.</p></div>
</section>
</body>
</html>

Разбор.

ПриёмСмысл
.wrapОграничитель ширины контента по центру (max-width + margin: 0 auto)
justify-content: space-between в шапкеЛоготип слева, ссылки справа
clamp(1.75rem, 4vw, 2.75rem)Шрифт заголовка от 28px до 44px в зависимости от окна
border-radius: 999px на .cta«Таблетка» — типичная форма кнопки призыва
Повтор auto-fit + minmax в .featuresТа же адаптивная сетка, что у каталога карточек

2.2. Липкая шапка при прокрутке

Задача. Меню остаётся сверху, пока читаете длинную статью.

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Sticky header</title>
<style>
*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; font-family: system-ui, sans-serif; }
header {
position: sticky;
top: 0;
z-index: 10;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0.75rem 1.25rem;
background: rgba(255, 255, 255, 0.92);
backdrop-filter: blur(8px);
border-bottom: 1px solid #e5e7eb;
}
main { padding: 1.25rem; max-width: 40rem; margin: 0 auto; }
main p { margin-bottom: 1.25rem; }
</style>
</head>
<body>
<header>
<strong>Журнал</strong>
<span>Меню</span>
</header>
<main>
<h1>Длинная статья</h1>
<p>Прокрутите вниз — шапка останется сверху.</p>
<p>Добавьте сюда ещё абзацы для проверки…</p>
<p>…и ещё один абзац.</p>
</main>
</body>
</html>

Разбор.

СвойствоСмысл
position: stickyЭлемент ведёт себя как обычный, пока не «прилипнет» к top: 0 при скролле
z-index: 10Шапка рисуется поверх текста, а не под ним
rgba(255,255,255,0.92)Полупрозрачный фон — лёгкий эффект стекла
backdrop-filter: blur(8px)Размытие контента под шапкой (в старых браузерах просто непрозрачный фон)

Отличие от fixed. fixed вырывает шапку из потока — нужен padding-top у main. sticky проще для учебных статей.


3. Дашборд и bento-сетка

3.1. Боковая панель + плитки метрик

Задача. Макет «админки»: меню слева, сверху заголовок раздела, ниже виджеты.

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Дашборд</title>
<style>
*, *::before, *::after { box-sizing: border-box; }
body {
margin: 0;
min-height: 100dvh;
display: grid;
grid-template-columns: 14rem 1fr;
font-family: system-ui, sans-serif;
}
aside {
padding: 1rem;
background: #1e293b;
color: #e2e8f0;
}
aside a { display: block; color: #94a3b8; text-decoration: none; padding: 0.4rem 0; }
aside a:hover { color: #fff; }
.workspace { display: flex; flex-direction: column; min-width: 0; }
.bar {
padding: 0.75rem 1rem;
border-bottom: 1px solid #e2e8f0;
font-weight: 600;
}
.tiles {
flex: 1;
padding: 1rem;
display: grid;
gap: 1rem;
grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
align-content: start;
}
.tile {
padding: 1rem;
background: #f8fafc;
border: 1px solid #e2e8f0;
border-radius: 8px;
}
@media (max-width: 40rem) {
body { grid-template-columns: 1fr; }
aside { display: flex; gap: 1rem; flex-wrap: wrap; }
}
</style>
</head>
<body>
<aside>
<strong style="display:block;margin-bottom:0.75rem">Admin</strong>
<a href="#">Обзор</a>
<a href="#">Пользователи</a>
<a href="#">Отчёты</a>
</aside>
<div class="workspace">
<div class="bar">Главная</div>
<div class="tiles">
<div class="tile">Посетители<br /><strong>1 240</strong></div>
<div class="tile">Заказы<br /><strong>86</strong></div>
<div class="tile">Выручка<br /><strong>₽ 42k</strong></div>
</div>
</div>
</body>
</html>

Разбор.

  • Grid на body — две большие зоны: сайдбар и рабочая область.
  • Flex на .workspace — внутри правой части бар сверху, плитки заполняют остаток (flex: 1 у .tiles).
  • min-width: 0 — flex-ребёнок может сжиматься; без этого иногда появляется горизонтальная прокрутка.
  • Вложенный Grid в .tiles — снова auto-fit для карточек метрик.

3.2. Bento — плитки разного размера

Задача. Современная сетка «как у Apple / Notion»: одни ячейки шире или выше других.

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bento</title>
<style>
*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; padding: 1rem; font-family: system-ui, sans-serif; background: #0f172a; color: #f8fafc; }
.bento {
display: grid;
gap: 0.75rem;
max-width: 48rem;
margin: 0 auto;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: 5rem;
}
.cell {
border-radius: 12px;
padding: 1rem;
background: #334155;
display: flex;
align-items: flex-end;
font-weight: 600;
}
.wide { grid-column: span 2; background: #6366f1; }
.tall { grid-row: span 2; background: #0ea5e9; }
.big { grid-column: span 2; grid-row: span 2; background: #10b981; }
@media (max-width: 36rem) {
.bento { grid-template-columns: 1fr 1fr; }
.wide, .big { grid-column: span 2; }
}
</style>
</head>
<body>
<div class="bento">
<div class="cell wide">Широкий</div>
<div class="cell">A</div>
<div class="cell tall">Высокий</div>
<div class="cell">B</div>
<div class="cell big">Крупный</div>
<div class="cell">C</div>
</div>
</body>
</html>

Разбор.

КлассЭффект
grid-auto-rows: 5remВысота одной «ступеньки» сетки — 80px
grid-column: span 2Блок занимает 2 колонки
grid-row: span 2Блок занимает 2 ряда
.bigИ ширина, и высота удвоены — крупная плитка

4. Статья и тарифы

4.1. Текст и боковая колонка

Задача. Блог, документация: основной текст + метаданные справа.

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Статья</title>
<style>
*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; font-family: Georgia, serif; line-height: 1.65; color: #222; }
.layout {
display: grid;
gap: 2rem;
max-width: 56rem;
margin: 0 auto;
padding: 1.5rem 1.25rem;
}
@media (min-width: 48rem) {
.layout { grid-template-columns: minmax(0, 1fr) 12rem; }
}
article { max-width: 65ch; }
article h1 { font-family: system-ui, sans-serif; line-height: 1.2; }
aside {
font-family: system-ui, sans-serif;
font-size: 0.9rem;
color: #555;
border-top: 3px solid #4361ee;
padding-top: 0.75rem;
}
</style>
</head>
<body>
<div class="layout">
<article>
<h1>Заголовок материала</h1>
<p>Основной текст. На десктопе сайдбар справа, на телефоне — под статьёй.</p>
</article>
<aside>
<p><strong>Автор</strong><br />И. Иванов</p>
<p><strong>Обновлено</strong><br />31 мая 2026</p>
</aside>
</div>
</body>
</html>

Разбор.

ПриёмСмысл
65chШирина текста в символах — глаза меньше устают, чем на всю ширину монитора
minmax(0, 1fr)Колонка с текстом может сжиматься; длинные слова не ломают сетку
Порядок в HTML: article, потом asideНа мобильном сначала главное, метаданные ниже — хорошо для чтения и SEO
border-top у asideВизуально отделяет боковую колонку без лишней рамки вокруг всего

4.2. Три тарифа в ряд

Задача. Страница цен: карточки «Базовый / Про / Команда», средний выделен.

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Тарифы</title>
<style>
*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; padding: 1.5rem; font-family: system-ui, sans-serif; background: #f8fafc; }
h1 { text-align: center; }
.plans {
display: grid;
gap: 1rem;
max-width: 52rem;
margin: 0 auto;
grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
}
.plan {
background: #fff;
border: 1px solid #e2e8f0;
border-radius: 12px;
padding: 1.25rem;
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.plan.featured {
border-color: #4361ee;
box-shadow: 0 12px 28px rgba(67, 97, 238, 0.2);
transform: scale(1.02);
}
.price { font-size: 1.75rem; font-weight: 700; }
ul { margin: 0; padding-left: 1.1rem; flex: 1; font-size: 0.95rem; color: #444; }
button {
padding: 0.55rem;
border: none;
border-radius: 8px;
background: #4361ee;
color: #fff;
cursor: pointer;
}
</style>
</head>
<body>
<h1>Тарифы</h1>
<div class="plans">
<div class="plan">
<h2>Базовый</h2>
<div class="price">₽0</div>
<ul><li>1 проект</li><li>Поддержка по email</li></ul>
<button type="button">Выбрать</button>
</div>
<div class="plan featured">
<h2>Про</h2>
<div class="price">₽990</div>
<ul><li>10 проектов</li><li>Приоритетная поддержка</li></ul>
<button type="button">Выбрать</button>
</div>
<div class="plan">
<h2>Команда</h2>
<div class="price">₽2990</div>
<ul><li>Без лимита</li><li>SSO</li></ul>
<button type="button">Связаться</button>
</div>
</div>
</body>
</html>

Разбор.

CSSЗачем
flex-direction: column на .planЭлементы карточки в столбик
flex: 1 на ulСписок растягивается, кнопки на одной линии внизу у всех тарифов
.featuredВыделение среднего тарифа — типичный приём на лендингах
transform: scale(1.02)Чуть крупнее соседей; на очень узком экране можно убрать, если мешает

5. Подвал с колонками ссылок

Задача. Внизу сайта группы ссылок (продукт, компания, правовое) и строка копирайта.

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Подвал</title>
<style>
*, *::before, *::after { box-sizing: border-box; }
body {
margin: 0;
min-height: 100dvh;
display: flex;
flex-direction: column;
font-family: system-ui, sans-serif;
}
main { flex: 1; padding: 2rem 1.25rem; }
footer {
background: #111827;
color: #9ca3af;
padding: 2rem 1.25rem 1rem;
}
.cols {
max-width: 56rem;
margin: 0 auto;
display: grid;
gap: 1.5rem;
grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
}
footer h3 { color: #f3f4f6; margin: 0 0 0.5rem; font-size: 1rem; }
footer a { color: #93c5fd; text-decoration: none; display: block; margin-bottom: 0.35rem; }
.copy {
max-width: 56rem;
margin: 1.5rem auto 0;
padding-top: 1rem;
border-top: 1px solid #374151;
font-size: 0.85rem;
}
</style>
</head>
<body>
<main><h1>Страница</h1><p>Контент выше подвала.</p></main>
<footer>
<div class="cols">
<div>
<h3>Продукт</h3>
<a href="#">Возможности</a>
<a href="#">Тарифы</a>
</div>
<div>
<h3>Компания</h3>
<a href="#">О нас</a>
<a href="#">Вакансии</a>
</div>
<div>
<h3>Правовое</h3>
<a href="#">Политика</a>
<a href="#">Оферта</a>
</div>
</div>
<p class="copy">© 2026 Пример</p>
</footer>
</body>
</html>

Разбор. main &#123; flex: 1 &#125; прижимает footer к низу окна. Внутри подвала снова auto-fit — колонки сами перестраиваются. Ссылки display: block — удобная зона нажатия на телефоне.

Типичная ошибка. Забыли flex: 1 у main — на короткой странице подвал оказывается посередине, а не внизу.


6. Адаптив и тёмная тема

6.1. Mobile-first — меню сверху, на ПК слева

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Mobile-first</title>
<style>
*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; font-family: system-ui, sans-serif; }
.menu { display: flex; flex-direction: column; gap: 0.5rem; padding: 1rem; background: #f1f5f9; }
.content { padding: 1rem; }
@media (min-width: 48rem) {
body { display: grid; grid-template-columns: 14rem 1fr; }
.menu { min-height: 100dvh; }
}
</style>
</head>
<body>
<nav class="menu">
<a href="#">Главная</a>
<a href="#">Проекты</a>
<a href="#">Настройки</a>
</nav>
<div class="content">
<h1>Mobile-first</h1>
<p>Базовые стили для телефона. От 768px — меню слева на всю высоту.</p>
</div>
</body>
</html>

Разбор. Сначала стили для узкого экрана, в @media (min-width: 48rem) — расширение. Так проще сопровождать, чем верстать только «десктоп» и ужимать через max-width. 48rem ≈ 768px при стандартном размере шрифта.


6.2. Светлая и тёмная тема через переменные

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Тема</title>
<style>
*, *::before, *::after { box-sizing: border-box; }
:root {
--bg: #ffffff;
--text: #1e1e2e;
--card: #f4f4f5;
--accent: #4361ee;
}
@media (prefers-color-scheme: dark) {
:root {
--bg: #11111b;
--text: #cdd6f4;
--card: #1e1e2e;
--accent: #89b4fa;
}
}
body {
margin: 0;
min-height: 100dvh;
font-family: system-ui, sans-serif;
background: var(--bg);
color: var(--text);
padding: 1.5rem;
}
.card {
max-width: 28rem;
padding: 1.25rem;
background: var(--card);
border-radius: 12px;
}
a { color: var(--accent); }
</style>
</head>
<body>
<div class="card">
<h1>Системная тема</h1>
<p>Цвета в <code>:root</code>, тёмный набор — в <code>prefers-color-scheme: dark</code>.</p>
<p><a href="#">Ссылка</a></p>
</div>
</body>
</html>

Разбор. Переменные --имя объявляют в :root (доступны везде). var(--bg) подставляет значение. Браузер сам выбирает тёмный блок, если в ОС включена тёмная тема.

Попробуйте сами. DevTools (F12) → «Rendering» → prefers-color-scheme — переключите light/dark.


7. Чистая база для своего проекта

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>База</title>
<style>
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
margin: 0;
font-family: system-ui, sans-serif;
line-height: 1.5;
color: #1e1e2e;
background: #fff;
}
img, picture, video, canvas, svg { display: block; max-width: 100%; }
input, button, textarea, select { font: inherit; }
.container {
width: min(100% - 2rem, 64rem);
margin-inline: auto;
}
</style>
</head>
<body>
<div class="container">
<h1>Чистый лист</h1>
<p>Добавляйте секции внутрь <code>.container</code>.</p>
</div>
</body>
</html>
СтрокаЗачем
-webkit-text-size-adjust: 100%iOS не раздувает мелкий шрифт в landscape
font: inherit на полях вводаКнопки и input совпадают с шрифтом страницы
min(100% - 2rem, 64rem)Контейнер с отступами от краёв, но не шире 1024px
margin-inline: autoЦентрирование (логичное свойство «слева–справа»)

Частые вопросы

Как центрировать div по центру страницы?
Самый короткий способ — body &#123; display: grid; min-height: 100dvh; place-items: center; &#125; или flex с align-items и justify-content (см. карточку и форму выше).

Почему два блока по 50% не влезают в ряд?
Часто из‑за box-sizing: content-box и padding. Добавьте глобально box-sizing: border-box или используйте gap во Grid/Flex вместо width: 50% + margin.

Flexbox или Grid для всего сайта?
Grid для «каркаса» (шапка, колонки, подвал), Flex для строк меню, кнопок в форме, выравнивания внутри карточки.

Нужен ли Bootstrap?
Для обучения и малых работ хватит чистого CSS из этой статьи. Фреймворки ускоряют большие проекты, но скрывают основы.

Как посмотреть макет на телефоне?
Откройте DevTools (F12) → режим устройства, или залейте файл на хостинг / откройте через «Поделиться» в локальной сети.


Что изучить дальше

ТемаКуда перейти
Теги, формы, ссылкиHTML
Flex и Grid подробноFlexbox и CSS Grid
Медиазапросы, clamp, viewportАдаптивность
Мини-шаблоны git, READMEШаблоны
Рисование в Python (другой формат «примеров»)Turtle
Рисование в браузере (JavaScript)p5.js
Окна, формы, кнопки на PythonTkinter — окна и виджеты
Интерактив в браузереJavaScript — о разделе

Для отчёта и портфолио

В описании работы укажите, какой приём использовали: «адаптивная сетка на CSS Grid с auto-fit», «липкий header на position: sticky». Одно точное название свойства показывает, что вы понимаете код, а не только скопировали шаблон.


См. также

Другие статьи этого же раздела в боковом меню (как на странице "О разделе").