CSS Grid макет приложения в продакшене

CSS Grid макет приложения в продакшене

От автора: CSS Grid – одно из крупнейших улучшений в макетах, которое видел веб за долгое время. Наконец-то мы можем создавать нативные двумерные макеты в браузере. Это делает HTML короче, а CSS – надежнее. В этой статье мы хотим поделиться тем, как нам удалось реализовать в Grid CSS макет для нашего приложения, какие преимущества мы увидели и даже о том, как нам удалось реализовать поддержку IE11.

Начиная с основ

Наше приложение представляет собой UI для продавцов, управляющих своим бизнесом. Мы использовали классический макет holy grail, который состоит из:

App Bar: фиксированная высота 45px, вся ширина, не скролится вместе с контентом.

Menu: должно располагаться под app bar, иметь ширину 200px и занимать всю высоту, не должно скролиться вместе с контентом страницы.

Content: должен занимать оставшуюся ширину и высоту, должен прокручиваться.

Реализовать макет сверху в CSS Grid очень легко.

<div class="app"> <header></header> <aside></aside> <main></main>
</div> 
html, body { height: 100%; margin: 0;
} .app { height: 100%; display: grid; grid-template-rows: 45px 1fr; grid-template-columns: 200px 1fr;
} header { box-shadow: 0 2px 5px rgba(0, 0, 0, .16); /* stretch from first grid line to last grid line */ grid-column: 1/-1;
} aside { background-color: #213e48;
} 

Изучение новых свойств

Давайте разберем новые CSS свойства, которые мы использовали. Если вы их уже знаете, можете спокойно пропустить раздел «заставляем работать макет в IE11».

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

Теперь мы готовы определять макет. Он состоит из двух колонок и строк:

grid-template-colums: 200px 1fr; задает 2 колонки. Первая будет 200px шириной, а вторая будет занимать одну фракцию (fr) от оставшегося горизонтального пространства. Фракции работают по принципу значений flex-grow в Flexbox. Эти единицы представляют собой фракцию доступного пространства в grid-контейнере.

Похожим образом grid-template-rows: 45px 1fr; определяет нам 2 строки. Первая строка будет 45px в высоту, вторая будет занимать оставшееся вертикальное пространство.

В CSS Grid колонки и строки также называют grid-дорожками. Линии, окружающие дорожки, называются grid-линии. Grid-линиям автоматически присваиваются номер:

Grid-дорожки используются для определения колонок и строк. Grid-линии используются для размещения grid-элементов внутри grid.

По умолчанию CSS Grid автоматически размещает каждый элемент в одну grid-ячейку. Если необходимо, чтобы один grid-элемент занимал более одной ячейки – как наш App Bar, который должен занимать 2 ячейки по горизонтали – необходимо явно спозиционировать grid-элемент с помощью grid-column и/или grid-row.

Если посмотреть на изображение выше, мы можем определить grid-линии, которые должны растянуть App Bar.

/* start at grid line 1 and stretch to grid line 3 */
grid-column: 1/3;

Код сверху говорит, что App Bar начинается на первой grid-линии и тянется до grid-линии 3.

Заметьте, что в полном коде сверху мы говорим app bar растянуться до линии -1, а не 3. -1 всегда указывает на последнюю линию в grid. Так App Bar всегда будет занимать всю ширину вне зависимости от добавленных позже колонок.

Заметьте, что мы не явно помещаем AppBar на первую строку. Также мы неявно размещаем Menu и Content. CSS Grid автоматически делает это за нас.

Заставляем работать макет в IE11

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

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

К сожалению, реализация CSS Grid в IE10 – которая используется и в IE11 – не поддерживает автоматическое размещение:

«В реализации IE10 нет автоматического размещения. Это значит, что вам нужно все позиционировать, а не использовать автоматическое размещение grid. — Rachel Andrews»

Жаль! Нам нужен фолбек с явным размещением всего в grid с помощью grid-column и grid-row. У нас это будет хорошо работать, так как у нас всего пара элементов в grid. Если бы нам нужно было динамически заполнять grid элементами, мы бы не смогли сделать реализацию IE.

После работы autoprefixer свойство grid-column трансформируется в IE версию -ms-grid-column-start. По сравнению с grid-column оно поддерживает только начальное значение, как можно судить из имени. В IE необходимо явно определить количество колонок, на которые должен растягиваться grid-элемент с помощью свойства -ms-grid-column-span. См. пример кода ниже.

В IE11 мы заметили еще один глюк – по какой-то причине тег main не становится дочерним элементом grid. Как выход, можно вернуться к div с атрибутом role=»main», что сохраняет HTML5 семантику и позволяет разместить главный контейнер в grid в IE11.

Ниже представлен обновленный код.

Заметьте, что мы не проставляем префиксы вручную. Единственная часть для IE – мы растягиваем App Bar с помощью ms-grid-column-span:

<div class="app"> <header></header> <aside></aside> <div role="main"></div>
</div> 
html, body { height: 100%; margin: 0;
} .app { height: 100%; display: grid; grid-template-rows: 45px 1fr; grid-template-columns: 200px 1fr;
} header { box-shadow: 0 2px 5px rgba(0, 0, 0, .16); /* stretch from first grid line to last grid line */ grid-column: 1/-1; -ms-grid-column-span: 2; grid-row: 1;
} aside { background-color: #213e48; grid-row: 2; grid-column: 1;
} [role=main] { grid-row: 2; grid-column: 2;
} 

Еще раз взглянем на структуру HTML. Разметка полностью семантическая. Никаких ненужных оберток div.

Мы создали полностью функциональный макет приложения, совместимый с IE11. Было легко, неправда ли? Давайте шагнем дальше.

Адаптивный Nav

Чтобы предоставить пользователям планшетов больше пространства по горизонтали для контента, нам нужно уменьшить nav до 64px, когда экран становится меньше 992px по ширине.

Как сделать так, чтобы левая колонка была 64px или 200px в зависимости от ширины экрана? Его ширина автоматически подстраивается под содержимое, а контент адаптивен (nav bar).

Это хорошо разделяет проблемы. Nav bar завязан на адаптивное изменение своей ширины. Макет приложения завязан на том, что дает nav bar столько места, сколько необходимо.

Измененные CSS правила:

.app { height: 100%; display: grid; grid-template-rows: 45px 1fr; /* changing the width of the first column from 200px to auto */ grid-template-columns: auto 1fr;
}
aside { background-color: #213e48; grid-row: 2; grid-column: 1; /* defining the width on the grid child, not the grid container */ width: 200px;
}
@media (max-width: 992px) { aside { width: 64px; }
} 

Возможность так легко реализовать адаптивный nab bar снесла мне крышу. Никакого абсолютного позиционирования. Никакого calc(). Просто макет.

Уведомления

Осталась лишь одна вещь в существующем макете. Глобальные уведомления толкают контент под ними вниз.

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

Реализация старыми методами с абсолютным позиционированием была бы кошмаром. В CSS Grid это глоток свежего воздуха.

Нам лишь нужно:

Добавить еще одну auto sized строку над строкой хедера

Поднять все значения grid-row на единицу

Добавить контейнер для уведомлений

Полный код:

<div class="app"> <div class="global-notification"> Cookie consent notice </div> <header></header> <aside></aside> <div role="main"></div>
</div> 
html, body { height: 100%; margin: 0; font-family: sans-serif;
} .app { height: 100%; display: grid; grid-template-rows: auto 45px 1fr; grid-template-columns: auto 1fr;
} header { box-shadow: 0 2px 5px rgba(0, 0, 0, .16); /* stretch from first grid line to last grid line */ grid-column: 1/-1; -ms-grid-column-span: 2; grid-row: 2;
} aside { background-color: #213e48; grid-row: 3; grid-column: 1; width: 200px;
}
@media (max-width: 992px) { aside { width: 64px; }
} [role=main] { grid-row: 3; grid-column: 2;
} .global-notification { grid-column: 1/-1; -ms-grid-column-span: 2; grid-row: 1; color: white; background-color: #00749e; padding: 24px;
} 

В сумме это всего лишь 45 строк CSS и 9 строк HTML.

Заключение

CSS Grid – удивителен и готов к продакшену. Не нужно ждать, пока все перестанут пользоваться IE11, чтобы использовать CSS Grid для базовых макетов. Возможно, вам и не нужны фолбеки на Flexbox и float макеты в IE11, как в этой статье.

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

Автор: Philipp Sporrer

Источник: https://techblog.commercetools.com/

Редакция: Команда webformyself.