HTML та CSS
HTML і CSS — це дві мови, з яких складається будь-який вебінтерфейс, і шар, який найчастіше вважають простим. HTML — це не розмітка заради вигляду: кожен елемент є обіцянкою, за якою діють браузер і допоміжні технології. CSS — не список стилів, а алгоритм розв’язання конфліктів із визначеним порядком, і знання цього порядку перетворює вгадування на міркування.
- Специфікує
- WHATWG · W3C
- Ворота каскаду
- Четверо, по черзі
- Інструменти розкладки
- Flow · Flex · Grid
HTML — це набір обіцянок
<button> — це не коробка, схожа на кнопку. Вона отримує фокус із клавіатури, реагує на Enter і пробіл, оголошує себе кнопкою для зчитувача екрана, бере участь у надсиланні форми й доступна автоматизації браузера та шару доступності операційної системи. <div> з обробником кліку не має нічого з цього, а відтворити все це правильно — це рядків сорок, у яких ви припуститеся непомітних помилок.
За цим стоїть дерево доступності. Розбираючи ваш HTML, браузер поряд із DOM будує другу структуру, у якій кожен вузол має роль, ім’я, стан і набір підтримуваних дій. Зчитувачі екрана, голосове керування, режими читання в браузері та пошукові краулери читають саме це дерево, а не ваш CSS. Семантичні елементи наповнюють його правильно й безкоштовно; несемантичні лишають порожнім і потребують ручного заповнення через атрибути ARIA.
Дві речі дають більшу частину практичної користі. Заголовки мають описувати структуру документа, а не кегль тексту: багато людей переміщуються сторінкою, стрибаючи між заголовками, і сторінка, чий єдиний <h1> — це логотип, не дає їм нічого. І кожен елемент форми потребує пов’язаного <label>; плейсхолдер лейблом не є, бо зникає саме тоді, коли потрібен, і часто взагалі не озвучується.
Каскад — це алгоритм
Коли два оголошення задають одну властивість одного елемента, браузер не вгадує. Він проводить чотири порівняння у фіксованому порядку й зупиняється на першому, яке їх розрізняє. Майже на кожне питання «чому мій стиль не застосовується» відповідає розуміння того, на якому саме порівнянні ви програєте.
| Ворота | Що порівнюється | Де програють |
|---|---|---|
| 1. Джерело й важливість | Стилі автора, користувача й браузера, де !important перевертає порядок між ними. | !important у чужому стилі, який ви не писали. |
| 2. Шари каскаду | До якого @layer належить правило; шари порівнюються в порядку оголошення. | Дуже специфічний селектор у ранньому шарі програє простому в пізнішому. |
| 3. Специфічність | Спершу id, потім класи, атрибути й псевдокласи, потім елементи — порівнюються як три колонки, а не сумуються. | Припущення, що одинадцять класів переможуть один id. Ні: колонку id перевіряють першою. |
| 4. Порядок у коді | Виграє останнє відповідне оголошення в порядку коду. | Складальник ставить ваші файли в інакшому порядку, ніж ви очікували. |
Шари каскаду варто брати передусім з однієї причини: вони відділяють «наскільки сильно це має вигравати» від «наскільки точно це вибирає». Покладіть сторонній стиль у ранній шар, а власні перевизначення — у пізніший, і потреба нарощувати селектори зникне зовсім: один клас у пізнішому шарі переможе id у ранішому, бо другі ворота вирішуються раніше за треті.
Розкладка: flow, flex, grid
До будь-якої системи розкладки існує нормальний потік — поведінка документа взагалі без CSS. Блокові елементи складаються вниз сторінкою й займають доступну ширину; рядкові стоять уздовж рядка й переносяться. Чимало коду розкладки існує, щоб відтворити те, що нормальний потік уже робив, а найдешевша розкладка — та, якої ви не написали.
Flexbox — одна вісь
- Розміри визначає вміст; контейнер розподіляє простір
- Рядок або колонка, з переносом, якщо дозволите
- Пасує панелям, рядкам кнопок, начинці карток
- Вирівнювання вздовж і впоперек однієї осі
Grid — дві осі
- Структуру визначає контейнер; вміст її заповнює
- Рядки й колонки задані наперед, за бажання — іменами
- Пасує структурі сторінки й будь-якій справді двовимірній розкладці
- Елементи можна розміщувати й свідомо накладати
Правило вибору коротке: якщо ви шикуєте речі вздовж однієї лінії і розміри має визначати вміст — беріть flex; якщо ви задаєте структуру, у яку падає вміст, — беріть grid. Вони вільно поєднуються: сторінка на grid із flex усередині кожної клітинки — звичайний випадок, а суперечка про те, що «краще», дорівнює суперечці, чи молоток перемагає пилку.
Що прибрав сучасний CSS
Значна частина усталеної мудрості в цій темі — це поради до проблем, яких уже немає. Якщо ви вчили CSS за матеріалами приблизно до 2022 року, кілька з цього буде новим, і кожен пункт видаляє милицю, а не додає прийом.
- Користувацькі властивості (
--gap) — це справжні значення, які браузер обчислює під час роботи, тож вони каскадуються, реагують на медіазапити й читаються та задаються з JavaScript — на відміну від змінних препроцесора, яких на момент читання файлу браузером уже немає. clamp()замінює більшість типографських шкал на брейкпоінтах: одне оголошення задає мінімум, плавну середину й максимум.- Контейнерні запити дозволяють компоненту реагувати на ширину власного контейнера, а не вікна, — а саме цього багаторазовому компоненту й бракувало весь час.
:has()вибирає батька за тим, що в ньому лежить, — той «батьківський селектор», який два десятиліття вважали неможливим.- Логічні властивості (
margin-inline,padding-block) описують напрям відносно режиму письма, тож розкладка працює в мові справа наліво без дзеркального набору стилів. gapпрацює і в flexbox, і в grid, і це прибирає останню причину вішати відступи на дітей, а потім знімати їх у першої чи останньої.
Що насправді коштує користувачеві
CSS блокує рендер за задумом: браузер не малюватиме, доки не отримає стилі для поточного медіа, бо намалювати спершу й перестилювати потім означало б показати всім нестилізований вміст. Саме тому розмір і кількість стилів у голові документа — це проблема першої відмальовки, а не пропускної здатності.
Два видимі збої варто назвати, бо обидва дешево попередити. Зсув розкладки стається, коли вміст приходить без зарезервованого місця: зображення без розмірів, шрифт, що підмінюється на інший за метрикою, рекламний блок, що виникає над тим, що людина читає. Зарезервуйте місце — і цього не буде. А «биття» розкладки стається, коли JavaScript у циклі читає геометричну властивість, пише стиль і читає знову, змушуючи браузер синхронно перераховувати розкладку на кожній ітерації; групуйте спершу читання, потім записи.
Як це виявляється в реальній поставці
Стилі стають непідтримуваними майже ніколи не через розмір. Причина в тому, що ніхто не може передбачити, що зламає видалення правила, — а це стається, коли селектори тягнуться через межі компонентів: правило у файлі шапки стилізує щось у підвалі, бо обидва підпали під .card h3. Хоч би яку методологію ви взяли, щоб цьому запобігти — конвенцію імен, CSS-модулі, скоуповані стилі у фреймворку чи шари плюс дисципліну, — властивість, яку ви купуєте, та сама: локальність, щоб зміна лишалася там, де ви її зробили.
Де це вироджується
- Div з обробником кліку замість кнопки — невидимий для клавіатури й для будь-якої допоміжної технології.
outline: noneна фокусі без заміни робить навігацію клавіатурою неможливою для відстеження.- Заголовки, обрані за розміром, руйнують структуру документа, за якою люди орієнтуються.
- Гонка
!important, де кожна сторона може відповісти лише ще одним. - Селектори, що тягнуться через межі компонентів, — жодне правило не можна безпечно видалити.
- Магічні числа —
margin-top: 37px— кодують один розмір екрана й ламаються на наступному. - Зображення без розмірів — текст стрибає під пальцем читача, поки сторінка вантажиться.
Коли це застосовувати
Застосовуйте, коли
- Завжди — кожен фреймворк із цього списку зрештою зводиться до цих двох мов.
- Для контентних сторінок беріть чистий HTML і CSS: фреймворк додасть витрат і жодної нової спроможності.
- Беріть рідні елементи раніше за ARIA, а ARIA — лише щоб описати те, що ви справді реалізували.
- Беріть шари каскаду, коли інтегруєте сторонні стилі, які не можете редагувати.
Уникайте, коли
- Робити руками віджети, які вже є рідними: діалог, розкривний блок, поле дати.
- Додавати методологію CSS у проєкт, достатньо малий, щоб локальність ще не була проблемою.
- Відтворювати систему розкладки в JavaScript, бо слухач resize здався простішим за grid.
- Оптимізувати швидкість селекторів — це не було справжнім вузьким місцем понад десять років.
Було корисно?
Поділіться з тим, хто працює над тією ж задачею.