Зв'язок Grid позиціонування з іншими методами позиціонування

  1. Grid і flexbox
  2. Одномірне vs Двовимірний позиціонування
  3. Ті ж яйця, вид в профіль: той же макет, але з CSS грід
  4. Що важливіше: контент або макет?
  5. вирівнювання блоків
  6. Тим часом в паралельному всесвіті: вирівнювання в CSS грід
  7. Одиниця fr і flex-basis
  8. Заповнити форму грід-треків
  9. Змінна кількість треків
  10. Гріди і абсолютно позиційований елементи
  11. Грід-контейнер як контейнерний блок
  12. Грід-контейнер в якості батьківського елемента
  13. А що якщо батьківський елемент - це грід-область?
  14. Грід і display: contents

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

Grid і flexbox

Основна відмінність між CSS Grid Layout і CSS Flexbox Layout в тому, що flexbox призначений для позиціонування елементів в одному напрямку, тобто, або в рядку, або в колонці. Grid же був розроблений для позиціонування елементів в двовимірної системі, тобто, для одночасного позиціонування і в рядку, і в колонці. Однак, в двох специфікаціях є деякі спільні риси, і якщо ви вже навчилися приборкувати flexbox, ви побачите подібності, які допоможуть вам розібратися і з Grid.

Одномірне vs Двовимірний позиціонування

Простий приклад допоможе нам продемонструвати різницю між одно- і двовимірним позиціонуванням.

В пером прикладі ми скористаємося flexbox для того, щоб розмістити кілька блоків. Припустимо, що у нас є п'ять дочірніх елементів в контейнері, задамо їм значення flex-властивостей таким чином, щоб їх розмір збільшувався і зменшувався, починаючи з базового в 200px.

Також встановимо властивість flex-wrap в значення wrap. Це призведе до того, що якщо вільного простору в нашому контейнері буде не вистачати для розміщення елемента в 200px, наші елементи спокійно перейдуть на новий рядок.

* {Box-sizing: border-box;} .wrapper {border: 2px solid # f76707; border-radius: 5px; background-color: # fff4e6; } .Wrapper> div {border: 2px solid # ffa94d; border-radius: 5px; background-color: # ffd8a8; padding: 1em; color: # d9480f; } <Div class = "wrapper"> <div> One </ div> <div> Two </ div> <div> Three </ div> <div> Four </ div> <div> Five </ div> < / div> .wrapper {display: flex; flex-wrap: wrap; } .Wrapper> div {flex: 1 + 1 200px; }

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

Загальне питання полягає в тому, як змусити наші перебігли елементи вирівняти за елементами зверху. Якраз в цьому випадку і потрібен метод розміщення елементів в двовимірної системі: потрібно вирівнювання і по рядку, і по колонці, а для цього на допомогу поспішає Grid.

Ті ж яйця, вид в профіль: той же макет, але з CSS грід

У прикладі нижче ми створюємо той же самий макет, але використовуючи гріди. На цей раз у нас три треки-колонки шириною в 1fr. І при цьому нам не потрібно задавати будь-які властивості дочірнім елементам, тому що вони самостійно займають по одній клітинці створеного гріда. Як Ви бачите, наші елементи лежать в жорсткій сітці і вирівнюються і по рядку, і по колонці. Оскільки у нас п'ять елементів, в результаті ми отримуємо вільну позицію в кінці другого рядка.

* {Box-sizing: border-box;} .wrapper {border: 2px solid # f76707; border-radius: 5px; background-color: # fff4e6; } .Wrapper> div {border: 2px solid # ffa94d; border-radius: 5px; background-color: # ffd8a8; padding: 1em; color: # d9480f; } <Div class = "wrapper"> <div> One </ div> <div> Two </ div> <div> Three </ div> <div> Four </ div> <div> Five </ div> < / div> .wrapper {display: grid; grid-template-columns: repeat (3, 1fr); }

Якщо Ви вагаєтеся, що вибрати - flexbox або грід, задайте собі просте запитання:

  • мені потрібно управляти розміщенням елементів в рядку або в колонці - окей, потрібен flexbox
  • мені потрібно управляти розміщенням елементів і в рядку, і в колонці - окей, потрібен грід

Що важливіше: контент або макет?

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

Грід працює, виходячи з макета. Коли Ви використовуєте CSS Grid Layout, Ви створюєте структуру і потім розміщуєте елементи саме в цій структурі або ж дозволяєте правилам авто-розміщення розмістити елементи в грід-осередках відповідно до жорстко заданої сіткою. Звичайно, існує можливість створювати треки, подстраивающиеся під розмір контенту, але при цьому вони також змінюють саму структуру.

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

вирівнювання блоків

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

Властивості вирівнювання з специфікації flexbox були додані в нову специфікацію, названу Box Alignment Level 3 . А це означає, що вони можуть використовуватися і в інших специфікаціях, в тому числі і в Grid Layout.

Далі в нашому керівництві ми докладно розглянемо вирівнювання блоків Box Alignment і то, як воно працює в Grid Layout, а тут давайте розглянемо два простих прикладу, і порівняємо flexbox і гріди.

У першому прикладі, що використовує flexbox, у нас є контейнер з трьома елементами. Для блоку-обгортки wrapper встановлено властивість min-height , І воно задає висоту flex-контейнера. Ми встановили властивість align-items flex-контейнера в значення flex-end, тому елементи вирівнюються по кінця flex-контейнера. Ми також встановили значення властивості align-self для box1 таким чином, що воно буде перезаписано поведінка за умовчанням і змусить наш блок розтягнуться на всю висоту контейнера. Для box2 властивість align-self встановлено таким чином, що блок перестрибне в початок flex-контейнера.

* {Box-sizing: border-box;} .wrapper {border: 2px solid # f76707; border-radius: 5px; background-color: # fff4e6; } .Wrapper> div {border: 2px solid # ffa94d; border-radius: 5px; background-color: # ffd8a8; padding: 1em; color: # d9480f; } <Div class = "wrapper"> <div class = "box1"> One </ div> <div class = "box2"> Two </ div> <div class = "box3"> Three </ div> </ div> .wrapper {display: flex; align-items: flex-end; min-height: 200px; } .Box1 {align-self: stretch; } .Box2 {align-self: flex-start; }

Тим часом в паралельному всесвіті: вирівнювання в CSS грід

Другий приклад використовує грід, щоб створити той же самий макет, і на цей раз ми розглянемо те, як властивості вирівнювання блоків застосовуються до грід. Замість flex-start і flex-end ми задаємо start і end. У випадку з макетом на грідах ми вирівнюємо елементи всередині їх грід-області, в даному прикладі - це одна єдина грід-осередок, але в цілому грід-область може складатися з декількох грід-осередків.

* {Box-sizing: border-box;} .wrapper {border: 2px solid # f76707; border-radius: 5px; background-color: # fff4e6; } .Wrapper> div {border: 2px solid # ffa94d; border-radius: 5px; background-color: # ffd8a8; padding: 1em; color: # d9480f; } <Div class = "wrapper"> <div class = "box1"> One </ div> <div class = "box2"> Two </ div> <div class = "box3"> Three </ div> </ div> .wrapper {display: grid; grid-template-columns: repeat (3,1fr); align-items: end; grid-auto-rows: 200px; } .Box1 {align-self: stretch; } .Box2 {align-self: start; }

Одиниця fr і flex-basis

Ми вже бачили, як працює одиниця fr в разі пропорційного розподілу доступного простору між грід-треками в грід-контейнері. При комбінуванні fr з функцією minmax () ми отримуємо поведінку, дуже схоже на властивість flex в flexbox - і при цьому як і раніше можемо створювати макет в двовимірної системі.

Якщо повернутися до прикладу, що демонструє різницю між одно-і двовимірним позиціонування, можна побачити, що існує також і відмінність у самому способі того, як дві техніки працюють з чуйними макетами. З макетом на flex, якщо ми зменшуємо або збільшуємо розмір вікна, flexbox акуратно перерозподіляє кількість елементів в кожному рядку відповідно до доступним простором. Так, якщо у нас достатньо місця, щоб розмістити всі п'ять наших елементів в одному рядку, вони і будуть розміщені в одному рядку. Якщо ж контейнер вузький, то в рядку у нас буде місце тільки для одного елемента.

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

Заповнити форму грід-треків

Можна створити ефект, схожий на поведінку flexbox, і при цьому як і раніше тримати контент в жорсткій сітці з рядків і колонок, якщо задати структуру треків, використовуючи repeat-нотацію і властивості auto-fill і auto-fit.

У прикладі нижче ми використовуємо ключове слово auto-fill замість цілого числа в repeat-нотації і задаємо структуру треків розміром в 200 пікселів. Це означає, що грід створить стільки треків-колонок розміром в 200 пікселів, скільки їх може розміститися в контейнері.

* {Box-sizing: border-box;} .wrapper {border: 2px solid # f76707; border-radius: 5px; background-color: # fff4e6; } .Wrapper> div {border: 2px solid # ffa94d; border-radius: 5px; background-color: # ffd8a8; padding: 1em; color: # d9480f; } <Div class = "wrapper"> <div> One </ div> <div> Two </ div> <div> Three </ div> </ div> .wrapper {display: grid; grid-template-columns: repeat (auto-fill, 200px); }

Змінна кількість треків

Давайте згадаємо приклад з flexbox, коли елементи, розмір яких більше 200 пікселів, переходять на новий рядок. Той же самий ефект в грідах ми можемо отримати комбінуючи auto-fill і функцію minmax () . У прикладі нижче ми створюємо автозаповнення треки за допомогою minmax. Ми хочемо, щоб треки були як мінімум 200 пікселів в ширину, це наше мінімальне значення, а для максимального задамо 1fr. В процесі, коли браузер обчислює, скільки блоків в 200 пікселів може розміститися в контейнері - при цьому з огляду на грід-зазори - він розцінює максимум 1fr як інструкцію розподілити вільний простір між цими блоками.

* {Box-sizing: border-box;} .wrapper {border: 2px solid # f76707; border-radius: 5px; background-color: # fff4e6; } .Wrapper> div {border: 2px solid # ffa94d; border-radius: 5px; background-color: # ffd8a8; padding: 1em; color: # d9480f; } <Div class = "wrapper"> <div> One </ div> <div> Two </ div> <div> Three </ div> </ div> .wrapper {display: grid; grid-template-columns: repeat (auto-fill, minmax (200px, 1fr)); }

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

Гріди і абсолютно позиційований елементи

Грід взаємодіє з абсолютно позиціонувати елементами, що аж ніяк не марно, якщо Ви хочете розмістити елемент всередині гріда або грід-області. У специфікації описано поведінку гріда і тоді, коли грід-контейнер є контейнерним блоком (containing block) і тоді, коли грід-контейнер - батьківський елемент для абсолютно позиціонованого елемента.

Грід-контейнер як контейнерний блок

Для того, щоб перетворити грід-контейнер в контейнерний блок Вам потрібно додати йому властивість position зі значенням relative. Якщо після цього поставити якомусь грід-елементу position: absolute, грід-контейнер стане контейнерним блоком для даного елемента.

У прикладі нижче у нас є блок-обгортка з чотирма дочірніми елементами. Третій елемент абсолютно позиціонується і одночасно розміщений в гріді за допомогою прив'язки до грід-лініях. У грід-контейнера position: relative, тому він стає контекстом позиціонування для нашого третього елемента.

* {Box-sizing: border-box;} .wrapper {border: 2px solid # f76707; border-radius: 5px; background-color: # fff4e6; } .Wrapper> div {border: 2px solid # ffa94d; border-radius: 5px; background-color: # ffd8a8; padding: 1em; color: # d9480f; } <Div class = "wrapper"> <div class = "box1"> One </ div> <div class = "box2"> Two </ div> <div class = "box3"> Цей блок абсолютно позиціонується. У нашому прикладі грід-контейнер є контейнерним блоком, тому значення зсуву абсолютного позиціонування відраховуються від зовнішнього краю тієї області, в якій розміщений елемент. </ Div> <div class = "box4"> Four </ div> </ div> .wrapper {display: grid; grid-template-columns: repeat (4,1fr); grid-auto-rows: 200px; grid-gap: 20px; position: relative; } .Box3 {grid-column-start: 2; grid-column-end: 4; grid-row-start: 1; grid-row-end: 3; position: absolute; top: 40px; left: 40px; }

Ви бачите, що наш елемент займає область від колоночной грід-лінії 2 до колоночной грід-лінії 4 і починається після малої лінії 1. За допомогою властивостей left і top ми зрушуємо його щодо цієї області. У той же час, він вилучається з потоку так само, як і будь-який інший елемент з абсолютним позиціонуванням, тому правила авторозміщення тепер поміщають інші елементи на його місце. Абсолютне позиціонування нашого елемент також не приводить до появи нового рядка.

Спробуйте удалітьposition: absolute з правил для .box3, і побачите, як він розміщувався б без абсолютного позиціонування.

Грід-контейнер в якості батьківського елемента

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

Ще раз: наш елемент більше не займає простір в грід-макеті і не впливає на те, як розташовуються інші елементи при авторозміщення.

А що якщо батьківський елемент - це грід-область?

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

Задаємо .box3 властивість position в значенні relative і потім переміщаємо наш під-елемент за допомогою властивостей зсуву. В даному випадку контекстом позиціонування є грід-область.

* {Box-sizing: border-box;} .wrapper {border: 2px solid # f76707; border-radius: 5px; background-color: # fff4e6; } .Wrapper> div {border: 2px solid # ffa94d; border-radius: 5px; background-color: # ffd8a8; padding: 1em; color: # d9480f; } <Div class = "wrapper"> <div class = "box1"> One </ div> <div class = "box2"> Two </ div> <div class = "box3"> Three <div class = "abspos "> Цей блок абсолютно позиціонується. В даному прикладі контекстом позиціонування являетсягрід-область, тому значення зсуву відраховуються від зовнішніх країв грід-області. </ Div> </ div> <div class = "box4"> Four </ div> </ div> .wrapper {display: grid; grid-template-columns: repeat (4,1fr); grid-auto-rows: 200px; grid-gap: 20px; } .Box3 {grid-column-start: 2; grid-column-end: 4; grid-row-start: 1; grid-row-end: 3; position: relative; } .Abspos {position: absolute; top: 40px; left: 40px; background-color: rgba (255,255,255, .5); border: 1px solid rgba (0,0,0,0.5); color: # 000; padding: 10px; }

Грід і display: contents

Останнє, про що потрібно згадати, говорячи про взаємодію грід з іншими специфікаціями, що стосуються позиціонування елементів, - це взаємодія між CSS Grid Layout і display: contents. Значення contents властивості display - нова властивість CSS, яке описується в специфікації Display наступним чином:

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

Якщо Ви пишете для елемента display: contents, блок (бокс), який він повинен створити в дереві документа зникає, а ось блоки його дочірніх елементів і його псевдо-елементів переходять на один рівень вгору. А значить це те, що дочірні елементи грід-елемента можуть самі стати грід-елементами. Звучить незрозуміло? Давайте розберемося на простому прикладі. У розмітці нижче у нас є грід. Перший елемент цього гріда налаштований так, щоб займати все три треки-колонки. У нього є три вкладених елемента. Оскільки ці вкладені елементи не є прямими нащадками гріда, вони не стають частиною грід-макета і відображаються, як звичайні блоки.

* {Box-sizing: border-box;} .wrapper {border: 2px solid # f76707; border-radius: 5px; background-color: # fff4e6; } .Box {border: 2px solid # ffa94d; border-radius: 5px; background-color: # ffd8a8; padding: 1em; color: # d9480f; } .Nested {border: 2px solid # ffec99; border-radius: 5px; background-color: # fff9db; padding: 1em; } <Div class = "wrapper"> <div class = "box box1"> <div class = "nested"> a </ div> <div class = "nested"> b </ div> <div class = "nested "> c </ div> </ div> <div class =" box box2 "> Two </ div> <div class =" box box3 "> Three </ div> <div class =" box box4 "> Four < / div> <div class = "box box5"> Five </ div> </ div> .wrapper {display: grid; grid-template-columns: repeat (3, 1fr); grid-auto-rows: minmax (100px, auto); } .Box1 {grid-column-start: 1; grid-column-end: 4; }

Якщо ми тепер додамо правило display: contents для box1, блок цього боксу зникне, зате дочірні елементи стануть грід-елементами і будуть розташовані відповідно до правил авторозміщення.

* {Box-sizing: border-box;} .wrapper {border: 2px solid # f76707; border-radius: 5px; background-color: # fff4e6; } .Box {border: 2px solid # ffa94d; border-radius: 5px; background-color: # ffd8a8; padding: 1em; color: # d9480f; } .Nested {border: 2px solid # ffec99; border-radius: 5px; background-color: # fff9db; padding: 1em; } <Div class = "wrapper"> <div class = "box box1"> <div class = "nested"> a </ div> <div class = "nested"> b </ div> <div class = "nested "> c </ div> </ div> <div class =" box box2 "> Two </ div> <div class =" box box3 "> Three </ div> <div class =" box box4 "> Four < / div> <div class = "box box5"> Five </ div> </ div> .wrapper {display: grid; grid-template-columns: repeat (3, 1fr); grid-auto-rows: minmax (100px, auto); } .Box1 {grid-column-start: 1; grid-column-end: 4; display: contents; }

Таким чином ми можемо змусити вкладені елементи поводитися, немов вони частина гріда (і в деякому сенсі імітація того поведінки, яке повинні будуть реалізувати подгріди (subgrids), коли руки розробників браузерів до них доберуться). Точно так само можна використовувати display: contents з flexbox, щоб вкладені елементи ставали flex-елементами.

UPD: На 04.02.2018 головна проблема з display: contents в тому, що "рідкісний браузер долетів до середини Дніпра", підтримка у властивості - відсутня. Слідкуйте за оновленнями https://caniuse.com/#feat=css-display-contents

Як Ви могли побачити, CSS Grid Layout - це частина Вашої інструментарію. Не бійтеся змішувати його з іншими методами створення макетів, щоб отримати різні ефекти. І не перемикайтеся, далі буде багато цікавого.

А що якщо батьківський елемент - це грід-область?
Звучить незрозуміло?

Дополнительная информация

rss
Карта