Перехід з HTML Grid на CSS Grid-системи

Пару місяців тому мене хтось питав, чи я можу підказати що-небудь по переходу з класів «.col» Bootstrap на Susy або Neat. І це питання поставив мене в глухий кут: я ніколи не говорив на цю тему, хоча сам вже дуже довго користуюся сітками Susy!

У будь-якому випадку, якщо ви переходите в іншу систему вперше, це досить відповідальний крок. У цій статті я розповім вам про процес переходу, що складається з 4 етапів.

Перед тим як продовжити, передбачається, що ви вже розумієте, чому вирішили перейти з HTML Grid (типу Bootstrap, Foundationи будь-якого фреймворку) систем на CSS Grid (Susy, Neat або навіть Flexboxс CSS).Якщо ж ви до кінця не зрозумієте, чому вирішили зробити це, то перед переходом настійно раджу прочитати цю статтю. У ній описані всі плюси і мінуси обох систем.

Готові?

Наші чотири етапи:

  1. Визначаємо шаблони макета
  2. Придумаємо нову розмітку і класи
  3. Створюємо шаблони макета в CSS
  4. Міняємо стару розмітку на нову


Пройдемося по кожному етапу окремо.

Етап 1: Визначаємо шаблони макета

Шаблон макета – шаблон, в якому вказано, як ваш макет буде змінюватися на різних дозволах екрану. Прикладом шаблон макета може послужити макет «content-sidebar». В даному макеті на мобільних пристроях область контенту і сайдбар займають всі 12 колонок (передбачається, що ви використовуєте 12-тиколоночную систему). При ширині екрану в 600px контент займає 9 колонок, а сайдбар 3.



Код цього макета в Bootstrap відносно простий. (Давайте припустимо, що col-md тригери на 600px. Я забув точні дозволу в Bootstrap).

<div class="row">
<div class="col-12 col-md-9">Content</div>
<div class="col-12 col-md-3">Sidebar</div>
</div>


Ще один приклад шаблону макета – трьохколонкова сітка. На екранах мобільних пристроїв кожна клітинка займає всі 12 колонок, а при ширині екрану 600px 4 колонки.



Код трьохколонковою сітки в Bootstrap також не відрізняється складністю:

<div class="row">
<div class="col-12 col-md-4">Grid item</div>
<div class="col-12 col-md-4">Grid item</div>
<div class="col-12 col-md-4">Grid item</div>
</div>


Іноді доводиться працювати з більш складними макетами. Наприклад, ви хочете вписати два блоки в трехколоночную сітку. При ширині екрану 600px і вище кожен блок повинен займати 6 колонок, а не 4.



У Bootstrap код буде виглядати приблизно так:

<div class="row">
<div class="col-12 col-md-6">Featured Grid Item</div>
<div class="col-12 col-md-6">Featured Grid Item</div>
<div class="col-12 col-md-4">Grid item</div>
<div class="col-12 col-md-4">Grid item</div>
<div class="col-12 col-md-4">Grid item</div>
</div>


На даний момент ми переглянули 3 шаблону:

  1. «content-sidebar» шаблон
  2. Шаблон трьохколонковою сітки
  3. Шаблон трьохколонковою функціональної сітки


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

Етап 2: Придумаємо нову розмітку і класи

Один з плюсів HTML Grid систем в тому, що нам не потрібно думати про розмітку і класах, все вже вирішено за нас. А при переході на CSS Grid системи нам доводиться спішно створювати класи типу «.some-class-name» на заміну класами типу «.col-md-6».

Це величезна проблема, і безліч людей застрягли на цьому місці. Коли я перший раз працював з CSS Grid системою, я теж тут застряг.

Спочатку я намагався дотримуватися семантику. Я використовував класи типу .content і .sidebar де тільки міг, а також по максимуму намагався видалити всі спадкування. Нижче представлена моя початкова розмітка для шаблону content-sidebar:

<div class="content">Content</div>
<div class="sidebar">Sidebar </div>


Якщо ваш макет досить простий, а на сайті є лише область контенту .content і сайдбар .sidebar, то ця розмітка, в принципі, підійде. Все стає трохи заплутаніше при додаванні інших типів шаблонів.

Наприклад, найпростіша розмітка для трьохколонковою сітки, яку я створив, виглядає наступним чином:

<div class="grid">
<div class="grid-item">Grid item</div>
<div class="grid-item">Grid item</div>
<div class="grid-item">Grid item</div>
</div>


Якщо з'єднати дві розмітки разом, то можна помітити, що мій перший метод не працює з трьохколонковою сіткою і шаблоном content-sidebar.

<!-- НЕ РОБІТЬ ТАК! -->
<div class="content">Content</div>
<div class="sidebar">Sidebar </div>
<div class="grid">
<div class="grid-item">Grid item</div>
<div class="grid-item">Grid item</div>
<div class="grid-item">Grid item</div>
</div>


Краще додати контейнер div зразок класу .row в Bootstrap:

<div class="content-sidebar-container">
<div class="content">Content</div>
<div class="sidebar">Sidebar</div>
</div>
<div class="three-column-grid-container">
<div class="grid-item">Grid item</div>
<div class="grid-item">Grid item</div>
<div class="grid-item">Grid item</div>
</div>


Трюк з додаванням div контейнера означає, що для стилізації його прямих спадкоємців можна використовувати псевдоклас: nth-child:

// Це SCSS
.content-sidebar-container {
> div:nth-child(1) {
// Стилі вмісту
}

> div:nth-child(2) {
// Стилі сайдбара
}
}


А значить, більше не потрібно задавати класи дочірнім елементів контейнера (такі як .content, .sidebar і .grid-item). Розмітка стає ще простіше:

<div class="content-sidebar-container">
<div>Content</div>
<div>Sidebar</div>
</div>


Тут можна внести ще одне виправлення — .content-sidebar-container занадто довго набирати. Я ледачий розробник і не люблю багато друкувати.

Я вибрав імена класів зразок системи SMACSS. У SMACSS рекомендується всі правила для макета записувати з приставкою .l. Так як ми пишемо тільки класи контейнерів, а ці класи в свою чергу задають шаблони макету, то ми можемо скоротити .content-sidebar-container до .l-content-sidebar.

Клас .content-sidebar теж досить довгий. За бажанням його можна скоротити до .l-cs. (Начебто, зрозумілий клас, так адже? Просто не забудьте його задокументувати де-небудь.

Як висновок цього етапу, рекомендую створювати імена класів на зразок:

  1. Шаблон content-sidebar => .l-cs
  2. Шаблон трьохколонковою сітки => .l-g3
  3. Шаблон функціональної трьохколонковою сітки => .l-fg3


Після того, як ви придумали нову розмітку і класи, необхідно створити макети CSS.

Етап 3: Створюємо шаблони макета в CSS

Створювати шаблони макета в CSS ви можете за допомогою будь-якого методу: Susy, Neat, Bootstrap Sass, Flexbox і т. д. найголовніше тут-це вміти користуватися цим методом.

  • У будь-якому з методів вам потрібно навчитися писати медіа запити для техніки mobile-first і працювати з властивістю CSS Box Sizing.
  • Для роботи з Susy, Neat і Bootstrap Sass вам потрібно вивчити float.
  • Для роботи з Flexbox доведеться вивчити Flexbox.


Список можна продовжувати, але суть ви зрозуміли.

Нижче я покажу вам, що ви можете створити абсолютно будь-макет за допомогою кожного з цих методів в CSS. Я створю:

  • .l-cs за допомогою обтеканий (в чистому SCSS) і Susy
  • .l-g3 з допомогою обтеканий (в чистому SCSS) і Susy
  • .l-fg з допомогою Flexbox


Спочатку розберемо .l-cs.

Як створити макет .l-cs за допомогою звичайного SCSS

Ми вже знаємо, як за допомогою запропонованої мною розмітки створювати макети – використовувати псевдоклас: nth-child. Також варто скористатися селектором прямого наслідування (>), щоб виключити випадковий вибір інших div ів в макеті.

.l-cs {
> div:nth-child(1) {
// Стилі вмісту
}

> div:nth-child(2) {
// Стилі сайдбара
}
}


Ми знаємо, що div и за замовчуванням займають 100% ширини. Це означає, що для створення шаблону макета для маленьких екранів нам стилі писати взагалі не потрібно.

З шириною екрану в 600px ми будемо використовувати float, щоб область контенту займала 9 колонок з 12, а сайдбар — 3. При роботі з float-ами всім div ам в макеті необхідно вказати властивості width і float. Код буде наступний:

.l-cs {
> div:nth-child(1) {
@media (min-width: 600px) {
float: left;
width: 74.57627%;
}
}

> div:nth-child(2) {
@media (min-width: 600px) {
float: right;
width: 23.72881%;
}
}
}


І ще одне. Щоб контейнер не схлопнувся при роботі з float, йому необхідно додати clearfix:

@mixin clearfix() {
&:after {
display: table;
content: '';
clear: both;
}
}

.l-cs {
@include clearfix;

/ / код вище ... 
}


От і все! Не складно, правда?

Один мінус тут – обчислення width для області вмісту і сайдбара. Більшість CSS Grid бібліотек типу Susy і Neat намагаються позбутися цього головного болю.

Якщо працювати в Susy, код вище можна спростити, додавши міксин span(), який автоматично створює потрібні властивості:

.l-cs {
@include clearfix

> div:nth-child(1) {
@media (min-width: 600px) {
@include span(9);
}
}

> div:nth-child(2) {
@media (min-width: 600px) {
@include span(3 last);
}
}
}


Дивитися робочий код на codepen

З Susy все набагато простіше, правда?

Продовжимо.
.
Як створити макет .l-g3 з допомогою Susy

Для створення трьохколонковою сітки застосовується та ж техніка: псевдоклас: nth-child і селектор прямого наслідування >.

Тут вам доведеться вивчити всі значення псевдокласу nth-child. На сайті CSS Tricks є nth-tester, за допомогою якого можна наочно вивчити даний псевдоклас.

.l-g3 {
> div:nth-child(3n+1) { // Крайній лівий елемент сітки }
> div:nth-child(3n+2) { // Центральний елемент сітки}
> div:nth-child(3n+3) { // Крайній правий елемент сітки }
}


Так як ми створюємо трехколоночную сітку з допомогою обтеканий, то насамперед нам необхідно додати clearfix.

.l-g3 {
@include clearfix;
> div:nth-child(3n+1) { // Крайній лівий елемент сітки }
> div:nth-child(3n+2) { // Центральний елемент сітки }
> div:nth-child(3n+3) { // Крайній правий елемент сітки }
}


Як ми вже говорили вище, div за замовчуванням займає 100% ширини. Так що для маленьких екранів нам взагалі стилі писати не потрібно. Також ми пам'ятаємо, що при ширині екрану в 600px необхідно прописати властивості float і width.

Так як більше двох колонок, то в даному випадку також необхідно додати властивість margin для елементів сітки.

Код:

.l-g3 {
@include clearfix;

@media (min-width: 600px) {
// Крайній лівий елемент сітки
> div:nth-child(3n+1) {
width: 32.20339%;
float: left;
margin-right: 1.69492%;
}

// Центральний елемент сітки
> div:nth-child(3n+2) {
width: 32.20339%;
float: left;
margin-right: 1.69492%;
}

// Крайній правий елемент сітки
> div:nth-child(3n+3) {
float:right;
width: 32.20339%;
margin-right: 0;
}
}
}


Досить страшний код з властивістю nth-child. Виглядає складно, та ще й потрібно обчислювати точні значення margin і width.

Писати код у Susy набагато простіше. Ви можете вибрати один з двох миксинов: u() або gallery().

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

.l-g3 {
@include clearfix;

> div {
@include gallery(4 of 12);
}
}


Susy сама автоматично генерує правильні селектори nth-child і властивості. Мила штуковина!

Поиграйтесь з демо на codepen

Рекомендую ознайомитися з Susy – сильно спрощує створення сіток.

Ну а ми продовжимо.
.
Як створити макет .l-fg3 з допомогою Flexbox

Порівняно з float-ами під Flexbox сітку створити трохи складніше. Для початку давайте розглянемо розмітку, яку я вирішив використовувати для макета .l-fg3.

<div class="l-fg3">
<div>Featured Item</div>
<div>Featured Item</div>
<div>Grid item</div>
<div>Grid item</div>
<div>Grid item</div>
</div>


Перше, що необхідно зробити при роботі з Flexbox, це додати контейнера властивість flex. Властивості flex-wrap необхідно задати значення wrap, щоб клітинки сітки могли перескакувати на другий ряд.

Зверніть увагу: для спрощення коду я не став писав вендорные префікси. Для генерації префіксів використовуйте autoprefixer, кращий спосіб.

.l-fg3 {
display: flex;
flex-wrap: wrap;
}


Прописавши ці властивості, ви помітите, що елементи сітки займають лише необхідне для них простір:



Осередки сітки займають лише необхідне їм простір.

Це означає, що для мобільного макета нам доведеться змусити їх вручну розтягуватися на 100% ширини. Можна:

  • Задати властивість flex-flow: column .l-fg
  • Або задати властивість flex-basis: 100% всіх елементів сітки


Задамо flex-basis: 100%, її легше зрозуміти.

.l-fg3 > div {
flex-basis: 100%;
}




Зверніть увагу: Щоб ви бачили межі клітинок, я додав сіру рамку в 1px.

З мобільним макетом ми закінчили. Тепер створимо функціональну сітку для ширини 600px. Ми знаємо, що на одному рядку повинно бути три елементи, кожен повинен займати рівно третину від розміру вікна, якщо немає додаткових відстаней між елементами сітки. Для цього необхідно змінити значення властивості flex-basis на 33.333%:

.l-fg3 > div {
flex-basis: 100%;
@media (min-width: 600px) {
flex-basis: 33.333%;
}
}




Трьохколонкова функціональна сітка без магдіп'ов.

Тепер необхідно додати відступи між осередків.

При роботі з flexbox відступи доведеться розділити навпіл і розміщувати їх по краях елементів, сітки. Якщо відстань між елементами одно 20px, то кожній клітинці необхідно задати margin-left margin-right у 10px.

.l-fg3 > div {
flex-basis: 100%;
@media (min-width: 600px) {
margin: 10px;
flex-basis: 33.333%;
}
}


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



З-за неправильного значення flex-basis макет поплив.

Макет поплив з-за того, що магдіп'и додаються до значень flex-basis для кожного елемента. Ширина трьох елементів стає рівною 100%+60px, що більше 100%. Тому браузер просто не може не пересунути третій блок на наступний рядок.

Рішення проблеми на диво просте. Треба лише видалити магдіп'и у всіх елементів, сітки з допомогою calc():

.l-fg3 > div {
// ...
@media (min-width: 600px) {
margin: 10px;
flex-basis: calc(33.333% - 20px);
}
}


І ви отримаєте нормальну трехколоночную сітку (але з фіксованим відступом 20px).


Тепер впишемо два блоки в 3 клітинки.

Ми знаємо, що кожен елемент має займати половину ширини рядка (мінус 20px між ними). За такою ж формулою ми можемо просто змінити властивість flex-basis для перших двох елементів і отримаємо функціональну сітку.

.l-fg3 {
// ...
> div:nth-child(1),
> div:nth-child(2) {
@media (min-width: 600px) {
flex-basis: calc(50% - 20px);
}
}
}




Це ще не все.

Зазвичай, вам не будуть потрібні магдіп'и в 10px по всім сторонам сітки. Видалити зовнішні відступи можна за допомогою від'ємного значення margin на контейнері .l-fg3.

.l-fg3 {
margin: -10px;
}


Після цього ви виявите, що з'явився скролл вправо, а він нам точно не потрібен.



З-за негативного margin'а з'являється скролл вправо.

Виправити це можна, створивши flex контейнер з властивість overflow-x: hidden і помістивши в нього контейнер .l-fg:

<div class="l-flex">
<div class="l-fg">
<div>Featured Item</div>
<div>Featured Item</div>
<div>Grid Item</div>
<div>Grid Item</div>
<div>Grid Item</div>
</div>
</div>


.l-flex {
overflow-x: hidden;
}


От і все! Хто сказав, що під Flexbox важко створювати сітки?

До речі, так як Flexbox – не головна тема статті, то за створення сітки з його допомогою я пробігся досить поверхово. Але сподіваюся вам все зрозуміло.

Продовжимо.

Етап 4: Міняємо стару розмітку на нову

Останній етап – це заміна старої розмітки на нову. На даному етапі слід уважно перевірити, чи не припустилися ви помилки на 3 етапі.

І все готово.

Висновок

У цій статті ми навчилися переходити з HTML Grid (в більшості випадків фреймворки, схожі на Bootstrap) на CSS Grid систему, яку самі і написали.

Узагальнюючи все вищесказане, можна нагадати, що у нас було 4 етапи:

  1. Визначення наявних шаблонів макета
  2. Створення нової розмітки і класів
  3. Створення шаблону макету в CSS
  4. Заміна старої розмітки на нову


У висновку статті хотів повідомити, що днями ми підготував для Вас міні-курс «Фреймворк Bootstrap – верстаємо адаптивно, просто, швидко».

У цьому невеликому курсі ми з вами познайомимося з фреймворком Bootstrap, буквально зовсім трохи доторкнувшись до його можливостей. І як приклад зверстаємо простий макет сайту-портфоліо, намальований в мінімалістичному стилі.
Тому, якщо хочете освоїти роботу з цим фреймворком, подивіться уроки по фреймворку bootstrap.

Чи допомогла вам ця стаття перейти з HTML Grid на CSS Grid систему? Пишіть про це в коментарях!

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.