Модуль 08 — Адаптивная вёрстка и публикация

Одна страница для телефона, планшета и компьютера — и как выложить её в интернет

Прогресс курса Модуль 8 из 9

Что вы освоите в этом модуле

01

meta viewport

Больше половины посетителей сайтов приходят с телефонов. Исторически сайты верстали под компьютер, и мобильные браузеры, чтобы показать их целиком, считают страницу без указаний настольной — шириной 980px — и уменьшают. Строка в <head> отменяет это поведение:

<meta name="viewport" content="width=device-width, initial-scale=1">

Две одинаковые страницы на экране телефона шириной 390px: сначала без этой строки (снято в окне 980px и уменьшено так, как это делает мобильный браузер), затем с ней:

Результат в браузере
Телефон без meta viewport: страница разложена на 980 пикселей и уменьшена до ширины экрана, заголовок и текст мелкие
Результат в браузере
Телефон с meta viewport: заголовок и абзац обычного размера, текст переносится по ширине экрана

Без viewport медиазапросы для телефонов не сработают вовсе: браузер считает ширину 980px. Поэтому эта строка — в скелете документа с модуля 01.

02

Медиазапросы и mobile first

Медиазапрос @media (условие) { … } применяет правила внутри только при выполнении условия — чаще всего при ширине окна. Подход mobile first: основные стили пишут для телефона (одна колонка, всё друг под другом), а для широких экранов добавляют правила через min-width:

<!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: Arial, sans-serif; line-height: 1.4; }
        .header { padding: 12px 16px; background: #1967d2; color: white; }
        .header nav { display: flex; flex-wrap: wrap; gap: 4px 16px; margin-top: 6px; }
        .header a { color: white; }
        .wrap { max-width: 1100px; margin: 0 auto; padding: 16px; }
        h1 { font-size: clamp(1.5rem, 4vw + 0.5rem, 2.5rem); margin: 0 0 12px; }
        .cards { display: grid; grid-template-columns: 1fr; gap: 12px; }
        .card { padding: 12px; border: 1px solid #ddd; border-radius: 8px; }
        .card h2 { margin: 0 0 4px; font-size: 1.1rem; }
        .card p { margin: 0; }

        /* Планшет и шире */
        @media (min-width: 600px) {
            .header { display: flex; justify-content: space-between; align-items: center; }
            .header nav { margin-top: 0; }
            .cards { grid-template-columns: repeat(2, 1fr); }
        }

        /* Компьютер */
        @media (min-width: 900px) {
            .cards { grid-template-columns: repeat(3, 1fr); }
        }
    </style>
</head>
<body>
    <header class="header">
        <strong>Кафе «Нева»</strong>
        <nav>
            <a href="#">Меню</a>
            <a href="#">Бронь</a>
            <a href="#">Контакты</a>
        </nav>
    </header>
    <main class="wrap">
        <h1>Завтраки весь день</h1>
        <div class="cards">
            <article class="card"><h2>Сырники</h2><p>Со сметаной и вареньем</p></article>
            <article class="card"><h2>Омлет</h2><p>С сыром и зеленью</p></article>
            <article class="card"><h2>Каша</h2><p>Овсяная с ягодами</p></article>
        </div>
    </main>
</body>
</html>
Результат в браузере
Телефон: синяя шапка, под названием кафе ссылки меню; крупный заголовок; три карточки друг под другом
Результат в браузере
Компьютер: шапка в одну строку — название слева, меню справа; заголовок; три карточки в один ряд

Почему от телефона, а не наоборот: мобильная раскладка проще (одна колонка), и телефону не приходится загружать и отменять правила настольной версии. Точки перехода (600px, 900px) выбирают не по моделям устройств, а там, где раскладка начинает выглядеть плохо: растяните окно и посмотрите, на какой ширине строки становятся слишком длинными или карточки — слишком широкими.

УсловиеКогда срабатывает
(min-width: 600px)Окно шириной 600px и больше
(max-width: 599px)Окно уже 600px — для подхода «от компьютера»
(orientation: landscape)Ширина больше высоты
(prefers-color-scheme: dark)В системе включена тёмная тема
(prefers-reduced-motion: reduce)Пользователь просил меньше анимации
printПечать страницы
03

Гибкие размеры

Адаптивность — это не только медиазапросы. Многое подстраивается само, если не задавать жёстких размеров:

Гибкие приёмы из модулей 05–07 и этого

  • max-width вместо width у колонок и блоков.
  • Колонки в fr и сетка repeat(auto-fit, minmax(…, 1fr)) меняют число колонок без медиазапросов.
  • flex-wrap: wrap переносит пункты меню, когда они не помещаются (так в шапке примера выше).
  • clamp(минимум, желаемое, максимум) — значение, которое растёт с шириной окна в заданных границах. В примере заголовок: clamp(1.5rem, 4vw + 0.5rem, 2.5rem) — на телефоне 24px, на широком экране не больше 40px.
  • Отступы в rem, шрифты в rem — уважают настройку размера шрифта пользователя.
Главный признак сломанной мобильной вёрстки — горизонтальная прокрутка: страница «ездит» вбок. Обычные виновники: блок с width в пикселях шире экрана, картинка без max-width, длинный адрес или слово без переноса, таблица. Найти виновника: F12 → режим устройства, затем по очереди выделять крупные блоки и смотреть, какой выходит за правый край.
04

Адаптивные изображения

Картинка шире экрана — самая частая причина горизонтальной прокрутки. Одна строка CSS ограничивает её шириной родителя, а height: auto сохраняет пропорции:

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Картинки</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 16px; }
        img { max-width: 100%; height: auto; }
    </style>
</head>
<body>
    <img src="wide.svg" alt="Панорама набережной, схематично" width="900" height="300">
    <p>Картинка шириной 900px уменьшается до ширины экрана и сохраняет пропорции.</p>
</body>
</html>
Результат в браузере
Телефон: широкая картинка-панорама уменьшена до ширины экрана, пропорции сохранены, под ней подпись

Но уменьшенная картинка всё равно весит, как большая: телефон загружает файл для широкого экрана. Атрибуты srcset и sizes дают браузеру несколько вариантов, и он выбирает подходящий по ширине экрана и плотности пикселей; <picture> позволяет предложить современный формат с запасным вариантом:

<img src="hall-800.jpg"
     srcset="hall-400.jpg 400w, hall-800.jpg 800w, hall-1600.jpg 1600w"
     sizes="(min-width: 900px) 800px, 100vw"
     alt="Зал кафе с окнами на Неву" width="800" height="533" loading="lazy">

<picture>
    <source srcset="hall.avif" type="image/avif">
    <source srcset="hall.webp" type="image/webp">
    <img src="hall.jpg" alt="Зал кафе с окнами на Неву" width="800" height="533">
</picture>

400w — реальная ширина файла в пикселях; sizes — какую ширину картинка займёт на странице. loading="lazy" откладывает загрузку картинок ниже первого экрана до прокрутки к ним.

05

Проверка на устройствах

Режим устройства в инструментах разработчика (Ctrl+Shift+M) показывает страницу в размерах популярных телефонов и позволяет тянуть ширину мышью. Это быстро, но не заменяет настоящий телефон: там другие шрифты, «чёлка» экрана, пальцы вместо курсора.

Что проверить перед сдачей

  • Ширина 320, 390, 768, 1024, 1440px — нет горизонтальной прокрутки, ничего не наезжает.
  • Кнопки и ссылки на телефоне — не меньше 44 × 44px, не вплотную друг к другу.
  • Пройти страницу клавишей Tab: фокус виден на каждом элементе. Если убрали стандартную обводку outline, дайте свою через :focus-visible.
  • Контраст текста — не ниже 4,5 : 1. В инструментах разработчика при выборе цвета в Styles показан коэффициент контраста.
  • Увеличить шрифт в браузере до 200% — страница остаётся читаемой.
  • Lighthouse (вкладка в F12 Chrome и Яндекс Браузера): разделы «Доступность» и «Рекомендации».

Открыть страницу на телефоне можно до публикации: запустите в каталоге сайта простой веб-сервер python3 -m http.server 8000 (курс «Основы Python», в Windows — py -m http.server 8000) и откройте на телефоне, подключённом к той же сети Wi-Fi, адрес http://IP-адрес-компьютера:8000. Брандмауэр Windows при первом запуске спросит разрешение на доступ из сети.

06

Подготовка к публикации

Чек-лист файлов

  • Главная — index.html в корне; имена файлов и каталогов — латиница в нижнем регистре, без пробелов.
  • Все пути относительные и с правильным регистром букв (сервер Linux различает Logo.png и logo.png).
  • Картинки уменьшены до нужного размера и сжаты; фотографии — WebP или JPEG.
  • У каждой страницы свой <title> и <meta name="description"> — их показывает поисковик.
  • Значок вкладки: <link rel="icon" href="favicon.svg">.
  • Валидатор HTML — без ошибок; в консоли браузера (F12 → Console) нет ошибок загрузки файлов.
07

Публикация

Сайт из HTML, CSS и картинок — статический: серверу нужно только отдавать файлы. Варианты, от простого к сложному:

ВариантКакЧто нужно знать
Хостинг статических сайтов или страниц из git-репозиторияЗагрузить файлы или отправить репозиторий; сервис выдаёт адресБесплатно, HTTPS сразу; доступность сервиса из России проверяйте на момент публикации
Виртуальный хостинг российского провайдераЗагрузить файлы в каталог сайта по SFTP или через панельСвой домен, HTTPS через панель; платно, недорого
Свой сервер (VPS) с nginxСкопировать файлы в каталог, настроить nginxПолный контроль; администрирование — на вас (курс «Основы Linux»)

Минимальная настройка nginx для статического сайта в Debian — файл /etc/nginx/sites-available/cafe:

server {
    listen 80;
    server_name cafe.example.ru;
    root /var/www/cafe;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

Затем ссылка в sites-enabled, проверка sudo nginx -t и sudo systemctl reload nginx. Сертификат HTTPS бесплатно выдаёт Let's Encrypt, программа certbot получает и продлевает его сама. Без HTTPS браузеры помечают сайт как небезопасный, а формы с данными пользователей без него недопустимы (модуль 03).

Ключевые выводы модуля

Запомните главное

  • Без meta viewport телефон показывает уменьшенную настольную страницу, и медиазапросы не работают
  • Mobile first: базовые стили — для телефона, расширения — в @media (min-width: …)
  • Точки перехода — там, где ломается раскладка, а не по моделям телефонов
  • img { max-width: 100%; height: auto; }; srcset — чтобы телефон не грузил большие файлы
  • Горизонтальная прокрутка — главный признак ошибки; проверка на 320–1440px, клавиатурой и Lighthouse
  • Статический сайт — это файлы: хостинг, SFTP или nginx; всегда HTTPS
Практические задания — на учебном портале. Задания, критерии оценивания, сдача работ и оценки преподавателя — в курсе на portal.nevabit.ru. Учётную запись выдаёт преподаватель.
Модуль 07: Grid Все модули Итоговый проект