HTML + CSS — готовые макеты
Готовые одностраничные шаблоны: скопировали код в файл index.html, открыли в браузере — макет уже работает. Если нужен разбор тегов и семантики целой страницы (без упора на CSS) — сначала HTML-страницы целиком. Подойдёт для урока информатики, лабораторной по вебу, домашнего задания, первого портфолио или когда в поиске нужны запросы вроде «html css центрировать блок», «flexbox шапка подвал», «адаптивная сетка карточек». Те же задачи через utility-классы — в соседней главе Tailwind — готовые блоки.
Под каждым примером — разбор строк: что делает свойство и зачем оно здесь. Сначала простые макеты, затем каркас сайта, лендинг, дашборд и адаптив.
Основы вёрстки
Теория — в HTML и CSS. Подробно про Flexbox и Grid — отдельная глава. Шпаргалка «что использовать / чего избегать» — Практические рекомендации по CSS.
Вставьте любой пример из статьи в редактор выше — предпросмотр обновится через пару секунд. Так быстрее, чем каждый раз сохранять файл на диск.
Мини-симулятор показывает, как Flex и Grid по-разному раскладывают четыре блока. Перед сложными макетами полезно покрутить justify-content и align-items.
Базовые термины
| Термин | Простыми словами |
|---|---|
| HTML | Разметка: заголовки, абзацы, кнопки, формы — «скелет» страницы |
| CSS | Стили: цвета, отступы, сетка, расположение блоков |
| Макет (layout) | Как блоки стоят относительно друг друга и экрана |
| Flexbox | Раскладка в одну линию (ряд или столбец) с выравниванием |
| CSS Grid | Раскладка в таблицу из строк и колонок сразу |
| Адаптив | Страница подстраивается под ширину телефона и монитора |
Медиазапрос @media | Другие стили, когда экран уже или шире порога |
rem | Единица от размера шрифта корня; удобна для отступов |
viewport | Видимая область браузера; без meta-тега на телефоне страница «мелкая» |
Как работать с примерами
- Скопируйте весь блок кода (от
<!DOCTYPE html>до</html>). - Вставьте в файл
макет.html(илиindex.html). - Откройте двойным щелчком или перетащите в Chrome / Edge / Firefox.
- Меняйте текст, цвета, числа в
padding— смотрите, что изменилось. - Если сломали — верните исходник из статьи и меняйте по одному свойству.
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-box | padding и border входят в заявленную ширину блока — сетка не «плывёт» |
body { margin: 0 } | Убирает белую полоску по умолчанию у краёв окна |
img { max-width: 100% } | Картинка не вылезает за экран на узком телефоне |
Типичные ошибки.
- Забыли
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 { width: 100% } | Кнопка на всю ширину карточки — привычный паттерн для форм |
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 { flex: 1 } | Средняя часть забирает всё свободное место, выталкивая footer вниз |
max-width + margin: 0 auto на main | Текст не растягивается на весь 4K-монитор — удобно читать |
nav { display: flex; gap: 1rem } | Ссылки в ряд с равномерным зазором без отступов на каждой ссылке |
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 { display: flex } | Пункты меню в ряд, а не столбиком слева |
Типичные ошибки.
- Опечатка в имени области (
"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 { flex: 1 } прижимает 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 { display: grid; min-height: 100dvh; place-items: center; } или 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 |
| Окна, формы, кнопки на Python | Tkinter — окна и виджеты |
| Интерактив в браузере | JavaScript — о разделе |
В описании работы укажите, какой приём использовали: «адаптивная сетка на CSS Grid с auto-fit», «липкий header на position: sticky». Одно точное название свойства показывает, что вы понимаете код, а не только скопировали шаблон.
См. также
Другие статьи этого же раздела в боковом меню (как на странице "О разделе"). Практическая карта типовых IT-задач: термины, пошаговое внедрение, проверка качества и типичные ошибки. Простой консольный чат на C# — учебное приложение с сокетами: TCP между клиентом и сервером, многопоточность и обмен сообщениями в консоли. Перед началом работы обязательно изучите главу Turtle . Галерея 3D-фигур на Panda3D — карточки, куб, пирамида, сфера, сетки и составные сцены; код для локального запуска. Готовые docker-compose.yml с разбором каждой строки — nginx, PostgreSQL, Redis, WordPress, MongoDB. Примеры для школьников и студентов: postgres example, поднять базу локально, app + db. Примеры nginx.conf для статики, reverse proxy, React/Vue SPA, PHP, SSL и балансировки — построчный разбор директив, проверка curl и типичные ошибки для лабораторных и VPS. dockerfile example — 10 готовых Dockerfile с построчным разбором: node, python, golang, react nginx, spring boot, php, dotnet. Для студентов, лабораторных и docker build с нуля. PromQL example — готовые запросы Prometheus и Grafana с построчным разбором: up, rate, node_exporter cpu, memory, disk, http_requests_total, histogram_quantile p99, алерты. Для студентов, лабораторных и devops docker compose. Готовые манифесты Kubernetes с разбором каждой строки — Pod, Deployment, Service, ConfigMap, Secret, Ingress. Примеры для Minikube, kind и kubectl apply. Примеры графиков Matplotlib на Python для школьников и студентов — sin, cos, парабола, столбцы, scatter, гистограмма, подграфики; код с подробным разбором. Примеры pandas на Python для школьников и студентов — DataFrame, фильтрация, groupby, очистка, merge, сводные таблицы и экспорт; код с подробным разбором каждой строки. p5.js и Processing — готовый код фигур с подробным разбором каждой строки: квадрат, треугольник, цветок, снежинка, фракталы, анимация; для школьников и студентов.Готовые решения
Простой консольный чат на CSharp
Примеры фигур Turtle на Python
Примеры фигур Panda3D на Python
Docker Compose — готовые стеки
Nginx — конфиги под задачу
Dockerfile — 10 типовых образов
Prometheus + Grafana — запросы
Kubernetes YAML — минимальные манифесты
Matplotlib — графики
Pandas — типовые операции
Примеры фигур на Processing/p5.js