Статьи

Простые адаптивные макеты CSS сетки: 4 метода

В наши дни есть основа для всего, и кажется, что прежде чем мы сможем даже переварить один, выпускается еще один. Это особенно верно, когда речь идет о макетах CSS-сетки, и нет недостатка в фреймворках, которые считаются «лучшими, самыми легкими на сегодняшний день». Эта передозировка информации может сбить нас с толку и заставить нас задуматься о том, действительно ли фреймворки, такие как HTML9 Responsive Boilerstrap JS , действительно подходят.

Давайте сделаем шаг назад, немного вздохнем и зададимся вопросом: действительно ли мы будем использовать каждый из этих 24 вариантов и миллион подвариантов, с которыми поставляется «Тот Великий каркас»? Часто нам нужно только простое гибкое решение с несколькими вариантами для работы в нашем проекте, и с сильным знанием основ мы можем расширять его по своему усмотрению. Я собираюсь представить четыре различных метода для разработки вашей собственной сетки CSS, и каждый из них легко расширяется. Вот четыре метода:

  1. Адаптивный макет сетки, v1 (с использованием отрицательных полей)
  2. Адаптивный макет сетки, v2 (с использованием box-sizing: border-box
  3. Адаптивный макет сетки с использованием отображения таблицы
  4. Адаптивное расположение сетки с использованием flexbox

Я собираюсь упростить эти методы, используя минимальное количество простого и понятного CSS. Демонстрация CodePen будет предоставляться с каждым примером, так что вы можете раскошелиться и / или поиграть с CSS в демоверсиях. Давайте погрузимся в.

Примечание: я включил встроенные демонстрации для каждого, но для того, чтобы увидеть полную адаптивность каждого метода, лучше всего просмотреть демонстрации CodePen в полноэкранном режиме, нажав ссылку «Изменить на CodePen» в верхней части каждой демонстрации.

Общий CSS

Прежде чем мы углубимся в каждый метод, давайте рассмотрим некоторые распространенные CSS, которые мы будем использовать. Мы будем использовать объявление box-sizing: border-box.clearfixочистки чисел с плавающей точкой . Вот наш базовый CSS:

 /* resets */
*,
*:before,
*:after {
  box-sizing: border-box;
}
.clearfix:after {
  content: "";
  display: table;
  clear: both;
}

В случае, если нужны какие-либо префиксы от поставщиков, мы будем использовать функцию автопрефиксера CodePen, чтобы заполнить их для нас. Давайте теперь перейдем к первому из наших четырех методов.

Способ 1: использование отрицательных полей

Этот метод использует отрицательные поля для создания блоков сетки CSS с фиксированным отступом между каждым блоком. Отрицательное поле изменяется в зависимости от положения блока сетки, а поле между блоками сетки остается фиксированным. Давайте сначала посмотрим на HTML:

 <div class="row-2 clearfix">
  <div class="col-1-2"></div>
  <div class="col-1-2"></div>
</div><!-- /.row -->

<div class="row-4 clearfix">
  <div class="col-1-4"></div>
  <div class="col-1-4"></div>
  <div class="col-1-4"></div>
  <div class="col-1-4"></div>
</div><!-- /.row -->

<div class="row-8 clearfix">
  <div class="col-1-8"></div>
  <div class="col-1-8"></div>
  <div class="col-1-8"></div>
  <div class="col-1-8"></div>
  <div class="col-1-8"></div>
  <div class="col-1-8"></div>
  <div class="col-1-8"></div>
  <div class="col-1-8"></div>
</div><!-- /.row -->

И наш CSS:

 /* grid */
[class*="row-"] {
  margin-bottom: 20px;
}
[class*="row-"]:last-child {
  margin-bottom: 0;
}
[class*="col-"] {
}

@media all and ( min-width: 768px ) {

  /* all cols margin */
  [class*="col-"] {
    margin-right: 20px;
  }
  [class*="col-"]:last-child {
    margin-right: 0;
  }

  /* make the columns responsive */
  .col-1-2 {
    float: left;
    width: 50%;
  }
  .col-1-4 {
    float: left;
    width: 25%;
  }
  .col-1-8 {
    float: left;
    width: 25%;
  }

  /* 2 span rows */
  .row-2 {
    padding-left: 20px;
  }
  .row-2 [class*="col-"]:first-child {
    margin-left: -20px;
  }

  /* 4 span rows */
  .row-4 {
    padding-left: 60px;
  }
  .row-4 [class*="col-"]:first-child {
    margin-left: -60px;
  }

  /* 8 span rows */
  .row-8 {
    padding-left: 60px;
  }
  .row-8 [class*="col-"]:nth-child(4n+1) {
    margin-left: -60px;
  }
  .row-8 [class*="col-"]:nth-child(5n-1) {
    margin-right: 0;
  }
  .row-8 [class*="col-"]:nth-child(6n-1) {
    clear: both;
  }

}

@media all and ( min-width: 1200px ) {

  /* adjust width */
  .col-1-8 {
    float: left;
    width: 12.5%;
  }

  /* 8 span rows */
  .row-8 {
    padding-left: 140px;
  }
  /* reset these... */
  .row-8 [class*="col-"]:nth-child(4n+1) {
    margin-left: 0;
  }
  .row-8 [class*="col-"]:nth-child(5n-1) {
    margin-right: 20px;
  }
  .row-8 [class*="col-"]:nth-child(6n-1) {
    clear: none;
  }
  /* and add this */
  .row-8 [class*="col-"]:nth-child(1) {
    margin-left: -140px;
  }

}

А вот демоверсия CodePen:

Как вы можете видеть, когда мы достигаем чувствительной точки останова, слева от строки добавляется фиксированное значение поля (назовем его x), умноженное на количество столбцов минус 1 (n-1). Каждый столбец имеет правое поле x, кроме последнего дочернего элемента. И первый ребенок имеет отрицательное поле (n-1) * (x).

Недостатки и ошибки

Для этого метода требуется некоторая математика, которая становится непрактичной по мере увеличения количества элементов сетки. Кроме того, когда мы расширяем его на нескольких шагах столбца (например, переходя от 1 к строке, к 4, к 8), мы должны сбросить CSS, и в него вовлечено много математики nth-child

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

Преимущества и использование в реальном мире

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

 <div class="container clearfix">
  <div class="primary">
    <h2>Primary</h2>
    Lorem ipsum dolor...
  </div>
  <div class="secondary">
    <h2>Secondary</h2>
    Lorem ipsum dolor...
  </div>
</div><!-- /.container -->

И наш CSS так:

 /* layout */
.primary {
  margin-bottom: 20px;
}

@media all and ( min-width: 600px ) {

  .container {
    padding-right: 300px;
  }
  .primary {
    float: left;
    padding-right: 60px;
    width: 100%;
  }
  .secondary {
    float: right;
    margin-right: -300px;
    width: 300px;
  }

}

Вот демонстрация CodePen, чтобы увидеть его в действии:

Способ 2: использование box-sizing: border-box

Этот метод использует всю мощь объявления box-sizing: border-box Поскольку эта функция позволяет нам дополнить элемент, не добавляя его к общей ширине, мы все равно можем создать гибкую сетку с фиксированными «полями». На этот раз, вместо использования свойства margin Давайте посмотрим на некоторые HTML:

 <div class="row clearfix">
  <div class="col-1-2"></div>
  <div class="col-1-2"></div>
</div><!-- /.row -->

<div class="row clearfix">
  <div class="col-1-4"></div>
  <div class="col-1-4"></div>
  <div class="col-1-4"></div>
  <div class="col-1-4"></div>
</div><!-- /.row -->

<div class="row clearfix">
  <div class="col-1-8"></div>
  <div class="col-1-8"></div>
  <div class="col-1-8"></div>
  <div class="col-1-8"></div>
  <div class="col-1-8"></div>
  <div class="col-1-8"></div>
  <div class="col-1-8"></div>
  <div class="col-1-8"></div>
</div><!-- /.row -->

Здесь нам также не понадобится сумасшедшая математика, поэтому наш CSS становится действительно простым. Вот оно, до восьми столбцов:

 /* grid */
.row {
  margin: 0 -10px;
  margin-bottom: 20px;
}
.row:last-child {
  margin-bottom: 0;
}
[class*="col-"] {
  padding: 10px;
}

@media all and ( min-width: 600px ) {

  .col-2-3 {
    float: left;
    width: 66.66%;
  }
  .col-1-2 {
    float: left;
    width: 50%;
  }
  .col-1-3 {
    float: left;
    width: 33.33%;
  }
  .col-1-4 {
    float: left;
    width: 25%;
  }
  .col-1-8 {
    float: left;
    width: 12.5%;
  }

}

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

Вот демо:

Расширение этого метода

Допустим, вы хотели, чтобы .col-8 Немного подумав, это очень просто. Предполагая ту же разметку, что и выше, наш CSS будет выглядеть так:

 @media all and ( min-width: 600px ) {

  .col-1-8 {
    float: left;
    width: 25%;
  }
  .col-1-8:nth-child(4n+1) {
    clear: both;
  }

}

@media all and ( min-width: 960px ) {

  .col-1-8 {
    width: 12.5%;
  }
  .col-1-8:nth-child(4n+1) {
    clear: none;
  }

}

Вот демо:

Метод 3: Использование отображения таблицы

Этот метод реализует устаревшую функциональность table В этом методе видимые элементы по умолчанию являются блочными. Но в определенной точке останова строки сетки становятся таблицами, а столбцы — ячейками таблицы. Давайте посмотрим на разметку — она ​​похожа на метод 2, но не требуется никаких исправлений:

 <div class="row">
  <div class="col-1-2"></div>
  <div class="col-1-2"></div>
</div><!-- /.row -->

<div class="row">
  <div class="col-1-4"></div>
  <div class="col-1-4"></div>
  <div class="col-1-4"></div>
  <div class="col-1-4"></div>
</div><!-- /.row -->

<div class="row">
  <div class="col-1-8"></div>
  <div class="col-1-8"></div>
  <div class="col-1-8"></div>
  <div class="col-1-8"></div>
  <div class="col-1-8"></div>
  <div class="col-1-8"></div>
  <div class="col-1-8"></div>
  <div class="col-1-8"></div>
</div><!-- /.row -->

А вот и CSS:

 /* grid */
.row {
  margin: 0 -10px;
  margin-bottom: 10px;
}
.row:last-child {
  margin-bottom: 0;
}
[class*="col-"] {
  padding: 10px;
}

@media all and ( min-width: 600px ) {

  .row {
    display: table;
    table-layout: fixed;
    width: 100%;
  }
  [class*="col-"] {
    display: table-cell;
  }

  /* set col widths */
  .col-2-3 {
    width: 66.66%;
  }
  .col-1-2 {
    width: 50%;
  }
  .col-1-3 {
    width: 33.33%;
  }
  .col-1-4 {
    width: 25%;
  }
  .col-1-8 {
    width: 12.5%;
  }

}

И наша демка:

Этот метод может показаться запутанным, но есть и преимущества. Для начала, мы не нарушаем семантику, используя традиционные макеты таблиц, и нам не нужно очищать числа с плавающей точкой. Столбцы с одинаковой высотой также очень просты. Гибкие и гибкие комбинации? Нет проблем. Тем не менее, отображение таблиц приносит свои проблемы и является моим наименее любимым из этих четырех методов, хотя иногда это хороший вариант.

Способ 4: Flexbox

Последний метод, который я представлю, использует модуль flexbox. Согласно MDN :

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

Flexbox предоставляет нам множество различных функций, которые дают нам мощный арсенал вариантов компоновки. Создание адаптивного модуля flexbox — абсолютный бриз. Как и прежде, наша разметка выглядит так:

 <div class="row">
  <div class="col-1-2"></div>
  <div class="col-1-2"></div>
</div><!-- /.row -->

<div class="row">
  <div class="col-2-3"></div>
  <div class="col-1-3"></div>
</div><!-- /.row -->

<div class="row">
  <div class="col-1-4"></div>
  <div class="col-1-4"></div>
  <div class="col-1-4"></div>
  <div class="col-1-4"></div>
</div><!-- /.row -->

<div class="row">
  <div class="col-1-8"></div>
  <div class="col-1-8"></div>
  <div class="col-1-8"></div>
  <div class="col-1-8"></div>
  <div class="col-1-8"></div>
  <div class="col-1-8"></div>
  <div class="col-1-8"></div>
  <div class="col-1-8"></div>
</div><!-- /.row -->

Вот посмотрите сейчас на наш CSS:

 /* grid */
.row {
  display: flex;
  flex-flow: row wrap;
  margin: 0 -10px;
  margin-bottom: 10px;
}
.row:last-child {
  margin-bottom: 0;
}
[class*="col-"] {
  padding: 10px;
  width: 100%;
}

@media all and ( min-width: 600px ) {

  /* set col widths */
  .col-2-3 {
    width: 66.66%;
  }
  .col-1-2 {
    width: 50%;
  }
  .col-1-3 {
    width: 33.33%;
  }
  .col-1-4 {
    width: 25%;
  }
  .col-1-8 {
    width: 12.5%;
  }

}

И демонстрация CodePen:

На этот раз нам нужно установить свойство displayflexflex-flow Полные определения и описания этих свойств доступны в документации по flexbox для MDN . В нашей отзывчивой точке останова мы переключаем ширину столбцов, а flexbox обрабатывает все остальное. Ухоженная!

Заворачивать

Мы рассмотрели 4 уникальных способа создания адаптивной системы сетки CSS, каждый из которых имеет свои преимущества. Не существует «лучшего» способа что-либо сделать, и я часто оказываюсь в ситуациях, когда один более эффективен, чем другой, или мне нужно комбинировать оба. Методы 1 и 2 — мои предпочтительные, и я часто их использую в одних и тех же проектах (определение основных макетов с помощью метода 1 и адаптивных сеток с помощью метода 2).

Метод 3 также имеет свои преимущества, как упомянуто выше, но я лично склоняюсь к макетам на основе таблиц, только когда это абсолютно необходимо. Метод 4 просто прекрасен, и я с нетерпением жду того дня, когда смогу свободно применять его во всех проектах. Flexbox находится в движении, но поддерживается только IE10 и выше. Доступны полифилы, но я предпочитаю вообще избегать их. Знайте свой рынок, хотя; Сегодня существуют сценарии, когда flexbox действительно предлагает идеальное решение.

Каждый из этих методов легко масштабируется и расширяется. С мыслительными процессами, представленными выше, у вас не должно быть никаких проблем при настройке сетки, адаптированной для вашего проекта с минимальным количеством CSS. Модуль CSS Grid также в разработке, но пройдет некоторое время, прежде чем мы рассмотрим его реализацию. Надеюсь, вам понравилось это читать, и теперь вы менее напуганы сетками CSS!