Mobile-first: что это за подход и как верстать от мобильного экрана

Mobile-first: что это за подход и как верстать от мобильного экрана Полезное

Mobile-first — это подход к проектированию и верстке, при котором сначала делают версию интерфейса для самого узкого экрана, а затем постепенно добавляют раскладку и возможности для экранов шире. В CSS это выражается просто: базовые стили без медиазапросов написаны для телефона, а медиазапросы с min-width только добавляют то, что нужно планшету и десктопу.

Ниже разберем, чем mobile-first отличается от адаптивного и отзывчивого дизайна, соберем рабочий пример страницы, покажем две типичные ошибки на реальном прогоне и чек-лист проверки.

Три термина, которые путают

Mobile-first часто называют «адаптивной версткой», но это разные уровни. Один отвечает на вопрос «как устроен макет», другой — «в каком порядке его проектируют».

Термин Что описывает Как выглядит в коде
Отзывчивый дизайн (responsive) Один гибкий макет, который тянется под любую ширину Резиновая сетка, %/fr, гибкие изображения, медиазапросы
Адаптивный дизайн (adaptive) Несколько заранее заданных макетов под типовые ширины или устройства Фиксированные раскладки на брейкпоинтах, иногда выбор шаблона на сервере
Mobile-first Порядок проектирования: от узкого экрана и главного контента к широкому База без медиазапросов + @media (min-width: ...)
Desktop-first Обратный порядок: от десктопа к телефону База для широкого экрана + @media (max-width: ...)

Отсюда главное различие: отзывчивый сайт может быть сделан и как mobile-first, и как desktop-first. Mobile-first — это не отдельный вид макета, а направление, в котором макет наращивают.

Еще одна частая путаница — mobile-first indexing в Google. Это не метод верстки, а то, что поисковый робот для индексации использует мобильную версию страницы. Связь прямая: если на мобильной версии контент урезан, в индекс попадет урезанный вариант. Но сам по себе подход mobile-first не дает бонуса к позициям.

Принципы подхода

Упрощенно mobile-first держится на трех идеях. Упрощение в том, что в реальном проекте их применяют вместе с дизайн-системой и требованиями бизнеса, а не как жесткий регламент.

  1. Приоритет контента. На экране шириной 360-400 CSS-пикселей помещается мало, поэтому сначала решают, что пользователю нужно в первую очередь: цена, кнопка записи, контакты. Все второстепенное уходит ниже или в раскрывающиеся блоки, но не удаляется.
  2. Прогрессивное улучшение. База работает на любом устройстве, а более широкие экраны и точные указатели (мышь) получают дополнительные возможности: вторую колонку, боковое меню, эффекты при наведении.
  3. Ограничения как требования. Сенсорное управление, медленная сеть и маленький экран учитываются сразу, а не «потом допилим мобильную версию».

Рабочий пример: страница каталога

Сначала полный минимальный пример целиком, потом разбор. Это страница с меню и тремя карточками. На телефоне карточки идут в одну колонку, на планшете — в две, на десктопе появляется боковое меню и три колонки.

<!DOCTYPE html>
<html lang="ru">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Mobile-first: каталог</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <div class="layout">
    <nav class="nav">
      <a href="#">Курсы</a> <a href="#">Вебинары</a> <a href="#">Блог</a>
    </nav>
    <main class="cards">
      <article class="card"><h2>HTML/CSS</h2><a class="btn" href="#">Подробнее</a></article>
      <article class="card"><h2>JavaScript</h2><a class="btn" href="#">Подробнее</a></article>
      <article class="card"><h2>React</h2><a class="btn" href="#">Подробнее</a></article>
    </main>
  </div>
</body>
</html>
/* База: узкий экран, без медиазапросов */
*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; font: 1rem/1.5 system-ui, sans-serif; }
.layout { display: grid; gap: 1rem; padding: 1rem; }
.nav { display: flex; gap: 1rem; overflow-x: auto; }
.cards { display: grid; grid-template-columns: 1fr; gap: 1rem; }
.btn { display: inline-flex; align-items: center; min-height: 44px; padding: 0 1rem; }

/* Шире 40em (640px при шрифте 16px): две колонки карточек */
@media (min-width: 40em) {
  .cards { grid-template-columns: repeat(2, 1fr); }
}

/* Шире 64em (1024px): боковое меню и три колонки */
@media (min-width: 64em) {
  .layout { grid-template-columns: 14rem 1fr; }
  .nav { flex-direction: column; }
  .cards { grid-template-columns: repeat(3, 1fr); }
}

/* Наведение - только там, где есть точный указатель */
@media (hover: hover) and (pointer: fine) {
  .btn:hover { text-decoration: underline; }
}

Сохрани файлы как index.html и style.css рядом и открой страницу в браузере, меняя ширину окна. Я проверил пример в Chromium 148 через Playwright с эмуляцией телефона и десктопа и прочитал вычисленные стили:

ширина 375, телефон  -> карточек в ряд: 1, меню: row,    hover: False
ширина 768, планшет  -> карточек в ряд: 2, меню: row,    hover: False
ширина 1280, десктоп -> карточек в ряд: 3, меню: column, hover: True

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

  • Мета-тег viewport говорит мобильному браузеру считать ширину страницы равной ширине экрана. Без него медиазапросы работают против тебя (ниже покажу, как именно).
  • Базовые стили не содержат ни одного медиазапроса: одна колонка, меню в строку с горизонтальной прокруткой, кнопка высотой не меньше 44px, чтобы в нее было удобно попасть пальцем.
  • min-width: 40em и min-width: 64em только добавляют правила. Каждый следующий брейкпоинт шире предыдущего и переопределяет меньше, чем пришлось бы в обратном порядке.
  • em в медиазапросах считается от размера шрифта браузера по умолчанию, а не от font-size, заданного в CSS. Если пользователь увеличил шрифт в настройках, брейкпоинты сдвигаются вместе с ним, и раскладка не ломается.
  • (hover: hover) and (pointer: fine) включает эффект наведения только на устройствах с мышью. На сенсорном экране «зависшее» состояние hover после касания не появится.

Брейкпоинты 40em и 64em здесь учебные. В реальном проекте их ставят там, где ломается конкретный контент, а не под модели устройств.

Mobile-first и desktop-first: одно и то же, но разной ценой

Тот же результат можно получить в порядке desktop-first. Я прогнал такую версию на тех же ширинах, колонки совпали: 1, 2 и 3.

.layout { display: grid; gap: 1rem; padding: 1rem; grid-template-columns: 14rem 1fr; }
.nav { display: flex; gap: 1rem; flex-direction: column; }
.cards { display: grid; gap: 1rem; grid-template-columns: repeat(3, 1fr); }

@media (max-width: 63.99em) {
  .layout { grid-template-columns: none; }
  .nav { flex-direction: row; overflow-x: auto; }
  .cards { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 39.99em) {
  .cards { grid-template-columns: 1fr; }
}

Разница в том, кто платит за переопределения. Здесь телефон применяет десктопную раскладку и затем отменяет ее двумя медиазапросами. В mobile-first самый слабый клиент получает самый короткий путь, а переопределяет широкий экран. Плюс граница 63.99em — костыль, чтобы брейкпоинты не пересекались.

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

Ошибка 1: забыли мета-тег viewport

Уберем из index.html строку с viewport и откроем ту же страницу в эмуляции телефона шириной 375 пикселей.

<!-- неверно: в head нет meta viewport -->
<meta charset="utf-8">
<title>Mobile-first: каталог</title>

Фактический результат прогона в Chromium 148:

innerWidth: 981, карточек в ряд: 2

Браузер телефона без подсказки рисует страницу на виртуальном холсте шириной около 980 CSS-пикселей и уменьшает ее. Условие min-width: 40em выполняется, и на экране смартфона оказываются две мелкие колонки. Исправление — вернуть строку <meta name="viewport" content="width=device-width, initial-scale=1">. После этого innerWidth снова 375, колонка одна.

Ошибка 2: медиазапросы min-width не по порядку

В mobile-first блоки min-width должны идти по возрастанию. Если поставить 64em раньше 40em, более поздний блок перекроет более ранний, ведь на широком экране выполняются оба условия.

/* неверно: широкий брейкпоинт стоит раньше узкого */
@media (min-width: 64em) {
  .cards { grid-template-columns: repeat(3, 1fr); }
}
@media (min-width: 40em) {
  .cards { grid-template-columns: repeat(2, 1fr); }
}

Результат на ширине 1280: карточек в ряд 2 вместо 3, при этом боковое меню уже в колонку — раскладка получилась «наполовину десктопной». Исправление — вернуть порядок 40em, затем 64em, как в рабочем примере.

Что еще входит в mobile-first, кроме CSS

  • Изображения. Атрибуты srcset и sizes у img и элемент picture позволяют отдать телефону картинку меньшего размера. Для изображений ниже первого экрана — loading="lazy".
  • Размер текста. Основной текст около 16px. На iOS Safari поле ввода со шрифтом меньше 16px при фокусе увеличивает масштаб страницы.
  • Зоны касания. Кнопки и ссылки делают достаточно крупными и с отступами. Ориентиры разных систем различаются: 44 пункта у Apple, 48dp в Material Design, минимум 24 на 24 CSS-пикселя в WCAG 2.2.
  • Навигация. Меню не прячут навсегда: его сворачивают, но главные разделы остаются в одно касание.
  • Компоненты. Если карточка должна менять вид в зависимости от ширины своего контейнера, а не окна, подходят контейнерные запросы @container. Они дополняют медиазапросы, а не заменяют подход.

Как проверить результат

  1. Открой страницу в режиме эмуляции устройств в DevTools и пройди ширины 320, 375, 768, 1024 и 1440 пикселей, растягивая окно плавно, а не только по пресетам.
  2. Найди, где ломается контент: переполнение по горизонтали, обрезанный текст, кнопки вплотную. Там и нужен брейкпоинт.
  3. Увеличь шрифт браузера до 200% — раскладка на em должна перестроиться, а не развалиться.
  4. Проверь на реальном телефоне: эмуляция не повторяет точно поведение сенсора, клавиатуры и медленной сети.
  5. Прогони страницу через Lighthouse в мобильном режиме и посмотри на скорость загрузки и доступность.

Если не получилось: страница на телефоне мелкая и «как на компьютере» — проверь viewport. Появилась горизонтальная прокрутка — ищи элемент с фиксированной шириной в пикселях или длинное слово без переноса. Десктопная раскладка частично не включается — проверь порядок блоков min-width.

Выводы

  • Mobile-first — порядок проектирования и верстки от узкого экрана к широкому, а не отдельный тип макета: отзывчивый сайт можно сделать и так, и в порядке desktop-first.
  • В CSS подход сводится к базовым стилям без медиазапросов и блокам min-width, идущим по возрастанию.
  • Без мета-тега viewport мобильный браузер считает ширину около 980 CSS-пикселей, и mobile-first раскладка на телефоне показывает десктопные колонки.
  • Mobile-first indexing в Google — про то, какую версию страницы индексирует робот, а не про способ верстки.
  • Desktop-first остается разумным выбором для инструментов, которыми пользуются в основном с компьютера.

Где применяется / связь с практикой

Mobile-first — базовый навык верстальщика и фронтенд-разработчика: так собирают лендинги, каталоги, личные кабинеты и любые страницы, куда заметная часть пользователей приходит с телефона. На практике он опирается на уверенное знание CSS Grid, Flexbox, медиазапросов и семантической разметки.

Освойте тему на практике

Эти темы системно разбирают на курсе HTML/CSS: от разметки и сеток до адаптивных макетов с проверкой на разных устройствах. Чтобы посмотреть формат занятий, подойдут открытые уроки Otus.

FAQ

Обязательно ли рисовать макет для телефона раньше десктопа?
Нет. Главное — решить приоритет контента и собрать стили от узкого экрана; макеты можно рисовать параллельно, если логика упрощения согласована.

Можно ли перевести готовый desktop-first сайт на mobile-first?
Можно, но обычно по частям: переписывают компонент за компонентом, заменяя max-width на базовые стили и min-width, и сверяют результат на тех же ширинах.

Нужен ли mobile-first, если сайт открывают почти только с компьютера?
Не обязательно. Сверься с аналитикой: для внутренней системы учета desktop-first может быть дешевле, но базовая отзывчивость все равно пригодится.

OTUS Журнал
Скидка 5% 14-20 сентября на курсы (popup)