До 2011 года наш стандартный ответ на вопрос «как делать мобильную версию?» был простым: делаем второй сайт. m.yoursite.com. Урезанная версия с упрощённой навигацией, меньшими изображениями, без тяжёлого JavaScript. Два кодовых репозитория, два дизайна, два набора багов.
Затем Итан Маркотт опубликовал статью «Responsive Web Design» в A List Apart (май 2010) и описал третий вариант: один сайт, жидкая сетка, гибкие изображения, и медиа-запросы для перестройки макета на брейкпоинтах. Мы прочитали. Обсуждали месяц. Потом начали верить, что это реально.
Что мы делали раньше
Типичная мобильная вёрстка 2010 года:
<!-- В <head> -->
<link rel="stylesheet" href="/css/desktop.css" media="screen">
<link rel="stylesheet" href="/css/mobile.css" media="handheld">
Подход media="handheld" был провалом. Большинство мобильных браузеров (включая ранний Mobile Safari) идентифицировали себя как screen, а не handheld. Мобильный CSS игнорировался именно теми устройствами, для которых предназначался.
PHP-вариант с определением по User-Agent:
$ua = $_SERVER['HTTP_USER_AGENT'];
if (preg_match('/(iPhone|iPod|Android|BlackBerry|Nokia)/i', $ua)) {
header('Location: http://m.' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
exit;
}
Работало, пока не переставало: планшеты нельзя было отличить от телефонов, User-Agent-строки лгали, регулярное выражение разрасталось на сотни устройств, а поддомен m. не имел SEO-веса основного домена.
Медиа-запросы: прорыв
CSS3 Media Queries позволяют применять CSS-правила в зависимости от ширины viewport:
/* Базовые стили - подход mobile first */
.container {
width: 100%;
padding: 0 16px;
}
.sidebar {
display: none; /* Скрываем на маленьких экранах */
}
/* Планшет - от 768px */
@media screen and (min-width: 768px) {
.container {
width: 750px;
margin: 0 auto;
}
.sidebar {
display: block;
float: left;
width: 200px;
}
.main-content {
float: right;
width: 530px;
}
}
/* Десктоп - от 1024px */
@media screen and (min-width: 1024px) {
.container { width: 980px; }
.sidebar { width: 260px; }
.main-content { width: 690px; }
}
Ключевая идея: начинаем с мобильного макета как базового. Запросы min-width прогрессивно добавляют. Это и есть «mobile-first» - сначала пишем CSS для маленьких экранов, потом переопределяем для больших.
Жидкая сетка: сложная часть
Медиа-запросов одних недостаточно. Фиксированные пиксельные макеты ломались между брейкпоинтами. Жидкая сетка означала: ширина каждого элемента - процент от родителя, не фиксированные пиксели.
Формула: target / context = result
Если дизайн предполагает сайдбар 300px в контейнере 960px: 300 / 960 = 0.3125 = 31.25%.
// SCSS функция для расчёта
@function fluid-width($target, $context: 960px) {
@return percentage($target / $context);
}
.sidebar { width: fluid-width(300px); } // 31.25%
.main-content { width: fluid-width(640px); } // 66.666%
Гибкие изображения
/* Две строки кода, решающие проблему переполнения */
img {
max-width: 100%;
height: auto;
}
Просто. Работает. Мы не верили, что это решит проблему. Но решило.
Мета-тег viewport
Ранний Safari на iPhone сжимал полноценные десктопные страницы под размер экрана и давал пользователям зумить. Хорошо для legacy-сайтов, ужасно для адаптивных. Решение:
<meta name="viewport" content="width=device-width, initial-scale=1">
Без этого тега все наши медиа-запросы срабатывали относительно виртуального viewport шириной 980px, а не реального экрана iPhone в 375px. Мы потратили два дня, разбираясь, почему адаптивный макет не работает на реальных устройствах, прежде чем нашли это решение.
Переход на практике
Наш первый полностью адаптивный проект - региональный новостной сайт, конец 2011 года. Три брейкпоинта: 480px (телефоны), 768px (планшеты), 1024px (десктоп).
Тестирование на реальных устройствах показало то, что DevTools скрывали:
- Слишком маленькие области нажатия (ссылкам нужен
min-height: 44px) - Горизонтальный скролл из-за одного
width: 960pxв CSS плагина - 300ms задержка клика в iOS Safari (фикс:
touch-action: manipulation) - Таблицы:
<table>не реагировал наmax-width: 100%
Конец эпохи m.yoursite.com
К 2013 году делать отдельный мобильный сайт стало профессионально неловким. «Делаете адаптивный?» - такой вопрос клиенты задавали до подписания договора. Google в 2012 году заявил, что предпочитает адаптивный дизайн отдельным мобильным URL, потому что это упрощает индексацию и консолидирует PageRank на одном URL.
Эпоха m. закончилась не потому, что адаптивный дизайн был идеален. Он таковым не был - и не является сейчас. Она закончилась, потому что решала проблему обслуживания: один кодовый репозиторий, один URL, одно SEO-присутствие.
Двенадцать лет спустя каждый сайт обязан быть адаптивным. Медиа-запросы настолько вездесущи, что стали невидимы. CSS Grid и Flexbox сделали ручные расчёты жидкой сетки устаревшими. Но в 2011 году написать @media screen and (min-width: 768px) и увидеть, как десктопный макет перестраивается в мобильную колонку, казалось маленьким чудом.