Від автора: про те, як суміжний селектор вирішує складні вимоги до дизайну, зберігаючи CSS-код в читаному вигляді. Це одна з тих завдань в веб-розробці, які починаються просто, але в процесі стають складніше: як всередині статті, наприклад, поста в блозі використовувати вертикальні відступи CSS магдіп’и на елементах, коли сама стаття складається з складної markdown-розмітки.
Здебільшого вам доведеться працювати з винятками і залежностями. Між заголовком і зображенням повинен бути великий відступ, однак між двома йдуть підряд зображеннями відступ повинен бути невеликим. Відступ між h2 і h3 повинен бути більше, ніж між h2 і параграфом. І т. д.
Пару років тому на початку моєї кар’єри в якості веб-розробника всі ці винятки і залежно заплутували код, робили його візуально непослідовним, що призводило до несподіваного поведінки. Я реально гугл не один раз «чому не працює margin-top».
Нижче я опишу техніку, якої я дотримуюся вже на протязі довгого часу. Техніка дозволяє уникнути схлопування магдіп’ов, забезпечує хорошу читаність і дозволяє створювати складні залежності.
Крок 1
Проста стаття виглядає наступним чином:
Hello World
Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet
- Lorem
- Ipsum
- Dolor
Зазвичай я беру два параграфа і налаштовую між ними вертикальний margin так, щоб це виглядало красиво. Потім я використовую це значення в якості базового для всіх елементів.
.article > * + * {
margin-top: 1.5 rem;
}
Це правило додає margin-top до всіх прямим дочірнім елементів .article, у яких є суміжний тег. Застосовуючи margin-top тільки до прямих дочірнім елементам, я уникаю певного небажаного поведінки. Наприклад, ul у коді вище отримає margin-top, а його li вже немає.
У CodePen демо нижче показаний приклад:
Крок 2
На другому етапі я додаю більше певних правил, наприклад:
.article > img + * {
margin-top: 3rem;
}
Всі елементи після img отримують margin-top. Принцип схожий з застосуванням margin-bottom до img безпосередньо. Однак у суміжного селектора і margin-top є дві переваги: не потрібно видаляти margin-bottom :last-child і уникати схлопування магдіп’ов.
У CodePen нижче показаний розширений приклад:
Крок 3
На цьому етапі я додають правила до певних елементів, наприклад:
.article > * + h2 {
margin-top: 4rem;
}
.article > * + img {
margin-top: 3rem;
}
Якщо у h2 є суміжний тег, він отримає margin-top. Те ж саме буде з зображенням.
Приклад CodePen:
Крок 4
На останньому етапі я працюю з певними залежностями:
.article > img + img {
margin-top: 1rem;
}
Якщо після зображення випливає інше зображення, то інтервал між ними повинен бути дуже маленьким.
Приклад CodePen:
Якщо хочеться, можна зробити ще більш специфічний код. Наприклад:
.article > img + img + img + h2 {
margin-top: 5rem;
}
Якщо перед h2 йде три зображення поспіль, то заголовок отримає margin-top. На щастя, це крайній випадок. Однак корисно знати, що суміжний селектор може вирішувати такі складні залежності.
Сучасне використання
Щоб поліпшити читаність, я використовую (SCSS) вкладеність і пишу кожне правило на одному рядку. Також я не групую селектори з однаковим значенням, так як CSSO сам подбає про це в задачі по збірці.
.article {
> * + * { margin-top: 1.5 rem }
> h2 + * { margin-top: 1rem }
> img + * { margin-top: 3rem }
> * + h2 { margin-top: 4rem }
> * + h3 { margin-top: 3.5 rem }
> * + img { margin-top: 3rem }
> img + img { margin-top: 1rem }
> h2 + h3 { margin-top: 4.5 rem }
}
Ця техніка добре працює з SASS і CSS-змінними, наприклад, для створення базових сіток. Якщо все магдіп’и обчислюються з однієї базової змінної, то для збільшення або зменшення відступів потрібно всього лише змінити цю змінну.
CodePen приклад на CSS-змінних:
Висновок
Зазвичай на розроблених в нашому агентстві сайтах дуже складні статті. У них присутня не тільки складна markdown-розмітка, але і заголовки категорій, вступний текст і вкладені макети.
Суміжний селектор і margin-top дозволяють мені вирішувати складні вимоги до дизайну, зберігаючи читаність CSS-правил. Особливо якщо мені знадобиться пізніше додати або змінити правила.