Що я дізнався про макеті CSS Grid

38

Від автора: стаття нашого гостя, Олівера Вільямса. Олівер вже давно працює з макетом CSS Grid і дечому навчився за цей час. В цій статті він розповість нам про концепції, які він вивчив. Мені подобається сама ідея вивчення макета шляхом розбиття його на невеликі шматки. Так простіше вивчати щось велике.

CSS Grid з’явиться в браузерах на початку 2017 року. А поки новий рік ще не настав для роботи з таким макетом необхідно вручну включати сітку в браузері. У нічний збірці Firefox сітка активована за замовчуванням. Найкраще сітка поки що реалізована в Chrome Canary. Однак у Firefox є дуже цінне доповнення CSS Grid Inspector, яке показує лінії сітки. На даний момент це єдиний інструмент такого роду.

Для активації сітки в Chrome необхідно перейти за адресою «chrome://flags», знайти і активувати поле «Enable experimental Web Platform features». В IE і Edge є застаріла реалізація сіток, що відрізняється від поточної специфікації, з-за чого не рекомендується експериментувати з нею.

Не можна створювати елементи сітки в формі блоків тетрису

Ви самі можете досить швидко реалізувати такий макет.

Сітку придумали, щоб використовувати разом з flexbox, а не замість нього

Сітка і flexbox дуже схожі. Ви могли бачити, як деякі використовують flexbox для створення мережевих систем, але flexbox замислювався не для цього. Раджу прочитати статтю Джейка Арчібальда не використовуйте flexbox для повного макетування сторінок.

Варто ось про що подумати:

flexbox створений для макетування в одній площині (ряди або колонки);

CSS Grid створений для макетування в двох площинах.

Або як висловилася Рейчел Ендрюс: «Flexbox спочатку замислювався для макетування елементів в одному вимірі. Рядки АБО колонки. Grid спроектований для макетування в двох вимірах. Рядах І колонках.»

Функціонал обох методів можна комбінувати. Осередки сітки можна робити флекс-контейнерами, а флекс-елементи можна перетворювати в сітки.

Розберемо один хороший приклад. Нам необхідно центрувати по вертикалі текст всередині комірки сітки і зробити так, щоб фон покривав всю клітинку цілком, будь то колір, градієнт або зображення. Можна взяти властивість align-items зі значенням center, але тоді фон не буде покривати всю площу елемента. За замовчуванням властивість align-items приймає значення stretch. Якщо змінити значення, фон більше не буде заповнювати весь простір. Давайте залишимо значення stretch, а комірку сітки перетворимо в флекс-контейнер.

.grid {
align-items: stretch;
}
.griditem {
display: flex;
align-items: center;
}

Негативна нумерація сторінок – дуже корисна штука

Уявіть CSS Grid фреймворк з сіткою в 12 колонок. На маленьких екранах ми не зменшуємо число колонок, а змушуємо контент займати всі 12 колонок разом, тим самим створюючи відчуття, що використовується всього одна колонка на всю ширину екрану.

Те ж саме можна провернути і grid:

/* Для маленьких екранів */
.span4, .span6, .spanAll {
grid-column-end: span 12;
}
/* Для великих екранів */
@media (min-width: 650px) {
.span4 {
grid-column-end: span 4;
}
.span6 {
grid-column-end: span 6;
}
}

Метод цілком нормальний. Проте в CSS grid точно так само можна легко змінювати кількість колонок. Задавши значення -1, ви завжди будете знати, що контент займає всю вільну область.

/* Для маленьких екранів */
.span4, .span6, .spanAll {
grid-column-end: -1;
}

Для великих екранів вам може знадобитися більше дванадцяти колонок. Для мобільних пристроїв – десь в районі від однієї до чотирьох. Значення grid-template-columns легко можна змінювати за допомогою медіа запиту.

.grid {
grid-template-columns: 1fr 1fr;
}
@media (min-width: 700px) {
.grid {
grid-template-columns: repeat(12, 1fr);
}
}

Бувають такі елементи, які необхідно розтягнути на всю ширину екрану на будь-якому пристрої. Це можуть бути хедер, футер або якісь банери. Для маленьких екранів можна написати:

.wide {
grid-column: 1 / 3; /* починаємо на 1, закінчуємо на 3 */
}

Однак після виконання медіа запиту ці елементи будуть займати лише перші дві колонки з 12. Можна було б додати нове значення 13 для grid-column-end в цьому запиті, але є метод куди простіше. Просто встановіть кінцеве значення -1, і елемент розтягнеться на всі колонки. Приклад:

.wide, .hero, .header, .footer {
grid-column: 1 / -1;
}

Області сітки ставлять неявні імена ліній

Є два способи розміщення контенту у сітці – за іменами областей шаблону сітки і за номерами ліній. Однак обидва методи можна використовувати в одній сітці. Можна використовувати неявні імена ліній, які створюються кожного разу, коли ви задаєте нову область.

.grid {
grid-template-areas: «main main sidebar sidebar»;
}

Код вище, сам того не бажаючи, створив чотири іменовані рядки: main-start, main-end, sidebar-start і sidebar-end.

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

Існує ще один спосіб оголошення областей в сітці

Області сітки ставлять імена лініях, так само і імена ліній можуть створювати нові області в сітці. Синтаксис оголошення області:

.grid {
grid-template-areas:
«header header header»
«main main sidebar»
«footer footer footer»;
}

Синтаксис може сильно розростися, якщо у вашому дизайні багато порожніх областей. Ви можете навіть не здогадуватися, що існує ще один спосіб створення областей в сітці. Ми можемо привласнювати абсолютно будь-які імена лініям сітки, але якщо дотримуватися шаблону [name-start] і [name-end], можна створювати нові області. Приклад:

.grid {
display: grid;
grid-template-columns: 20px 100px [main-start] 1fr [main-end] 100px 20px;
grid-template-rows: 100px [main-start] 100px [main-end] 100px;
}
.griditem1 {
background-color: red;
grid-area: main;
}

Швидше за все, ви не будете створювати макет цілої сторінки за допомогою такого методу. Однак якщо ви хочете поєднати два методу розміщення елементів, grid-area і нумерацію ліній, просто знати про нього не завадить.

Створюйте блоки однакових розмірів за допомогою vmin

CSS grid дозволяє використовувати будь-які одиниці вимірювання для визначення розмірів рядків і колонок. Хочете, щоб колонки були однакові і в той же час адаптивні? Якщо ви хочете, щоб контент змінювався разом з контейнером, можете скористатися одиницями вимірювання vw і vh.

.grid {
grid-template-columns: repeat(5, 20vw);
grid-template-rows: repeat(5, 20vh);
}

Метод відмінно спрацює на десктопі і ноутбуках, однак на мобільних пристроях, де висота перевищує ширину екрана, контент не буде вміщуватися, тим самим створюючи горизонтальну смугу прокручування. Дадлі Сторі нещодавно написав статтю про корисність мало відомих одиниць вимірювання vmin. Одиниці виміру обчислюються у вигляді відсотка від ширини екрана в портретній орієнтації і висоти в альбомній орієнтації.

.gridcontainer {
display: grid;
width: 100vw;
height: 100vh;
justify-content: center;
align-content: center;
grid-template-columns: repeat(5, 20vmin);
grid-template-rows: repeat(5, 20vmin);
}

Ми отримали однакові блоки, адаптуються під будь-який розмір екрану.

Абсолютне позиціонування

При абсолютному позиціонування осередки сітки, її можна встановити не щодо свого контейнера (тобто всієї сітки), а щодо стартових і кінцевих ліній заданої колонки і рядка. Властивість position: absolute видаляє елемент із структури документи (елемент ігнорується іншими елементами). Властивість position: absolute дуже корисно в тих випадках, коли необхідно накласти контент поверх сітки, не порушуючи алгоритм авторозміщення. Автоматичне розміщення елементів у сітці робить так, щоб клітинки не налягали один на одного. Зворотне можливо тільки, якщо прописати grid-column-start та grid-row-start для всіх клітинок.

Видаліть position: absolute; у блоку div у прикладі нижче і подумайте, скільки разів вам довелося б оголошувати властивості grid-column і grid-row вручну!

Сортування працює не так, як ви могли думати

Якщо ви працювали з властивістю order під flexbox, то ви вже це знаєте. У всіх елементів, сітки за промовчанням установлено значення order: 0. Тобто якщо вказати елементу order: 1, то він не стане першим.

Для зсуву елементів вліво можна використовувати негативні значення.

Ліміт функції minmax

Хочете, щоб колонки порівну ділили вільний простір, поки вони не досягнуть максимальної ширини? Ви могли відразу ж подумати про функції minmax():

.grid {
display: grid;
grid-template-columns: repeat(3, minmax(1fr, 300px));
}

На жаль, код вище не спрацює. Якщо максимальне значення менше мінімального, код буде проігноровано. У функції minmax() можна використовувати одиниці виміру fr у мінімальному значенні. Значення auto у властивостях grid-template-columns та grid-template-rows розтягне рядок або колонку на весь контейнер.

Можна вказати max-width контенту:

.grid {
display: grid;
grid-template-columns: repeat(3, auto);
}
.item {
max-width: 300px;
}

На таку поведінку minmax() можуть бути вагомі причини та певні способи застосування, про яких я не думав. Навіть так, я написав пост на сайті Medium Що я ненавиджу в Grid.

Все стає набагато легше, якщо іменувати лінії в сітці

Це можна робити різними способами. Якщо ви любите стукати по клавіатурі, можете давати лініях кілька імен.

.grid {
grid-template-columns: [col1-start] 1fr [col1-end col2-start] 1fr [col2-end];
}

Найпростіший спосіб іменування – автоматична нумерація. Не потрібно набирати [col2], можна просто написати col і номер.

.griditem1 {
grid-column-start: col 2;
}

З допомогою ключового слова span ми можемо забути про нумерацію ліній і почати думати про те, з якої і по яку колонки пустити контент.

.grid {
grid-template-columns: repeat(4, [col] 100px);
}
.griditem1 {
grid-column: col 2 / span 2;
}

З одиницями вимірювання fr нічого не потрібно вважати

Скажімо, нам потрібно розбити сітку на чотири рівних колонки. Це легко зробити за допомогою відсотків. Потрібно всього лише написати grid-template-columns: 25% 25% 25% 25%.

А що буде, якщо ми захочемо скористатися властивістю grid-gap? Grid-gap: 10px. У нас три роздільника між колонками, тобто ширина стане 100% + 30px. З’явиться горизонтальна прокрутка, а частина контенту піде за межі екрану праворуч. Тут можна було б використовувати функцію calc(), але з одиницями fr все набагато простіше: grid-template-columns: 1fr 1fr 1fr 1fr.

Що я ненавиджу в сітках

Не можна змусити алгоритм автоматичного розміщення залишити деякі колонки або рядка порожніми.

За допомогою властивості grid-gap дуже легко контролювати відступи в контенті. Для поділу колонок і рядків можна використовувати окремі властивості grid-row-gap і grid-column-gap, але у них повинні бути однакові значення. Якщо ми хочемо зробити відступ між першою і другою рядком 10 пікселів, а між другим і третім рядком у 50px, нам нічого не залишається, крім як створити кілька додаткових рядків і залишити їх порожніми.

Ви могли бачити, як в синтаксисі grid-template-area використовуються точки:

grid-template-rows:
«header header header»
«main main main»
«. . .»
«secondary secondary secondary»
«footer footer footer»;

З їх допомогою можна дуже просто змусити алгоритм автоматичного розміщення не вставляти в ці галузі елементи. На жаль, це не працює. Синтаксис всього лише говорить, що ми не хочемо включати третій рядок у іменовану область сітки. Але алгоритм все одно зробить по-своєму.

Кілька порад по дизайну: необов’язково мати 12 колонок (а колонки необов’язково повинні бути одного розміру)

За замовчуванням у веб-дизайні використовується 12 колонок. Bootstrap використовує 12 колонок, як і інші фреймворки. І це неспроста: 12 ділиться одночасно і на 3, і на 4, що дає більшу гнучкість при розміщенні контенту на сторінці. Контент можна розділити порівну на 12, 6, 4, 3 частини або навпіл.

Деякі люблять працювати так, як вже звикли, використовуючи одну і ту ж сітку у всіх проектах. Однак немає потреби робити колонок більше, ніж вам потрібно. Сітку потрібно будувати так, щоб вона підходила під контент і макет, а не робити один варіант для всього.

Подивіться приклади на Gridset. Gridset – корисний інструмент для створення сіток. Але після виходу нативного модуля сіток для CSS цей інструмент вам більше не знадобиться. Там можна знайти декілька чудових прикладів сіток.

Что я узнал о макете CSS Grid

Я взяв на себе сміливість переробити один з макетів за допомогою CSS grid: