Адаптивная сетка для каталога

Как верстать подобного вида адаптивные сетки:

'1'

По мере изучения верстки, применял различные техники для верстки таких сеток(каталог, блок преимуществ и так далее), но остановился на подходе описанном ниже, как более универсальном и чистым с точки зрения эстетики.

Сразу можно посмотреть этот пример со всеми стилями на codepen

Вот HTML для такой сетки:

<div class="section"> <!-- Основная секция -->
  <div class="container"> <!-- Основной контейнер -->
    <div class="catalog"> <!-- Блок каталога -->
      <div class="catalog__flex"> <!-- Родитеский блок сетки -->
        <div class="catalog__col"> <!-- Дочерний блок сетки -->
          <div class="catalog__card card"> <!-- Блок с контентом, в данном случае карточка, все стили этого блока уже не относятся к сетке -->
            <div class="card__title">Lorem ipsum dolor sit amet</div>
            <div class="card__text">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod</div>
            <div class="card__button"><a href="">Button</a></div>
          </div>
        </div>
        <div class="catalog__col"> <!-- Дочерний блок сетки -->
          <div class="catalog__card card"> <!-- Блок с контентом, в данном случае карточка, все стили этого блока уже не относятся к сетке -->
            <div class="card__title">Lorem ipsum dolor sit amet</div>
            <div class="card__text">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod</div>
            <div class="card__button"><a href="">Button</a></div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

Основные стили для сетки:

.section {
  margin: 60px 0 /* внешние отступы для блока - сверху и снизу по 60px, слева и справа по 0px */;
}
.container {
  max-width: 1170px /* максимальная ширина контейнера */;
  margin: 0 auto /* расположение контейнера по центру */;
  padding: 0 30px /* внутренние отступы слева и справа по 30px, верхний и нижний отступы по 0px */;
}
.catalog__flex {
  display: flex /* по умолчанию дочерние блоки(.catalog__col) будут располагаться в ряд */;
  flex-wrap: wrap /* дочерние блоки переносятся на следующую строку, если ширина всех внутренних блоков превышает ширину родительского блока(.catalog__flex) */;
  margin: 0 -15px -30px /* Отрицательные внешние отступы(значения противоположные значениям padding блока .catalog__col), чтобы компенсировать внутренние отступы дочерних блоков(.catalog__col), НЕ ДОЛЖЕН превышать боковых значений padding блока .container*/;
}
.catalog__col {
  width: 25% /* Задаем ширину блока(по 4 блока в ряд)*/;
  padding: 0 15px 30px /* Размер внутренних отступов блока - справа и слева по 15px(которые дают общий отступ 30px между блоками) и снизу отступ 30px */;
}

Стили для адаптивности:

@media (max-width: 1199.98px) {
  .catalog__col {
    width: 33.33333333% /* при ширине браузера меньше 1200px будет по 3 блока в ряд */;
  }
}
@media (max-width: 991.98px) {
  .catalog__col {
    width: 50% /* при ширине браузера меньше 992px будет по 2 блока в ряд */;
  }
}
@media (max-width: 575.98px) {
  .catalog__col {
    width: 100% /* при ширине браузера меньше 576px будет по 1 блоку */;
  }
}


А теперь объясню ключевые моменты

Блок <div class="section"> - обычный отдельный блок в верстке

Блок <div class="container"> - общий контейнер, который обычно расположен по центру и с внутренними боковыми отступами padding в нашем примере по 30px, то есть padding-left: 30px и padding-right: 30px

'2'

Блок <div class="catalog"> - блок обертка для сетки, которую он будет содержать, необходим чтобы делать внешние отступы margin если это будет нужно, так как у блока сетки <div class="catalog__flex"> внешние отступы margin отрицательные

Блок <div class="catalog__col"> - у этого блока внутренние отступы padding создают отступы между блоками

Блок <div class="catalog__flex"> - у этого блока отрицательные внешние отступы margin равны внутренним отступам padding дочернего блока <div class="catalog__col">

Это все необходимо для того, чтобы блоки были расположены ровно по ширине контейнера и не было лишних отступов по 15px по краям, и внизу не было лишнего отступа в 30px

Нагляднее всего необходимость отрицательных отступов у <div class="catalog__flex"> можно посмотреть на таком примере - если у нас уже есть блок с контентом и он расположен по всей ширине контейнера, то если не ставить отрицательные отступы, то контент и карточки каталога не будут выровнены по одной линии

Так это выглядит без отрицательных отступов:

'3'

А так это выглядит с отрицательными отступами:

'4'

Внутренний блок <div class="catalog__card card"> будет помещаться в <div class="catalog__col"> и ему прописываем стили относящиеся только к внутреннему содержимому, которые не будет влиять на внешние отступы.



Примеры:

Если хотим расстояние между блоками по 20px и по бокам и внизу то пишем такие стили:

.catalog__flex {
  display: flex;
  flex-wrap: wrap;
  margin: 0 -10px -20px /* просто компенсируют отступы блока .catalog__col */;
}
.catalog__col {
  width: 25%
  padding: 0 10px 20px /* боковые внутренние отступы дают общий боковой отступ 20px, а отступ вниз остается 20px */;
}

Если хотим расстояние между блоками по 60px и по бокам и внизу то пишем такие стили:

.catalog__flex {
  display: flex;
  flex-wrap: wrap;
  margin: 0 -30px -60px /* просто компенсируют отступы блока .catalog__col */;
}
.catalog__col {
  width: 25%
  padding: 0 30px 60px /* боковые внутренние отступы дают общий боковой отступ 60px, а отступ вниз остается 60px */;
}

Если хотим расстояние между блоками по бокам 30px, а внизу 60px то пишем такие стили:

.catalog__flex {
  display: flex;
  flex-wrap: wrap;
  margin: 0 -15px -60px /* просто компенсируют отступы блока .catalog__col */;
}
.catalog__col {
  width: 25%;
  padding: 0 15px 60px /* боковые внутренние отступы дают общий боковой отступ 30px, а отступ вниз остается 20px */;
}

Распишу последний пример подробнее (расстояние между блоками по бокам 30px, а внизу 60px):

.catalog__flex {
  display: flex;
  flex-wrap: wrap;
  margin-left: -15px;
  margin-right: -15px;
  margin-bottom: -60px;
}
.catalog__col {
  width: 25%;
  padding-left: 15px;
  padding-right: 15px;
  padding-bottom: 60px;
}

Еще один важный нюанс - боковые внутренние отступы padding блока <div class="catalog__col"> не должны превышать боковые внутренние отступы ‘padding’ блока <div class="container">, то есть если у контейнера padding-left: 30px; и padding-right: 30px;, то у <div class="catalog__col"> боковые внутренние отступы padding не должны быть больше 30px, иначе при ширине браузера меньшей, чем ширина контейнера, будет появляться горизонтальная прокрутка.