Глиф Учебники

Урок 10. Адаптивная вёрстка — сайт для телефона и компьютера

Курс «HTML и CSS» · урок 10 из 10 · 5 минут чтения

На многих сайтах больше половины посетителей приходят с телефонов. Адаптивная вёрстка — это когда одна и та же страница сама перестраивается под ширину экрана: на компьютере — колонки рядом, на телефоне — друг под другом, крупный текст и удобные для пальца кнопки. Отдельная «мобильная версия» сайта для этого не нужна.

Шаг 1. meta viewport

Без этой строки в <head> телефон показывает страницу так, будто у него экран шириной около 980 пикселей, и уменьшает её — всё становится мелким:

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

width=device-width — ширина страницы равна ширине экрана, initial-scale=1 — без начального уменьшения. Эта строка нужна на каждой странице. Остальное в адаптивности делает CSS.

Без meta viewport как экран ≈980px — всё мелко С meta viewport width=device-width
Без meta viewport телефон рисует страницу как на экране шириной около 980px и уменьшает её, а с width=device-width страница равна ширине экрана и текст крупный.

Не добавляйте в неё user-scalable=no или maximum-scale=1: они запрещают увеличивать страницу пальцами, а людям со слабым зрением это нужно.

Шаг 2. Резиновые размеры

Главный враг адаптивности — жёсткая ширина в пикселях. Блок width: 1000px на телефоне шириной 390 пикселей вылезет за экран, и страница начнёт прокручиваться вбок.

Жёсткая ширина width: 1000px не помещается в экран страница прокручивается вбок Резиновая ширина max-width: 1000px сужается вместе с экраном
Блок с width: 1000px не помещается в экран телефона и страница прокручивается вбок, а блок с max-width: 1000px сужается до ширины экрана.
CSS
img {
  max-width: 100%;
  height: auto;
}

max-width: 100% не даёт картинке стать шире родителя, height: auto сохраняет пропорции. Эти две строки есть почти в любом CSS. Подробнее — в справке Как сделать адаптивную картинку.

Шаг 3. Медиазапросы

Медиазапрос — блок CSS, который действует только при условии, например при ширине окна не меньше заданной:

CSS
.cards {
  display: grid;
  grid-template-columns: 1fr;
  gap: 16px;
}

@media (min-width: 600px) {
  .cards {
    grid-template-columns: 1fr 1fr;
  }
}

@media (min-width: 960px) {
  .cards {
    grid-template-columns: 1fr 1fr 1fr;
  }
}

На телефоне карточки идут в один столбец, от 600 пикселей — в два, от 960 — в три. Правила внутри @media просто дописываются к обычным, когда условие выполнено. Поэтому медиазапросы ставят после основных правил: при равной точности побеждает то, что ниже.

ширина окна меньше 600px 1fr min-width: 600px 1fr 1fr min-width: 960px 1fr 1fr 1fr
Одни и те же карточки при ширине окна меньше 600px идут в один столбец, от 600px медиазапрос включает два столбца, а от 960px — три.

Сначала телефон

Удобнее писать стили сначала для узкого экрана, а затем медиазапросами с min-width добавлять колонки для широкого — так и сделано в примере выше. Такой подход называют mobile first. Простой одноколоночный вид работает везде, а сложная раскладка включается, только когда для неё есть место.

Точки перехода (их называют breakpoints) не привязывают к конкретным моделям телефонов. Расширяйте окно и ставьте медиазапрос там, где раскладка начинает выглядеть плохо: строки стали слишком длинными, появилось место для второй колонки.

Пример: страница с боковым меню

Из урока CSS Grid — раскладка «шапка, меню, текст, подвал». На телефоне меню уходит под шапку:

CSS
.layout {
  display: grid;
  grid-template-columns: 1fr;
  grid-template-areas:
    "head"
    "side"
    "main"
    "foot";
  gap: 16px;
}

@media (min-width: 800px) {
  .layout {
    grid-template-columns: 220px 1fr;
    grid-template-areas:
      "head head"
      "side main"
      "foot foot";
  }
}

.head { grid-area: head; }
.side { grid-area: side; }
.main { grid-area: main; }
.foot { grid-area: foot; }

HTML при этом не меняется — меняется только раскладка.

Меню на узком экране

Меню из пяти-шести ссылок в ряд не помещается на телефоне. Самое простое решение — разрешить перенос:

CSS
.menu {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 16px;
}

Две цифры в gap — промежуток между строками и между столбцами. Как сделать меню целиком — в справке Как сделать меню на сайте.

Текст и кнопки

Как проверить

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

  1. Откройте инструменты разработчика (F12).
  2. Нажмите Ctrl+Shift+M — в Chrome, Edge и Firefox включится режим, где можно выбрать ширину экрана или модель телефона. На macOS — Cmd+Shift+M в Chrome и Cmd+Option+M в Firefox.
  3. Пролистайте страницу на разных ширинах: нет ли прокрутки вбок, всё ли читается, не налезают ли блоки.

В конце обязательно откройте сайт на настоящем телефоне: режим браузера не показывает, как страница ощущается под пальцем.

Частые ошибки

Коротко

Проверьте себя

1. Что будет на телефоне, если на странице нет <meta name="viewport" …>?
2. Когда сработает @media (min-width: 768px)?
3. Какие две строки CSS не дают картинке вылезти за край на узком экране?
4. Медиазапрос написан правильно, но стили из него не применяются. Возможная причина?