РозробкаJunior

HTML та CSS

HTML і CSS — це дві мови, з яких складається кожна вебсторінка: HTML каже, чим є кожна її частина, а CSS — як вона виглядає і де стоїть. Обидві зазвичай вважають простим шаром, і обидві працюють за правилами, достатньо точними, щоб майже на кожне «чому воно так виглядає» існувала точна відповідь. Сторінка починається з дванадцяти симптомів верстки, яка робить не те, що написано в коді, — кожен із правилом, що за ним стоїть, і виправленням; далі — що браузер робить із двома файлами, обіцянки HTML, каскад, бокс і розкладка, що коштує користувачеві, і п’ять задокументованих кейсів.

Специфікує
WHATWG · W3C
Інструменти розкладки
Flow · Flex · Grid
Сторінок із помилками WCAG
95,9% · WebAIM 2026

Дванадцять симптомів і правило за кожним

Спершу таблиця, бо саме через це найчастіше відкривають сторінку про HTML і CSS: щось на екрані робить не те, що написано в коді. Кожен рядок — це симптом, який видно, правило, що його спричиняє, і виправлення. Жоден із дванадцяти не є багом браузера. Кожен — це правило, яке існувало завжди й зустріло код людини, що з ним ще не стикалася, — а правил так мало, що решта сторінки охоплює їх усі.

СимптомЩо насправді відбуваєтьсяВиправлення
1. Мій стиль ігноруєтьсяВін програв на одних із чотирьох воріт каскаду, або селектор узагалі не збігся з елементом.Знайдіть ворота, на яких програли (каскад, нижче), перш ніж підвищувати специфічність.
2. z-index: 9999 нічого не робитьЕлемент сидить у контексті накладання, який сам малюється нижче; число змагається лише всередині нього.Знайдіть предка, що створює контекст, — часто це transform чи opacity, — і виправте порядок там.
3. width: 100% із падінгом вилазить за крайЗа замовчуванням ширина охоплює лише вміст, а падінг і рамка додаються зверху.box-sizing: border-box для всього — це робить майже кожен CSS-ресет.
4. Проміжок між двома блоками менший за суму їхніх відступівВертикальні зовнішні відступи між блоками в нормальному потоці схлопуються до більшого. Так записано в специфікації.Розсувайте дітей через gap у flex- чи grid-батькові або падінгом — ні те, ні те не схлопується.
5. Довге слово чи посилання вилазить із карткиFlex-елемент не стискається вужче за своє найдовше неподільне слово: його мінімальна ширина за замовчуванням дорівнює вмісту.min-width: 0 для елемента, overflow-wrap: anywhere для тексту.
6. Сторінка прокручується вбікЩось ширше за екран: фіксована ширина, 100vw (що включає смугу прокрутки) або неподільний рядок.Знайдіть винуватця, на хвилину обвівши контуром усі елементи, і перейдіть на max-width та відносні одиниці.
7. position: sticky не прилипаєХтось із предків має overflow і став коробкою прокрутки, батько не вищий за сам елемент, або не задано top.Приберіть overflow у предка, дайте батькові висоту, задайте top.
8. Абсолютно позиціонований елемент відлітає в кут сторінкиВін ставиться відносно найближчого позиціонованого предка, а такого немає, тож береться сторінка.position: relative на елементі, до якого його треба прив’язати.
9. Сторінка стрибає під час завантаженняВміст прийшов без зарезервованого місця: зображення без розмірів, пізній шрифт, банер, вставлений згори.width і height або aspect-ratio для медіа; зарезервоване місце для всього, що вставляється пізніше.
10. Повноекранний блок на телефоні обрізаний знизуНа мобільному 100vh — це висота зі схованою панеллю браузера, тож блок вищий за видиму частину.100svh для стабільної висоти, 100dvh — щоб стежити за панеллю, коли вона рухається.
11. Анімація смикаєтьсяАнімуються width, top чи margin, а це перезапускає розкладку й відмальовку на кожному кадрі.Анімуйте transform і opacity: їх переробляє лише останній крок конвеєра.
12. Кнопка працює мишею — і більше нічимЦе <div> з обробником кліку: без фокуса, без клавіатури, без нічого, що міг би оголосити зчитувач екрана.<button>. Розділ про HTML нижче перелічує, що він дає безкоштовно.

Що браузер робить із двома файлами

HTML і CSS схожі на документи, тож їх і читають як документи — згори донизу, як опис сторінки. Браузер читає їх як вхідні дані для програми, яку перезапускає щоразу, коли на сторінці щось змінюється. Знання кроків цієї програми перетворює таблицю вище з дванадцяти фактів для запам’ятовування на один механізм, який можна зрозуміти.

Спершу розбір. HTML стає DOM — деревом об’єктів, по одному на елемент, які скрипти можуть читати й змінювати. CSS стає CSSOM — тими самими правилами, перетвореними на об’єкти, до яких браузер може звертатися. Далі по черзі йдуть чотири кроки. Стилі обходять DOM і для кожного елемента та кожної властивості запускають каскад, щоб обрати одне значення. Розкладка бере ці значення й обчислює розмір і позицію кожного бокса. Відмальовка заповнює пікселі шар за шаром у порядку накладання. Композиція складає намальовані шари на екрані — зазвичай на .

Браузер перетворює HTML на DOM, а CSS — на CSSOM, а потім щоразу, коли щось змінюється, проходить чотири кроки: стилі вирішують, яке значення отримує кожна властивість, розкладка обчислює розмір і позицію кожного бокса, відмальовка заповнює пікселі в порядку накладання, а композиція складає намальовані шари на екрані. Дерево доступності будується лише з HTML — тому жоден CSS не змінює того, що чує зчитувач екрана. Смуги показують ціну зміни: що раніший крок, з якого вона перезапускає конвеєр, то більше роботи на кожному кадрі анімації.

Гілка праворуч на діаграмі — та, про яку більшість людей ніколи не чує. Поряд із DOM браузер будує дерево доступності, у якому кожен вузол має роль, ім’я, стан і дії, які підтримує. Зчитувачі екрана, голосове керування й шар доступності операційної системи читають саме це дерево, а будується воно лише з HTML. Жоден CSS до нього не дістається. <div>, стилізований точнісінько під кнопку, у цьому дереві — просто шматок тексту.

КрокЩо вирішуєЯкі рядки таблиці пояснює
СтиліЯке значення отримує кожна властивість кожного елемента1
РозкладкаРозмір і позиція кожного бокса3–10
ВідмальовкаПікселі — і що намальовано поверх чого2
КомпозиціяЯк намальовані шари потрапляють на екран11 і його виправлення
Дерево доступностіЩо допоміжні технології бачать і можуть зробити12

HTML — це набір обіцянок

<button> — це не коробка, схожа на кнопку. Вона отримує фокус із клавіатури, реагує на Enter і пробіл, оголошує себе кнопкою для зчитувача екрана, бере участь у надсиланні форми й доступна автоматизації браузера та шару доступності операційної системи. <div> з обробником кліку не має нічого з цього, а відтворити все це правильно — це рядків сорок, у яких ви припуститеся непомітних помилок.

Та сама кнопка, написана двічі. На екрані вони однакові — і тому різниця переживає кожну перевірку мишею. Під капотом елемент button дає п’ять обіцянок, які браузер виконує безкоштовно: фокус із клавіатури, Enter і пробіл, роль, яку оголошує зчитувач екрана, надсилання форми та робочий стан disabled. Div не дає жодної, і кожну доводиться відтворювати вручну в JavaScript.

Діаграма — це весь аргумент в одному кадрі. Семантичні елементи кладуть у дерево доступності правильну роль, ім’я й стан без жодного рядка коду; <div> не кладе нічого, і кожен бракуючий шматок доводиться повертати атрибутами та JavaScript. Здебільшого вибір стоїть не між двома способами зробити кнопку. Він між тим, щоб узяти кнопку, яку браузер уже зробив, і тим, щоб переробити її гірше.

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

ЕлементЩо ви отримуєте безкоштовноЩо будують натомість
<button>Фокус, Enter і пробіл, роль, надсилання форми, робочий disabled<div> з обробником кліку
<a href>Справжнє посилання: відкрити в новій вкладці, скопіювати адресу, краулери йдуть за нимКнопка чи span, що змінює сторінку скриптом
<label for>Ім’я для поля й більша ціль для клікуТекст-плейсхолдер
<dialog>Відкритий через showModal(): фокус усередині, Escape закриває, решта сторінки неактивна<div> з високим z-index
<details>Відкривається й закривається з клавіатури, без жодного JavaScriptСаморобний акордеон
<nav>, <main>Орієнтири, між якими стрибає зчитувач екранаDiv-и з назвами класів

Дві звички дають більшу частину практичної користі. Заголовки мають описувати структуру документа, а не кегль тексту: багато людей переміщуються сторінкою, стрибаючи між заголовками, і сторінка, чий єдиний <h1> — це логотип, не дає їм нічого. І кожен елемент форми потребує пов’язаного <label>; плейсхолдер лейблом не є, бо зникає саме тоді, коли потрібен, і часто взагалі не озвучується. Поруч із ними стоїть один атрибут: елемент <html> потребує lang, бо за ним зчитувач екрана обирає голос і вимову, — а 13,5% головних сторінок мільйона найпопулярніших сайтів досі його не мають.

Каскад — це алгоритм

Коли два оголошення задають одну властивість одного елемента, браузер не вгадує. Він проводить чотири порівняння у фіксованому порядку й зупиняється на першому, яке їх розрізняє. Майже на кожне питання «чому мій стиль не застосовується» — рядок 1 таблиці — відповідає розуміння того, на якому саме порівнянні ви програєте.

Коли кілька оголошень задають одну властивість одного елемента, браузер розв’язує конфлікт у фіксованому порядку: спершу джерело й важливість, потім шари каскаду, потім специфічність і лише тоді порядок у коді. Кожні ворота відсіюють кандидатів, і застосовується той, хто лишився останнім. Специфічність — треті ворота, а не перші, тому її підвищення зазвичай є лікуванням не тієї стадії.
ВоротаЩо порівнюєтьсяДе програють
1. Джерело й важливістьСтилі автора, користувача й браузера, де !important перевертає порядок між ними.!important у чужому стилі, який ви не писали.
2. Шари каскадуДо якого @layer належить правило; шари порівнюються в порядку оголошення.Дуже специфічний селектор у ранньому шарі програє простому в пізнішому.
3. СпецифічністьСпершу id, потім класи, атрибути й псевдокласи, потім елементи — порівнюються як три колонки, а не сумуються.Припущення, що одинадцять класів переможуть один id. Ні: колонку id перевіряють першою.
4. Порядок у кодіВиграє останнє відповідне оголошення в порядку коду.Складальник ставить ваші файли в інакшому порядку, ніж ви очікували.

Шари каскаду варто брати передусім з однієї причини: вони відділяють «наскільки сильно це має вигравати» від «наскільки точно це вибирає». Покладіть сторонній стиль у ранній шар, а власні перевизначення — у пізніший, і потреба нарощувати селектори зникне зовсім: один клас у пізнішому шарі переможе id у ранішому, бо другі ворота вирішуються раніше за треті. Шари працюють в усіх основних браузерах з початку 2022 року, тож причини їх не брати вже немає.

Дві речі плутають із каскадом. Перша — успадкування: кілька властивостей — серед них color, font-family і line-height — передаються від батька до дитини, якщо їх ніхто не задав, а більшість — margin, border, width — не передаються ніколи. Елемент із хибним кольором без жодного власного правила не програє каскад: у ньому нічого немає, і він успадковує. Друга — пара селекторів, що змінюють специфічність навмисно. :where() обгортає селектор і дає йому нульову специфічність — так бібліотека постачає стилі за замовчуванням, які можна перебити одним класом. :is() бере специфічність свого найспецифічнішого аргументу — так невинний на вигляд селектор раптом перемагає.

Спершу бокс, потім розкладка

Кожен елемент, який розкладає браузер, — це прямокутник із чотирьох шарів: вміст, внутрішній відступ (падінг) навколо нього, рамка й зовнішній відступ (маржин) поза рамкою. Дві умовності цієї моделі дають два рядки таблиці. Перша: width задає ширину самого лише вмісту, тож падінг і рамка додаються зверху, — це рядок 3, і саме тому майже кожен набір стилів починається з box-sizing: border-box, де width означає весь бокс. Друга: вертикальні маржини між блоками в нормальному потоці схлопуються — 24 пікселі під одним абзацом і 16 над наступним дають проміжок 24, а не 40. Це рядок 4. Так задумано, щоб суцільний текст мав рівні інтервали, і стається це лише в нормальному потоці, ніколи між flex- чи grid-елементами.

До будь-якої системи розкладки існує нормальний потік — поведінка документа взагалі без CSS. Блокові елементи складаються вниз сторінкою й займають доступну ширину; рядкові стоять уздовж рядка й переносяться. Чимало коду розкладки існує, щоб відтворити те, що нормальний потік уже робив, а найдешевша розкладка — та, якої ви не написали.

Flexbox — одна вісь

  • Розміри визначає вміст; контейнер розподіляє простір
  • Рядок або колонка, з переносом, якщо дозволите
  • Пасує панелям, рядкам кнопок, начинці карток
  • Вирівнювання вздовж і впоперек однієї осі

Grid — дві осі

  • Структуру визначає контейнер; вміст її заповнює
  • Рядки й колонки задані наперед, за бажання — іменами
  • Пасує структурі сторінки й будь-якій справді двовимірній розкладці
  • Елементи можна розміщувати й свідомо накладати

Правило вибору коротке: якщо ви шикуєте речі вздовж однієї лінії і розміри має визначати вміст — беріть flex; якщо ви задаєте структуру, у яку падає вміст, — беріть grid. Вони вільно поєднуються: сторінка на grid із flex усередині кожної клітинки — звичайний випадок, а суперечка про те, що «краще», дорівнює суперечці, чи молоток перемагає пилку.

Одну умовність flex варто знати на ім’я, бо вона дає рядок 5. Мінімальна ширина flex-елемента дорівнює його вмісту, тож елемент відмовляється стискатися вужче за найдовше неподільне слово чи адресу й натомість виштовхується з контейнера. min-width: 0 дозволяє йому стиснутися. У grid та сама пастка, записана інакше, і те саме лікування — minmax(0, 1fr).

Позиціювання й накладання

Позиціювання виймає елемент зі звичайної розкладки, і кожен варіант визначається відносно чогось. relative зсуває елемент від місця, де він мав би бути, і лишає це місце за ним. absolute ставить його відносно найближчого предка, який сам позиціонований, — а коли такого немає, відносно сторінки: це рядок 8. fixed ставить його відносно вікна перегляду. sticky поводиться звичайно, доки контейнер прокрутки не почне виносити його з поля зору, а тоді тримає на місці, — і контейнер прокрутки — це найближчий предок із заданим overflow; ось чому випадковий overflow: hidden на три рівні вище — звична причина рядка 7.

Далі — що малюється поверх чого. z-index — це не глобальний рейтинг. Він упорядковує елементи всередині контексту накладання, а новий контекст створюється непомітно: позиціонованим елементом із z-index, але також opacity менше 1, будь-яким transform, filter чи isolation: isolate. Усе всередині контексту малюється разом, як одне ціле, на тому місці в порядку, яке займає його батько.

Z-index порівнюється лише із сусідами всередині того самого контексту накладання. 9999 у меню перемагає все всередині A — і нічого поза ним, бо A цілком порівнюється з B, а 1 в A програє 2 в B. Число не може вийти за межі контексту, у якому живе. Лагодять це порядком A і B або тим, щоб A взагалі не створював контексту; найчастіше винні transform чи opacity, додані заради анімації, а не z-index, який хтось свідомо обрав.

Що прибрав сучасний CSS

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

  • Користувацькі властивості (--gap) — це справжні значення, які браузер обчислює під час роботи, тож вони каскадуються, реагують на медіазапити й читаються та задаються з JavaScript — на відміну від змінних препроцесора, яких на момент читання файлу браузером уже немає.
  • Вкладення правил у правила працює в чистому CSS, в усіх основних браузерах з 2023 року, — це одна з останніх причин, через які малому проєкту взагалі був потрібен препроцесор.
  • clamp() замінює більшість типографських шкал на брейкпоінтах: одне оголошення задає мінімум, плавну середину й максимум.
  • Контейнерні запити дозволяють компоненту реагувати на ширину власного контейнера, а не вікна, — а саме цього багаторазовому компоненту й бракувало весь час.
  • :has() вибирає батька за тим, що в ньому лежить, — той «батьківський селектор», який два десятиліття вважали неможливим.
  • aspect-ratio резервує форму бокса ще до появи вмісту — це відправляє на пенсію хак із відсотковим падінгом і запобігає рядку 9 для кожного вбудованого відео.
  • Одиниці svh, lvh і dvh описують екран телефона з показаною панеллю браузера, зі схованою або такою, як вона є зараз, — це виправлення рядка 10.
  • Логічні властивості (margin-inline, padding-block) описують напрям відносно режиму письма, тож розкладка працює в мові справа наліво без дзеркального набору стилів.
  • gap працює і в flexbox, і в grid, і це прибирає останню причину вішати відступи на дітей, а потім знімати їх у першої чи останньої.

Що насправді коштує користувачеві

CSS блокує рендер за задумом: браузер не малюватиме, доки не отримає стилі для поточного медіа, бо намалювати спершу й перестилювати потім означало б показати всім нестилізований вміст. Саме тому розмір і кількість стилів у голові документа — це проблема першої відмальовки, а не пропускної здатності.

Смуги під діаграмою конвеєра — друга половина історії. Зміна властивості перезапускає конвеєр із першого кроку, на який ця властивість впливає, а під час анімації цей перезапуск стається шістдесят разів на секунду й частіше:

Ви змінюєтеЯкі кроки перезапускаютьсяЦіна на кадр анімації
width, height, top, margin, font-sizeСтилі, розкладка, відмальовка, композиціяДорого — кожен бокс навколо може зрушити
color, background, box-shadowСтилі, відмальовка, композиціяПомірно — нічого не рухається, пікселі перемальовуються
transform, opacityСтилі, композиціяДешево — намальований шар зсувається чи згасає як є

У цьому все пояснення рядка 11. transform і opacity може опрацювати сама лише композиція — за умови, що елемент лежить на власному шарі, а для всього анімованого браузери влаштовують це самі, — тож анімація на них лишається плавною, навіть коли головний потік зайнятий чимось іншим. Той самий виїзд, написаний через left, запускає розкладку для елемента й усього навколо нього на кожному кадрі.

Два видимі збої варто назвати, бо обидва дешево попередити. Зсув розкладки — рядок 9 — стається, коли вміст приходить без зарезервованого місця: зображення без розмірів, шрифт, що підмінюється на інший за метрикою, рекламний блок, що виникає над тим, що людина читає. Google вимірює це як CLS — один із трьох , які з 2021 року враховує в ранжуванні, — і вважає показник понад 0,1 таким, що потребує покращення. Зарезервуйте місце — і цього не буде. А «биття» розкладки стається, коли JavaScript у циклі читає геометричну властивість, пише стиль і читає знову, змушуючи браузер синхронно перераховувати розкладку на кожній ітерації; групуйте спершу читання, потім записи.

П’ять кейсів і те, чого в кожному бракувало

Кожен кейс нижче задокументовано публічно — судом, регулятором або самою компанією. У жодному з них не бракувало чогось просунутого. Бракувало елемента, атрибута чи звички, які ця сторінка вже назвала.

КейсЩо сталосяЧого бракувало
Target, 2006–2008Колективний позов незрячих покупців, які не могли користуватися Target.com; мирова угода з фондом $6 млнТекстові альтернативи для зображень; оформлення замовлення без миші
Domino’s, 2016–2019Незрячий клієнт не зміг замовити через зчитувач екрана; Верховний суд США відмовився розглядати апеляцію Domino’sЕлементи керування, які зчитувач екрана може назвати й натиснути
WebAIM Million, 202695,9% з мільйона головних сторінок не проходять автоматичних перевірок WCAG; 96% помилок — у шести категоріяхКонтраст, alt, лейбли, текст посилань і кнопок, lang
Facebook, 2020Понад 400 КБ стиснутого CSS на головній, із яких для першого екрана використовувалося близько десятої частиниСпосіб безпечно видаляти CSS: локальність
Мобільний 100vh, до 2022Повноекранні макети обрізані під панеллю браузера на кожному телефоніОдиниці для справжньої видимої висоти: svh, dvh

Domino’s — той самий провал через десятиліття, коли юридичне питання вже вирішено. Ґільєрмо Роблес, незрячий, не зміг замовити піцу через сайт чи застосунок зі зчитувачем екрана й у 2016 році подав позов. У січні 2019 року Апеляційний суд дев’ятого округу постановив, що закон про права людей з інвалідністю (ADA) поширюється на сайт і застосунок компанії, коли вони пов’язані з її фізичними закладами, а в жовтні 2019 року Верховний суд США відмовився розглядати апеляцію Domino’s. Відтоді недоступне оформлення замовлення в США — це юридичний ризик, а не пункт беклогу. WebAIM Million показує, наскільки практика від цього далека: лютневе сканування 2026 року, що охопило мільйон головних сторінок, знайшло порушення на 95,9% із них, а 96% усіх помилок припали на шість категорій — низькоконтрастний текст, відсутній alt, поля форм без лейблів, порожні посилання, порожні кнопки й відсутній lang. Кожна з шести — умовність, яку ця сторінка вже описала.

Щоб купити ту саму властивість, їхній інструментарій не потрібен. Стилі стають непідтримуваними майже ніколи не через розмір. Причина в тому, що ніхто не може передбачити, що зламає видалення правила, — а це стається, коли селектори тягнуться через межі компонентів: правило у файлі шапки стилізує щось у підвалі, бо обидва підпали під .card h3. Хоч би яку методологію ви взяли, щоб цьому запобігти, — конвенцію імен, CSS-модулі, скоуповані стилі у фреймворку чи шари плюс дисципліну, — властивість, яку ви купуєте, та сама: локальність, щоб зміна лишалася там, де ви її зробили.

Останній рядок — кейс іншого роду: рішення платформи, а не помилка команди. Мобільні браузери визначили 100vh як висоту зі схованою адресною панеллю, тож роками кожен повноекранний банер був вищим за екран, на якому відкривався, а обхідними шляхами були скрипти, що вимірювали вікно. CSS виправив це в корені трьома одиницями — svh, lvh, dvh, — які з’явилися в Safari в березні 2022 року і в Chrome у листопаді 2022-го. Якщо код досі задає висоту з window.innerHeight, він несе обхід проблеми, якої вже немає.

Де це вироджується

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

  • Div з обробником кліку замість кнопки — невидимий для клавіатури й для будь-якої допоміжної технології.
  • outline: none на фокусі без заміни робить навігацію клавіатурою неможливою для відстеження.
  • Заголовки, обрані за розміром, руйнують структуру документа, за якою люди орієнтуються.
  • Гонка !important і її близнючка, гонка z-index, — кожна сторона може відповісти лише більшою версією того самого ходу.
  • Селектори, що тягнуться через межі компонентів, — жодне правило не можна безпечно видалити.
  • Магічні числа — margin-top: 37px — кодують один розмір екрана й ламаються на наступному.
  • Зображення без розмірів — текст стрибає під пальцем читача, поки сторінка вантажиться.
  • Оверлей доступності — один скрипт, що обіцяє полагодити сторінку, — замість виправлення розмітки. У 2025 році Федеральна торгова комісія США змусила accessiBe заплатити $1 млн за твердження, що її віджет робить будь-який сайт сумісним із WCAG.
  • Ідеальна автоматична оцінка доступності, яку вважають фінішем, а не першою перевіркою.

Є й чесна межа, і вона важливіша за будь-який рядок таблиці. Усе на цій сторінці змушує браузер робити те, що ви мали на увазі. Ніщо з цього не каже, чи тим, що ви мали на увазі, можна користуватися. Автоматичні перевірки бачать у кращому разі частину: коли Government Digital Service (GDS) уряду Великої Британії у 2017 році зробила тестову сторінку зі 143 навмисними бар’єрами, найкращий із десяти інструментів знайшов 41% із них, усі десять разом — 71%, а 29% не знайшов жоден, — серед них посилання, позначені лише кольором, які проходять кожне правило, що його може перевірити машина.

Відповідь дешева й не має заміни. Відкладіть мишу й попрацюйте зі сторінкою самою лише клавіатурою п’ять хвилин. Увімкніть зчитувач екрана, який уже є у вашій операційній системі, — VoiceOver на Mac чи iPhone, Narrator у Windows, TalkBack на Android — і спробуйте виконати одну задачу, заради якої сторінка існує. Відкрийте її на справжньому телефоні середнього класу з повільним з’єднанням. Десять хвилин цього знаходять те, чого не знайде жоден лінтер, і це єдина перевірка на цій сторінці, яка тестує обіцянку, а не код.

Коли це застосовувати

Застосовуйте, коли

  • Завжди — кожен фреймворк із цього списку зрештою зводиться до цих двох мов.
  • Для контентних сторінок беріть чистий HTML і CSS: фреймворк додасть витрат і жодної нової спроможності.
  • Беріть рідні елементи раніше за ARIA, а ARIA — лише щоб описати те, що ви справді реалізували.
  • Беріть шари каскаду, коли інтегруєте сторонні стилі, які не можете редагувати.

Уникайте, коли

  • Робити руками віджети, які вже є рідними: діалог, розкривний блок, поле дати.
  • Додавати методологію CSS у проєкт, достатньо малий, щоб локальність ще не була проблемою.
  • Відтворювати систему розкладки в JavaScript, бо слухач resize здався простішим за grid.
  • Оверлей доступності замість виправлення розмітки: він не полагодить того, чого HTML ніколи не обіцяв.
  • Оптимізувати швидкість селекторів — це не було справжнім вузьким місцем понад десять років.

Джерела й метод

На чому стоїть ця стаття

  • 13 джерел
  • 3 задокументовані збої
  • Перевірено 13 жовтня 2026 р.

Дослідження з Claude. Пошук і звірку першоджерел зроблено з Claude (Anthropic). Відбір, текст і перевірку фактів — редакція Anatomy of IT Product.

Було корисно?

Поділіться з тим, хто працює над тією ж задачею.