Realizing common layouts using CSS Grid Layout

Этот перевод не завершён. Пожалуйста, помогите перевести эту статью с английского

Чтобы завершить набор руководств по CSS Grid Layout, я собираюсь пройтись по основным видам макетов, которые демонстрируют несколько различных методов, которые можно использовать при проектировании с помощью grid layout. Мы рассмотрим пример использования областей сетки-шаблона, типичную гибкую сеточную систему с 12 столбцами, а также список продуктов с использованием автоматического размещения. Как вы можете видеть из этого списка примеров, существует несколько способов достижения желаемого результата с помощью компоновки сетки. Выберите метод, который вы считаете наиболее полезным для решения проблем, которые вы решаете, и проектов, которые вам нужно реализовать.

Адаптивный 1-3 колоночный макет с использованием grid-template-areas

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

Image of the three different layouts created by redefining our grid at two breakpoints.

Я собираюсь создать этот макет, используя именованные области шаблонов, о которых мы узнали в руководстве Grid template areas.

Моя разметка-это контейнер с элементами внутри для хедера и футера, основного контента, навигации, боковой панели и блока, в который я собираюсь поместить рекламу.

<div class="wrapper">
        <header class="main-head">The header</header>
        <nav class="main-nav">
            <ul>
                <li><a href="">Nav 1</a></li>
                <li><a href="">Nav 2</a></li>
                <li><a href="">Nav 3</a></li>
            </ul>
        </nav>
        <article class="content">
            <h1>Main article area</h1>
            <p>In this layout, we display the areas in source order for any screen less that 500 pixels wide. We go to a two column layout, and then to a three column layout by redefining the grid, and the placement of items on the grid.</p>
        </article> 
        <aside class="side">Sidebar</aside>
        <div class="ad">Advertising</div>
        <footer class="main-footer">The footer</footer>
</div>

Поскольку мы используем grid-template-areas для создания макета, вне каких-либо медиа-запросов, мне нужно назвать области. Мы называем области, используя свойство grid-area.

.main-head {
  grid-area: header;
}
.content {
  grid-area: content;
}
.main-nav {
  grid-area: nav;
}
.side {
  grid-area: sidebar;
}
.ad {
  grid-area: ad;
}
.main-footer {
  grid-area: footer;
}

Это не создаст никакого макета, однако наши элементы теперь имеют имена, которые мы можем использовать для создания. Оставаясь вне каких-либо медиа-запросов, я теперь собираюсь настроить макет для мобильной платформы. Здесь я держу все в исходном порядке, пытаясь избежать любого разрыва между источником и дисплеем, как описано в руководстве Grid layout and accessibility. У меня нет столбцов или строк, т. к. такой макет предполагает один столбец, и строки будут создаваться по мере необходимости для каждого из элементов неявной сетки.

.wrapper {
  display: grid;
  grid-gap: 20px;
  grid-template-areas: 
    "header"
    "nav"
    "content"
    "sidebar"
    "ad"
    "footer";
}

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

@media (min-width: 500px) {
  .wrapper {
    grid-template-columns: 1fr 3fr;
    grid-template-areas: 
      "header  header"
      "nav     nav"
      "sidebar content"
      "ad      footer";
  }
  nav ul {
    display: flex;
    justify-content: space-between;
  }
}

Вы можете видеть, как макет принимает форму в значении grid-template-areas. Заголовок охватывает две дорожки столбцов, как и навигационная система. В треке третьего ряда у нас есть боковая панель рядом с содержимым. В четвертой строке я решил разместить свой рекламный контент – так он появляется под боковой панелью, а затем футер, рядом с ним под контентом. Я использую flexbox в навигации, чтобы отобразить его в разнесенном ряду.

Тепреь я могу добавить конечные точки в наш 3-х колоночный макет.

@media (min-width: 700px) {
  .wrapper {
    grid-template-columns: 1fr 4fr 1fr;
    grid-template-areas: 
      "header header  header"
      "nav    content sidebar"
      "nav    content ad"
      "footer footer  footer"
   }
   nav ul {
     flex-direction: column;
   }
}

Трехколоночный макет имеет две боковые колонки размером 1fr и среднюю колонку, размером 4fr . Это означает, что доступное пространство в контейнере разделено на 6 ячеек и распределено пропорционально нашему макету – по одной части к боковым колонкам и по 4 части к центру.

В этом макете я показываю навигацию в левой колонке, рядом с содержимым. В правой колонке у нас есть боковая панель, а под ней блок рекламы (ad). Футер теперь охватывает всю нижнюю часть макета. Затем я использую flexbox для отображения навигации в виде столбца.

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

Гибкий 12-колоночный макет.

Если вы работали с фреймворками или grid системами, вам знакомо размещение сайта на гибкой сетке с 12 или 16 столбцами. Мы можем создать такой макет, используя CSS Grid Layout. В качестве простого примера я создаю гибкую сетку из 12 столбцов, которая имеет 12 линий столбцов размером 12 1fr-все они имеют начальную линию с именем col-start. Это означает, что у нас будет двенадцать линий сетки с именем col-start.

.wrapper {
  display: grid;
  grid-template-columns: repeat(12, [col-start] 1fr);
  grid-gap: 20px;
}

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

<div class="wrapper">
  <div class="item1">Start column line 1, span 3 column tracks.</div>
  <div class="item2">Start column line 6, span 4 column tracks. 2 row tracks.</div>
  <div class="item3">Start row 2 column line 2, span 2 column tracks.</div>
  <div class="item4">Start at column line 3, span to the end of the grid (-1).</div>
</div>

Затем я могу поместить их в сетку, используя именованные линии, а также ключевое слово span.

.item1 {
  grid-column: col-start / span 3;
}
.item2 {
  grid-column: col-start 6 / span 4 ;
  grid-row: 1 / 3;
}
.item3 {
  grid-column: col-start 2 / span 2;
  grid-row: 2;
}
.item4 {
  grid-column: col-start 3 / -1;
  grid-row: 3;
}

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

Вместо того чтобы устанавливать номер конечной строки, я решил указать, сколько треков должен охватить этот элемент, используя ключевое слово span. Мне нравится этот подход, поскольку при работе с системой макета с несколькими столбцами мы обычно думаем о блоках с точки зрения количества треков сетки, которые они охватывают, и в зависимости от этого корректируем. Чтобы увидеть, как блоки выравниваются по трекам, используйте инспектор сетки Firefox Grid Inspector. Он наглядно демонстрирует, как расположены наши предметы.

Showing the items placed on the grid with grid tracks highlighted.

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

Построение макета с использованием 12-столбцовой системы

Чтобы увидеть, как этот метод макета работает на практике, мы можем создать тот же самый макет, который мы создали с grid-template-areas, на этот раз используя сеточную систему из 12 столбцов. Я начинаю с той же разметки, которая используется для примера областей шаблона сетки.

<div class="wrapper">
        <header class="main-head">The header</header>
        <nav class="main-nav">
            <ul>
                <li><a href="">Nav 1</a></li>
                <li><a href="">Nav 2</a></li>
                <li><a href="">Nav 3</a></li>
            </ul>
        </nav>
        <article class="content"><h1>Main article area</h1>
        <p>In this layout, we display the areas in source order for any screen less that 500 pixels wide. We go to a two column layout, and then to a three column layout by redefining the grid, and the placement of items on the grid.</p></article> 
        <aside class="side">Sidebar</aside>
        <div class="ad">Advertising</div>
        <footer class="main-footer">The footer</footer>
    </div>

Затем я настраиваю сетку как в примере выше.

.wrapper {
  display: grid;
  grid-template-columns: repeat(12, [col-start] 1fr);
  grid-gap: 20px;
}

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

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

.wrapper > * {
  grid-column: col-start / span 12;
}

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

Панель объявлений находится ниже боковой панели, поэтому начинается с строки сетки 4. Затем у нас есть основное содержимое и футер, начинающийся с col-start 4 и охватывающий 9 треков, ведущих их к концу сетки.

@media (min-width: 500px) {

  .side {
    grid-column: col-start / span 3;
    grid-row: 3;
  }
  .ad {
    grid-column: col-start / span 3;
    grid-row: 4;
  }
  .content, .main-footer {
    grid-column: col-start 4 / span 9;
  }
  nav ul {
    display: flex;
    justify-content: space-between;
  }
}

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

@media (min-width: 700px) {
  .main-nav {
    grid-column: col-start / span 2;
    grid-row: 2 / 4;
  }
  .content {
    grid-column: col-start 3 / span 8;
    grid-row: 2 / 4;
  }
  .side {
    grid-column: col-start 11 / span 2;
    grid-row: 2;
  }
  .ad {
    grid-column: col-start 11 / span 2;
    grid-row: 3;
  }
  .main-footer {
    grid-column: col-start / span 12;
  }
  nav ul {
    flex-direction: column;
  }
}

Снова смотрим Grid Inspector, чтобы увидеть, какую форму принял наш макет.

Showing the layout with grid tracks highlighted by the grid inspector.

При создании этого макета следует отметить, что нам не нужно было явно размещать каждый элемент сетки в каждой контрольной точке. Мы унаследовали ранее настроенное размещение – преимущество работы “сначала мобильный". Мы также можем воспользоваться преимуществами автоматического размещения сетки. Сохраняя элементы в логическом порядке, автоматическое размещение делает довольно много работы за нас при размещении элементов в сетке. В последнем примере этого руководства мы создадим макет, который полностью зависит от автоматического размещения.

Создание списка с помощью авторазмещения

Многие макеты, по сути, представляют собой наборы "карточек" - списки продуктов, галереи изображений и так далее. Сетка может очень легко создавать эти списки таким образом, чтобы они были отзывчивыми, без необходимости добавлять медиа-запросы. В следующем примере я комбинирую CSS Grid и Flexbox макеты, чтобы сделать простой макет списка продуктов.

Разметка моего списка-это неупорядоченный список элементов. Каждый элемент содержит заголовок, некоторый текст различной высоты и ссылку с призывом к действию.

<ul class="listing">
  <li>
    <h2>Item One</h2>
    <div class="body"><p>The content of this listing item goes here.</p></div>
    <div class="cta"><a href="">Call to action!</a></div>
  </li>
   <li>
     <h2>Item Two</h2>
     <div class="body"><p>The content of this listing item goes here.</p></div>
     <div class="cta"><a href="">Call to action!</a></div>
   </li>
   <li class="wide">
     <h2>Item Three</h2>
     <div class="body"><p>The content of this listing item goes here.</p> 
     <p>This one has more text than the other items.</p>
     <p>Quite a lot more</p>
     <p>Perhaps we could do something different with it?</p></div>
     <div class="cta"><a href="">Call to action!</a></div>
    </li>
    <li>
     <h2>Item Four</h2>
     <div class="body"><p>The content of this listing item goes here.</p></div>
     <div class="cta"><a href="">Call to action!</a></div>
    </li>
     <li>
     <h2>Item Five</h2>
     <div class="body"><p>The content of this listing item goes here.</p></div>
      <div class="cta"><a href="">Call to action!</a></div>
    </li>
</ul>

Мы собираемся создать сетку с гибким количеством гибких столбцов. Я хочу, чтобы они никогда не становились меньше 200 пикселей, а затем делили любое доступное оставшееся пространство поровну – так мы всегда получаем одинаковые по ширине дорожки столбцов. Мы достигаем этого с помощью функции  minmax() в нашей повторной нотации для определения размера трека.

.listing {
  list-style: none;
  margin: 2em;
  display: grid;
  grid-gap: 20px;
  grid-template-columns: repeat(auto-fill,minmax(200px, 1fr));
}

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

Затем я могу привести в порядок внутренние части ячеек, используя flexbox. Я установил для элемента списка display: flex and theи flex-direction для column. Затем я могу использовать margin auto для   .cta чтобы подтолкнуть этот элемент вниз к нижней части ячейки.

.listing li {
  border: 1px solid #ffe066;
  border-radius: 5px;
  display: flex;
  flex-direction: column;
}
.listing .cta {
  margin-top: auto;
  border-top: 1px solid #ffe066;
  padding: 10px;
  text-align: center;
}
.listing .body {
  padding: 10px;
}

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

Теперь все это выглядит более завершенным. Однако иногда у нас есть эти элементы, которые содержат больше контента, чем другие. Было бы неплохо, чтобы они охватывали два трека, и тогда они не будут такими высокими. У меня есть класс wide для большого элемента, и я добавляю правило grid-column-end со значением  span 2. Теперь, когда grid столкнется с этим элементом, он назначит ему два трека. В некоторых точках это означает, что мы получим разрыв в сетке – там, где нет места для размещения двухтрекового элемента.

The layout has gaps as there is not space to layout a two track item.

Я могу привести причину недостатка заполнения с помощью grid-auto-flow: dense  в грид ячейке. Будьте осторожны, когда делаете это, поскольку это действительно уводит элементы от их логического исходного порядка. Вы должны делать это только в том случае, если ваши элементы не имеют установленного порядка – и быть в курсе проблем порядка вкладок после источника, а не вашего переупорядоченного отображения.

.listing {
  list-style: none;
  margin: 2em;
  display: grid;
  grid-gap: 20px;
  grid-auto-flow: dense;
  grid-template-columns: repeat(auto-fill,minmax(200px, 1fr));
}
.listing .wide {
  grid-column-end: span 2;
}

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

Дальнейшие исследования

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

  • For inspiration see the Layout Labs from Jen Simmons, she has been creating layouts based on a range of sources.
  • For additional common layout patterns see Grid by Example, where there are many smaller examples of grid layout and also some larger UI patterns and full page layouts.