Создаем расписание конференции с помощью CSS Grid

Я заново оценил возможности CSS Grid, когда создавал адаптивный шаблон для расписания конференции. В результате появилось несколько интересных способов использования CSS Grid. К тому же я разобрался с некоторыми особенностями грида, с которыми сталкиваешься не каждый день.

Определяем требования к макету

Я решил создать этот макет благодаря WordCamp. В рамках проекта проводятся сотни конференций, посвященных WordPress. Конференции бывают разных масштабов и форматов, но все они используют один инструмент для создания расписания.

Определяем требования к макету

В результате получился этот макет.

Я знал недостатки существующего макета HTML-таблицы. Чтобы усовершенствовать его, я составил список требований к новому шаблону:

  • Дизайн легко настроить с помощью CSS

Сайты WordCamp позволяют задавать стили только с помощью CSS.

  • Макет может быть сгенерирован автоматически из контента CMS

Приступаем к работе: надежный HTML

<div> верхнего уровня будет иметь класс .schedule, а также он будет родительским элементом для Grid. У каждого времени начала конференции есть свой заголовок. За ним следует перечисление мероприятий (сессий), которые начинаются в это время.

HTML

<h2>Conference Schedule</h2>
<div class="schedule">

  <h3 class="time-slot">8:00am</h3>
  <div class="session session-1 track-1">
    <h4 class="session-title"><a href="#">Session Title</a></h4>
    <span class="session-time">8:00am - 9:00am</span>
    <span class="session-track">Track 1</span>
    <span class="session-presenter">Presenter Name</span>
  </div>
  <!-- Cессии 2, 3, 4 -->

  <h3 class="time-slot">9:00am</h3>
  <div class="session session-5 track-1">
    <h4 class="session-title"><a href="#">Session Title</a></h4>
    <span class="session-time">9:00am - 10:00am</span>
    <span class="session-track">Track 1</span>
    <span class="session-presenter">Presenter Name</span>
  </div>
  <!-- Сессии 6, 7, 8 -->

  <!—и так далее... -->

</div> <!-- конец .schedule -->

Макет для мобильных устройств и резервный вариант сетки

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

Вот как выглядит мой макет в цвете:

Макет для мобильных устройств и резервный вариант сетки

Добавляем макет сетки

Переходим к практической части реализации CSS Grid. Одна строка grid – это 1% от высоты диаграммы. Поэтому столбец занимает столько же строк, сколько и процент, который он представляет.

CSS

.chart {
  display: grid;
  grid-template-rows: repeat(100, 1fr); /* 1 строка = 1%! */
}

.fifty-percent-bar {
  grid-row: 51 / 101; /* 101 - 51 = 50 => 50% */
}

Благодаря этому я понял, что grid идеально подходит для любого макета, предназначенного для отображения часто изменяющихся величин. Например, времени. В данном случае мы будем использовать приращение  в 30 минут. Только избегайте ошибки в Chrome, которая ограничивает макеты сетки 1000 строк.

В первом варианте макета для размещения списка сессий я использовал такой же синтаксис, что и в гистограмме Робина. А также немного простой математики.

Мы используем восемь рядов, потому что есть восемь 30-минутных увеличений периодов между 8:00 и 12:00. Помните, что номера строк неявного грида начинаются с единицы (а не с 0). Поэтому строки нумеруются с 1 по 9.

Добавляем макет сетки

Элементарная версия расписания с одним столбцом и пронумерованными строками сетки.

CSS

.schedule {
  display: grid;
  grid-template-rows: repeat(8, 1fr);
}

.session-1 {
  grid-row: 1 / 3; /* 8:00 – 9:00, 3 - 1 = 2 30-минутных увеличения */
}

.session-2 {
  grid-row: 3 / 6; /* 9:00 - 10:30, 6-3 = 3 30-минутных увеличения */
}

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

Добавляем макет сетки - 2

Становится гораздо проще размещать сессии, если использовать строки сетки с названиями.

CSS

.schedule {
  display: grid;
  grid-template-rows:
    [time-0800] 1fr
    [time-0830] 1fr
    [time-0900] 1fr
    [time-0930] 1fr;
    /* и так далее...
        */
}

.session-1 {
  grid-row: time-0800 / time-0900;
}

.session-2 {
  grid-row: time-0900 / time-1030;
}

Также можно генерировать названия строк сетки и стилей макета с помощью информации, которая есть в WordPress. Установите в сетке время начала и окончания, и готово!

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

CSS

.schedule { /* продолжается */
  grid-template-columns:
    [times] 4em
    [track-1-start] 1fr
    [track-1-end track-2-start] 1fr
    [track-2-end track-3-start] 1fr
    [track-3-end track-4-start] 1fr
    [track-4-end];
}

Определив строки сетки, основанные на времени и темах, можно размещать любую нужную сессию, просто зная время и место!

CSS

.session-8 {
  grid-row: time-1030 / time-1100;
  grid-column: track-2-start / track-3-end;

Собрав все это вместе, мы получаем длинный, но вполне читабельный код:

CSS

@media screen and (min-width: 700px) {
  .schedule {
    display: grid;
    grid-gap: 1em;
    grid-template-rows:
      [tracks] auto /* Предвосхищаем! */
      [time-0800] 1fr
      [time-0830] 1fr
      [time-0900] 1fr
      [time-0930] 1fr
      [time-1000] 1fr
      [time-1030] 1fr
      [time-1100] 1fr
      [time-1130] 1fr
      [time-1200] 1fr;
    grid-template-columns:
      [times] 4em
      [track-1-start] 1fr
      [track-1-end track-2-start] 1fr
      [track-2-end track-3-start] 1fr
      [track-3-end track-4-start] 1fr
      [track-4-end];
  }

  .time-slot {
    grid-column: times;
  }
}

HTML

<div class="session session-1 track-1" style="grid-column: track-1; grid-row: time-0800 / time-0900;">
  <!-- детали -->
</div>
<div class="session session-2 track-2" style="grid-column: track-2; grid-row: time-0800 / time-0900">
  <!-- детали -->
</div>
<!—и так далее... -->

Небольшое примечание: использование единиц измерения fr и автоматического значения высоты строк

Стоит отметить одну деталь – применение единиц измерения fr для определения высоты строк. При использовании значения 1fr все строки получают одинаковую высоту. Эта высота определяется содержанием самой высокой строки в расписании.

Небольшое примечание: использование единиц измерения fr и автоматического значения высоты строк

Чтобы понять это, я был вынужден прочитать спецификацию W3C для fr.

Это создает макет расписания, в котором высота пропорциональна времени. Но это также может сделать макет очень высоким.

Небольшое примечание: использование единиц измерения fr и автоматического значения высоты строк - 2

Использование 1fr создает строки одинаковой высоты, определяемой самой высокой строкой в ​​сетке.

Например, если в сетке расписания есть 15-минутные увеличения периодов времени с 7:00 до 18:00, это в общей сложности 48 строк сетки. В этом случае вы захотите использовать для высоты строки значение auto. Потому что расписание будет намного компактнее с высотой каждой строки сетки, определяемой ее содержимым.

Использование значения auto приводит к тому, что высота каждой строки равна высоте ее содержимого.

Добавляем удобные названия тем

Пришло время добавить названия тем, которые выглядят как заголовки в верхней части каждого столбца. Я решил скрыть «заголовки» от вспомогательных технологий с помощью aria-hidden = «true».

Названия тем будут располагаться в первой строке сетки с удобным названием «tracks».

HTML

<span class="track-slot" aria-hidden="true" style="grid-column: track-1;">Track 1</span>
<span class="track-slot" aria-hidden="true" style="grid-column: track-2;">Track 2</span>
<span class="track-slot" aria-hidden="true" style="grid-column: track-3;">Track 3</span>
<span class="track-slot" aria-hidden="true" style="grid-column: track-4;">Track 4</span>

CSS

.track-slot {
  display: none; /* виден только в Grid layout */
}

@supports( display:grid ) {
  @media screen and (min-width:700px) {    
    .track-slot {
      grid-row: tracks;
      display: block;
      position: sticky;
      top: 0;
      z-index: 1000;
      background-color: rgba(255,255,255,.9);
    }
  }
}

Результат

Так выглядит проделанная работа

Это только начало

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