Как стилизовать wrapper в CSS

Контент сайта должен находиться в элементе, имеющем такую ширину, чтобы его было легко читать. Для достижения этого мы можем использовать то, что называется wrapper, обёртка или контейнер. Есть несколько способов использования обёртки в CSS, и все они могут вызвать некоторые затруднения.

В этой статье я объясню вам всё, что нужно знать о контейнерах в CSS: как они работают и как их использовать. Обратите внимание, в статье я могу употреблять термины wrapper, обёртка и контейнер, но все они означают одно и то же.

Готовы? Давайте разбираться!

Кратко о контейнерах

Когда вы слышите слово обёртка или контейнер – это буквально означает, что группа элементов обёрнута другим элементом или содержится в нём. Не используя дополнительные объекты, мы можем добавить обёртку к элементу <body>, как показано ниже.

CSS

body {
  max-width: 1170px;
  margin-left: auto;
  margin-right: auto;
  padding-left: 16px;
  padding-right: 16px;
}

Однако добавлять wrapper к элементу <body> в современных условиях было бы не очень практично. Контейнер не позволяет дочерним элементам выходить за его границы. Посмотрите на следующую фигуру:

Кратко о контейнерах

У нас есть боковые и центральные элементы, которые существуют внутри другого элемента, оборачивающего их. Конечно, у элемента wrapper есть своя ширина.

HTML

<div class="wrapper">
  <aside>...</aside>
  <main>...</main>
</div>

Без контейнера дочерние элементы соприкасались бы с границами экрана. Это выглядело бы довольно раздражающе для пользователя, особенно на большом экране.

Кратко о контейнерах - 2

Фигура, продемонстрированная выше, показывает, что элементы растягиваются, если их ничто не оборачивает. Пользователю не стоит видеть такую картину. Давайте объясню, почему.

Почему страница должна иметь обёртку

Использование контейнера на странице даёт много преимуществ, о которых вы, как дизайнер или разработчик, должны знать. Вот некоторые из них:

  1. Контейнеры делают контент более читабельным. Без обёртки такой контент как текст или картинки может растянуться на полную ширину экрана. На маленьких экранах это может быть приемлемо, но на больших выглядит неприятно.
  2. Обертки группируют элементы так, что становится легче настраивать расстояние между ними.
  3. Без обертки было бы сложно разделить элементы дизайна на колонки.

Добавляем ширину

Добавляем ширину

Первая вещь, о которой стоит подумать, создавая wrapper, – это его ширина. Насколько широким вы хотите его видеть? Это зависит от вашего дизайна. Как правило, чаще всего используется ширина контейнера в диапазоне 1000px – 1300px. Самый популярный фреймворк Bootstrap, например, использует ширину в 1170px.

CSS

.wrapper {
  width: 1170px;
}

Однако не рекомендуется использовать свойство width, так как из-за этого может появиться горизонтальная прокрутка экрана, если его размер меньше 1170px. Но вы можете от неё избавиться, добавив свойство max-width.

CSS

.wrapper {
  width: 1170px;
  max-width: 100%;
}

Это будет работать, но вы также можете убрать свойство width и использовать только max-width, как показано ниже:

CSS

.wrapper {
  max-width: 1170px;
}

Теперь, когда мы добавили контейнеру ширину, давайте расположим его в центре.

Центрирование контейнера

Центрирование контейнера

Чтобы разместить контейнер в центре, вы должны присвоить свойству margin значение auto с левой и правой стороны. Смотрите пример, приведенный ниже:

CSS

.wrapper {
  max-width: 1170px;
  margin: 0 auto;
}

Согласно спецификации CSS, auto margin работает следующим образом:

Если свойствам margin-left и margin-right присвоено значение auto, то размер отступа с обеих сторон будет одинаковым. Это горизонтально центрирует объект, относительно краёв содержащего блока.

Я использовал параметр «margin: 0 auto», который сбрасывает значение margin сверху и снизу до нуля, а справа и слева устанавливает значение auto. Пользуясь этим способом, можно ожидать некоторых последствий, о которых я расскажу в этой статье чуть позже.

Пока что рекомендую установить значения margin вручную.

CSS

.wrapper {
  max-width: 1170px;
  margin-left: auto;
  margin-right: auto;
}

Добавляем padding слева и справа

Добавляем padding слева и справа

Важно не забыть добавить padding с левой и правой стороны. Если размер окна просмотра меньше максимальной ширины контейнера, то края контейнера будут соприкасаться с границами окна просмотра.

CSS

.wrapper {
  max-width: 1170px;
  margin-left: auto;
  margin-right: auto;
  padding-left: 16px;
  padding-right: 16px;
}

Добавляя padding, мы можем быть уверены, что слева и справа будет отступ в 16px, даже если ширина окна просмотра меньше максимальной ширины контейнера.

Свойство padding действует как подстраховка, не допускающая прилегания границ контейнера к границам окна просмотра, в случае нехватки места.

Использование процентной ширины для контейнера

Я получил ответ об использовании процентной ширины (типа max-width: 90%) для контейнера, вместо добавления padding-left и padding-right.

Использование процентной ширины для контейнера

В случае использования этого метода, ширина, равная 90% от окна просмотра, будет слишком крупной на больших экранах. Это можно исправить, используя медиа-запросы.

CSS

.wrapper {
  max-width: 90%;
  margin-left: auto;
  margin-right: auto;
}

/* Медиа-запрос для большого экрана */
@media (min-width: 1170px) {
  .wrapper {
    max-width: 1170px;
  }
}

Применяя процентную ширину, мы совершаем дополнительный шаг. Можно легко избежать этот шаг, используя фиксированное значение ширины. Другое решение говорит, что мы можем совместить width: 90% со свойством max-width: 1170px.

CSS

.wrapper {
  width: 90%;
  max-width: 1170px;
  margin-left: auto;
  margin-right: auto;
}

Это довольно интересный подход, но я бы предпочел самостоятельно добавить padding, вместо того чтобы полагаться на процентную ширину.

Способ отображения контейнера

Так как контейнер – это <div>, он по умолчанию является блочным элементом. Вопрос в том, что делать, если мы хотим, чтобы он отображался в виде сетки, и всё его содержимое располагалось на сетке?

Что ж, я бы не рекомендовал так делать, потому что это противоречит концепции разделения обязанностей. «Обёртка» оборачивает другие элементы, и на этом всё. Если вам нужен контейнер с сеткой, добавьте в существующий контейнер элемент <div> со свойством display: grid. Это более простой, понятный и доступный способ.

HTML

<div class="wrapper">
  <!-- Содержимое -->
</div>

Так делать не рекомендуется, потому что использование элемента wrapper на другой странице может случайно повредить вашу вёрстку.

CSS

.wrapper {
  display: grid;
  grid-template-columns: 2fr 1fr;
  grid-gap: 16px;
}

Лучшим решением будет следующее:

HTML

<div class="wrapper">
  <div class="featured-news">
    <!-- Элементы, которые должны находиться в сетке -->
  </div>
</div>

CSS

.featured-news {
  display: grid;
  grid-template-columns: 2fr 1fr;
  grid-gap: 16px;
}

Заметьте, что я добавил отдельный элемент <div>, чтобы он содержал контент. Пожалуйста, не обращайте внимания на классы и соглашения по именованию в этом примере. Мы можем найти гораздо лучшее решение, создав названия классов, которые могут быть использованы повторно на разных страницах сайта. Однако соглашения по именованию выходят за рамки этой статьи.

Добавляем отступ между контейнерами

Помните, я не рекомендовал использовать сокращенную версию кода для центрирования контейнера? Я говорю об этой версии:

CSS

.wrapper {
  margin: 0 auto;
}

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

CSS

.wrapper-variation {
  margin-top: 50px;
}

.wrapper {
  max-width: 1170px;
  margin-left: auto;
  margin-right: auto;
  padding-left: 16px;
  padding-right: 16px;
}

Свойство margin не будет работать для элемента wrapper-variation, потому что оно противоречит свойству margin: 0 auto. Сокращенное свойство будет отменять полное. Чтобы избежать подобной путаницы, в таких случаях рекомендуется использовать полные свойства.

Теперь давайте перейдём к созданию отступа. В каждом проекте я подготавливаю несколько служебных классов и использую их по необходимости. Обратите внимание на следующую модель:

Добавляем отступ между контейнерами

HTML

<div class="wrapper mb-5"></div>
<section>
  <div class="wrapper"></div>
</section>
<div class="wrapper"></div>

CSS

.mb-5 {
  margin-bottom: 3rem !important;
}

Благодаря подобному подходу, сам контейнер остаётся без изменений, а отступ добавляется к дополнительным служебным классам в CSS. Теперь вы, наверное, спросите, зачем мне создавать несколько контейнеров на странице, если я могу создать один? В HTML-коде, приведенном выше, между двумя контейнерами есть элемент <section>.

Здесь было бы полезно использовать декларацию !important, так как основная цель служебных классов в CSS, – сделать определенное свойство обязательным. Мы гарантируем это, добавляя !important.

Контейнер внутри полноэкранного раздела

Могут быть случаи, когда фон секции занимает 100% ширины окна просмотра, а внутри секции находится контейнер. Это похоже на то, что я показывал в предыдущем примере.

Структура HTML-страницы может выглядеть так:

HTML

<section>
  <div class="wrapper"></div>
</section>
<section>
  <div class="wrapper"></div>
</section>

Элемент <section> занимает 100% ширины окна просмотра. Вы можете добавить к нему фоновый цвет или изображение. Внутри него контейнер не позволяет содержимому занять всю ширину окна просмотра.

Контейнер внутри полноэкранного раздела

На картинке, приведенной выше, у элемента <section> есть фоновое изображение, которое занимает всю ширину окна просмотра. Контент внутри него ограничен шириной контейнера.

Нужен ли контейнер для первой секции?

Бывает по-разному. Давайте рассмотрим два наиболее часто используемых варианта дизайна первой секции (Hero Section).

В первом варианте содержимое располагается по центру и ограничивается определенной шириной.

Нужен ли контейнер для первой секции?

Во втором варианте содержимое растягивается по ширине основного контейнера.

Нужен ли контейнер для первой секции? - 2

Чтобы лучше понять эти две модели, давайте разберёмся, как построить каждую из них.

Первая секция с контентом в центре

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

HTML

<section class="hero">
  <h2>How to make bread at home</h2>
  <p>....</p>
  <p><a href="/sign-up">Sign up</a></p>
</section>

Имея такой HTML-код, вы бы центрировали содержимое с помощью text-align.

CSS

.hero {
  text-align: center;
}

Это будет выглядеть здорово до тех пор, пока вы не измените размер окна браузера. Вы можете столкнуться проблемами, рассматриваемыми далее.

Содержимое касается краёв

Так как padding справа и слева отсутствует, содержимое будет касаться краёв без каких-либо отступов. Это плохо для пользователя, ведь в подобной ситуации сложно просматривать и читать контент.

Содержимое касается краёв

Слишком длинная строка на больших экранах

Будет очень сложно читать текст абзаца на больших экранах, так как строка слишком длинная. Сайт «Элементы типографического стиля, используемые в сети» рекомендует, чтобы в строке было 45-75 символов. Чем дальше от этого диапазона, тем сложнее будет читать текст, представленный на веб-странице.

Слишком длинная строка на больших экранах

Для устранения подобных проблем, можно использовать контейнер, который не даст строке текста стать слишком длинной и добавит отступ на мобильных устройствах.

HTML

<section class="hero">
  <div class="hero__wrapper">
    <h2>How to make bread at home</h2>
    <p>...</p>
    <p><a href="/sign-up">Sign up</a></p>
  </div>
</section>

Я использовал класс hero__wrapper, так как этот контейнер может принадлежать только первой секции (Hero Section), поэтому его ширина может быть меньше ширины других контейнеров.

CSS

.hero__wrapper {
  max-width: 720px;
  margin-left: auto;
  margin-right: auto;
  padding-left: 16px;
  padding-right: 16px;
}

Для центрирования содержимого вы можете применить любой метод, который хотите, в зависимости от варианта использования. В этом примере будет достаточно применить text-align: center, чтобы расположить контент в центре.

Контейнер стоит выравнивать по центру или по левой стороне?

Не знаю, есть ли однозначный ответ на этот вопрос, но я видел сайты, которые на экранах ноутбуков выравнивают контейнер по центру, а на экранах компьютеров – по левой стороне.

Сайт TechCrunch – хороший тому пример. Обратите внимание на то, что на больших экранах он выравнивается по левой стороне.

Контейнер стоит выравнивать по центру или по левой стороне?

Лично я больше люблю сайты, которые выравниваются по центру и имеют симметричный отступ справа и слева. Возможно, поэтому я мало знаю о данной теме.

Используем переменные CSS для вариаций контейнеров

Редко случается так, что вам нужен контейнер только одного размера. Ширина контейнера может быть большой или маленькой, в зависимости от содержимого и варианта использования. Применяя переменные CSS, мы можем по-новому взглянуть на wrapper и сделать его максимально пластичным. Обратите внимание на следующее:

HTML

<div class="wrapper"></div>

CSS

.wrapper {
  max-width: var(--wrapper-width, 1170px);
  margin-left: auto;
  margin-right: auto;
  padding-left: 16px;
  padding-right: 16px;
}

Возможно, вы заметили, что у функции var есть два значения: первое –
—wrapper-width, и второе – 1170px. Вторая переменная является резервной, то есть используется, если значение переменной —wrapper-width не установлено.

Что это значит? Это значит, что вы можете создать вариацию контейнера, установив свойство —wrapper-width, как показано ниже.

HTML

<div class="wrapper" style="--wrapper-width: 720px"></div>

Таким образом, я создал вариацию контейнера:

  • Без добавления новых классов;
  • Не копируя и не вставляя стили;
  • Более надежную и легко редактируемую с помощью DevTools.

Если вам не нравится использовать встроенные стили для изменения переменной CSS, вы можете вместо этого добавить новый класс. Смотрите пример, приведенный ниже:

HTML

<div class="wrapper wrapper--small"></div>

CSS

.wrapper--small {
  --wrapper-width: 720px;
  /* это изменит ширину контейнера, установленную по умолчанию */
}

Используем свойство Display: Contents

Для начала я вас познакомлю с этим значением. Каждый элемент в CSS является блочным; и этот блок содержит контент, границы, внутренние и внешние отступы. Если вы примените display: contents, этот блок будет исключен из потока. Я могу представить это как удаление открывающего и закрывающего тэгов вокруг него.

CSS

<header class="site-header">
    <div class="wrapper site-header__wrapper">
            <!-- Header content -->
    </div>
</header>

CSS

.site-header__wrapper {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}
Используем свойство Display: Contents

Возможно, в примере, приведенном выше, вам понадобится растянуть header на всю ширину страницы, вместо того, чтобы вписывать его в контейнер.

CSS

.site-header__wrapper {
  display: contents;
}

.site-header {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}

Таким способом элемент wrapper будет скрыт (в каком-то смысле). Теперь, когда мы применили display: flex к элементу site-header, объекты, принадлежавшие контейнеру, станут дочерними для элемента site-header.

Используем свойство Display: Contents - 2

Адаптивный фон, фиксированный контент

В своей книге о секретах CSS Лия Веру предложила интересную технику, которая может быть использована для секций с адаптивным фоном (фон, занимающий всю ширину окна просмотра), внутри которых есть контейнер. Давайте рассмотрим распространенный способ, позволяющий сделать это:

HTML

<section>
  <div class="wrapper"></div>
</section>

CSS

section {
  background-color: #ccc;
}

.wrapper {
  max-width: 1170px;
  margin-left: auto;
  margin-right: auto;
  padding-left: 16px;
  padding-right: 16px;
}

Принцип работы margin-left: auto и margin-right: auto заключается в вычислении половины ширины окна просмотра и вычитании из неё ширины контента. То же самое можно сделать, используя padding.

Адаптивный фон, фиксированный контент

CSS

section {
  padding: 1rem calc(50% - 585px);
}

Мы ещё не закончили. На мобильных устройствах контент будет соприкасаться с границами экрана. Решить это можно следующим способом:

CSS

section {
  padding: 1rem;
}

@media (min-width: 1170px) {
  section {
    padding: 1rem calc(50% - 585px);
  }
}

В качестве альтернативного решения можно использовать новую функцию CSS max(). Мы просто устанавливаем минимальный padding размером в 1rem, а вычисление 50% — 585px будет использовано в качестве другого значения.

CSS

section {
  padding: 1rem max(1rem, (50% - 585px));
}

Конец

Вот мы и стилизовали наш wrapper. У вас есть комментарий или предложение?

Пожалуйста, оставьте ваши комментарии по текущей теме материала. Мы очень благодарим вас за ваши комментарии, отклики, подписки, лайки, дизлайки!

Сергей Бензенкоавтор-переводчик статьи «Styling Layout Wrappers In CSS»