«Внутренняя» проблема

Предположим, что вам нужен контейнер на всю ширину окна. И все потому, что коде используется свойство background-color, растягивающее макет. Но содержимое страницы не обязательно должно растягиваться. Вам нужно добиться следующих результатов:

  1. Ограничить ширину (для больших экранов).
  2. Добавить отступы по краям.
  3. Отцентрировать содержимое.

Это не сложно реализовать…

Классическим решением является внешний и внутренний контейнеры

Предположим, что к элементу <body> применено свойство background-color , а также заданы отступы справа и слева. Внутренний контейнер (inside) ограничивает содержимое по ширине и высоте.

<footer>
  <div class="inside">
    Content
  </div>
</footer>
footer {
  --contentWidth: 400px;
  background: lightcoral;
  padding: 2rem 1rem;
}

.inside {
  max-width: var(--contentWidth);
  margin: 0 auto;
}

Кажется, что этот элемент (inside) лучше не использовать. Так как его нужно каждый раз добавлять его в разметку, когда используется такой шаблон. Но он выполняет ряд важных задач.

Что делать, если нужно использовать только один элемент?

Если у вас есть только один элемент, то свойство padding работает. Но для этого нужно использовать функцию calc(), чтобы вычесть половину максимальной ширины содержимого из 100%.

<footer>
  Content
</footer>
footer {
  --contentWidth: 600px;
  
  background: lightcoral;
  padding: 2rem calc((100% - var(--contentWidth)) / 2);
}

Но это не решает проблему касания краев. Может быть, стоило выбрать элементы внутри  и добавить к ним отступы с помощью селектора footer? Или  задать отступы для более «высоких» элементов. Например, <body>. Но это не сработает, потому что цвет фона должен охватывать всю область веб-страницы.

Что, если вы ограничены контейнером, который не можете контролировать, а из него нужно вырваться?

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

.full-width {
  width: 100vw;
  margin-left: 50%;
  transform: translateX(-50%);
}

Но это также растягивает содержимое контейнера на всю ширину. Поэтому нужно снова обратиться к внутреннему элементу.

Кроме этого, как только у вас появится вертикальная полоса прокрутки, значение 100vw приведет к добавлению горизонтального скроллбара. Чтобы избавиться от него, используйте свойство overflow-x:

body { overflow-x: hidden; }

Иначе придется явно установить ширину полосы прокрутки, а затем вычесть ее из 100vw.

body {
  scrollbar-width: 20px; /* способ в соответствии с будущими стандартами */
}

body::-webkit-scrollbar { /* способ webkit */
  width: 20px;
}

.full-width {
  width: calc(100vw - 20px);
}

Но тогда контейнер не вмещается в область просмотра по ширине, если нет вертикальной прокрутки. В CSS должен быть более приемлемый способ решения всех этих проблем.

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

Если убрать overflow-x из родительского элемента, тогда отрицательное поле и положительный отступ могут помочь решить проблему

В этой версии реализации задействуются только классические свойства CSS.

Могут ли здесь помочь CSS Grid или Flexbox?

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

«Подкраска» краев

Необязательно использовать только свойство background-color. Вы всегда можете «подделать» левую и правую стороны, задав огромный box-shadow или разместив псевдоэлемент.

Вадим Дворниковавтор-переводчик статьи «The “Inside” Problem»