Responsive Design: принципы

Responsive Design — подход к вёрстке, при котором сайт автоматически адаптируется к любому размеру экрана, ориентации устройства и возможностям браузера без создания отдельных версий — через гибкие сетки, относительные единицы, медиа-запросы и адаптивные изображения.

Зачем нужно

Более 50% трафика идёт с мобильных устройств. Пользователи ожидают, что сайт будет удобен на любом экране — от смартфона до 4K-монитора. Фиксированная вёрстка «ломается» или требует горизонтальной прокрутки на мобиле. Responsive Design — стандарт индустрии с 2010 года, без него невозможно качественное пользовательское взаимодействие.

Где используется

  • Любой современный сайт или веб-приложение
  • Лендинги, блоги, интернет-магазины
  • Корпоративные сайты и порталы
  • Email-шаблоны
  • Админ-панели и дашборды
  • PWA (Progressive Web Apps)

Предпосылки

Три столпа адаптивности

1. Гибкие сетки (Flexible / Fluid Grids)

Использовать относительные единицы вместо фиксированных:

.container {
  width: 100%;
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 16px;
}

/* Вместо фиксированных пикселей — проценты и fr */
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 24px;
}

/* Flexbox для строчных элементов */
.card-row {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
}

.card-row > * {
  flex: 1 1 300px; /* Минимум 300px, растягивается равномерно */
}

2. Гибкие изображения (Flexible Images)

/* Изображения не выходят за контейнер */
img, video {
  max-width: 100%;
  height: auto;
  display: block;
}

/* Object-fit для контейнеров фиксированного размера */
.card-image {
  width: 100%;
  height: 200px;
  object-fit: cover;
}

/* Адаптивный aspect-ratio */
.video-wrapper {
  aspect-ratio: 16 / 9;
  width: 100%;
}

.video-wrapper iframe {
  width: 100%;
  height: 100%;
}

3. Media queries

/* Базовые стили — мобильные (Mobile First) */
.layout {
  display: grid;
  gap: 24px;
}

/* Планшет */
@media (min-width: 768px) {
  .layout {
    grid-template-columns: 1fr 1fr;
  }
}

/* Десктоп */
@media (min-width: 1024px) {
  .layout {
    grid-template-columns: 1fr 1fr 1fr;
  }
}

Mobile-first vs Desktop-first

/* Mobile-first (рекомендуется) */
/* Базовые стили для мобиле, затем расширяем */
.nav { display: none; }

@media (min-width: 768px) {
  .nav { display: flex; }
}

/* Desktop-first (устаревший подход) */
.nav { display: flex; }

@media (max-width: 767px) {
  .nav { display: none; }
}

Метатег viewport

Без этого мобильный браузер масштабирует страницу как на десктопе:

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

Fluid Typography — адаптивная типографика

/* Фиксированный шрифт — плохо */
h1 { font-size: 48px; } /* Огромный на мобильном */

/* clamp — лучший подход */
h1 {
  font-size: clamp(1.75rem, 1rem + 2.5vw, 3rem);
  /* min: 28px, max: 48px, между — плавно */
}

h2 {
  font-size: clamp(1.25rem, 0.9rem + 1.5vw, 2rem);
}

body {
  font-size: clamp(1rem, 0.9rem + 0.3vw, 1.125rem);
  line-height: 1.6;
}

Система fluid spacing

:root {
  --space-xs: clamp(0.25rem, 0.2rem + 0.25vw, 0.5rem);
  --space-sm: clamp(0.5rem, 0.4rem + 0.5vw, 0.75rem);
  --space-md: clamp(1rem, 0.8rem + 1vw, 1.5rem);
  --space-lg: clamp(1.5rem, 1rem + 2vw, 3rem);
  --space-xl: clamp(2rem, 1.5rem + 3vw, 5rem);
}

section {
  padding-block: var(--space-xl);
  padding-inline: var(--space-md);
}

.card {
  padding: var(--space-md);
  gap: var(--space-sm);
}

Относительные единицы

/* rem — от корневого font-size (обычно 16px) */
.container {
  max-width: 75rem;      /* 1200px */
  padding: 1.5rem;       /* 24px */
}

/* em — от font-size родителя (для отступов в компонентах) */
.button {
  padding: 0.5em 1.5em;  /* Масштабируется с размером шрифта */
  border-radius: 0.25em;
}

/* % — от размера родителя */
.sidebar {
  width: 25%;
}

/* vw/vh — от viewport */
.hero {
  min-height: 100dvh;
  padding-inline: 5vw;
}

Content-First подход

Вместо «как разместить дизайн на мобильном» — «какой контент важен и как его показать».

/* Контент определяет layout, а не наоборот */
.article-grid {
  display: grid;
  /* Колонки появляются, когда есть место для контента */
  grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
  gap: 24px;
}

/* Контейнер адаптируется к контенту */
.content {
  width: min(65ch, 100% - 2rem); /* Максимум 65 символов или 100% */
  margin-inline: auto;
}

Адаптивная навигация

.nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1rem;
}

.nav-links {
  display: flex;
  gap: 1.5rem;
  list-style: none;
}

.burger-btn {
  display: none;
}

/* Мобильная навигация */
@media (max-width: 767px) {
  .burger-btn {
    display: block;
  }

  .nav-links {
    display: none;
    position: fixed;
    inset: 0;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    background: white;
    z-index: 100;
  }

  .nav-links.open() {
    display: flex;
  }
}

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

  1. Забыт <meta viewport> — без него адаптивность не работает на мобильных:
    <meta name="viewport" content="width=device-width, initial-scale=1">
    
  2. Фиксированные ширины вместо max-width:
    /* ОШИБКА */
    .container { width: 1200px; }
    /* ПРАВИЛЬНО */
    .container { max-width: 1200px; width: 100%; }
    
  3. overflow-x: hidden на body — маскирует горизонтальный скролл вместо исправления причины
  4. Элементы с фиксированной шириной — используйте min и max-width
  5. Desktop-first с переопределениями — приводит к тяжёлому CSS с лишними правилами; Mobile-first чище
  6. Брейкпоинты по устройствам, не по контенту — правильнее устанавливать брейкпоинт там, где раскладка «ломается», а не по размеру iPhone
  7. Тестирование только в DevTools — реальные устройства ведут себя иначе

Практика

  • Создать layout с auto-fit + minmax без media queries
  • Реализовать fluid typography через clamp
  • Сделать адаптивную навигацию (desktop-links / mobile-burger)
  • Настроить систему fluid spacing через CSS-переменные
  • Проверить сайт на реальных устройствах (не только DevTools)

Связанные темы

Ресурсы