Кросбраузерність і адаптивна верстка
Зміст
«У мене все працює» — фраза, після якої тікет закривають неправильно. Сайт, що бездоганно поводиться на робочому ноутбуці, не доводить нічого про телефон користувача, про корпоративний браузер із режимом сумісності чи про людину, яка читає сторінку читачем екрана. Другий бік тієї самої монети — звіт «на мобільному все поїхало» без жодної деталі, з якого неможливо зробити навіть перший крок.
Ця глава — повний виклад теми на сайті: інші глави посилаються сюди по матрицю браузерів, й . Мета — два вміння: назвати, що входить у периметр підтримки, і за хвилину відрізнити «браузери різні, тому й поведінка різна» від «це дефект застосунку».
Периметр: три різні речі під одним словом
Кросбраузерне тестування (cross-browser testing) — практика перевірки, що сайт працює в різних браузерах і на різних пристроях. Периметр ширший, ніж здається, бо в нього входять три різні речі:
- старіші браузери, які не підтримують найновіших можливостей JS і CSS;
- різні класи пристроїв — від настільних компʼютерів і ноутбуків до планшетів, смартфонів і смарт-ТВ із дуже різними апаратними можливостями;
- люди з інвалідністю, які покладаються на допоміжні технології — читачі екрана — або користуються самою лише клавіатурою.
Установка, з якої варто починати, сформульована в матеріалах MDN як гасло: ти — не твій користувач. Те, що сайт працює на машині розробника чи тестувальника, не доводить нічого.
Найдорожча помилка тут — вважати критерієм піксельну ідентичність. Сайт не мусить давати однаковий досвід у всіх браузерах, доки базова функціональність доступна в якийсь спосіб: у сучасному браузері може бути анімований тривимірний елемент, у старішому — плаский графічний із тією самою інформацією, і обидва варіанти прийнятні. Тому «у Safari тінь на два пікселі інша» — здебільшого не дефект, а «у Safari не працює кнопка оплати» — дефект безумовний: базова функціональність недоступна.
Покрити геть усі браузери й пристрої практично неможливо, тому діапазон підтримки має бути домовленістю з власником продукту — між трьома стратегіями: вирівняти поведінку в усіх цільових браузерах (зокрема поліфілами — polyfill); свідомо дати спрощений, але прийнятний варіант; або відмовитися від підтримки старих браузерів за згодою замовника чи користувацької бази.
Третій периметр тут лишається саме периметром: доступність — частина тієї самої матриці , а її предмет (семантика розмітки, критерії, читачі екрана, автоматичні перевірки) розбирає глава «Семантичний HTML і доступність (a11y)».
Чому цей клас дефектів мовчить
Причин кросбраузерних розбіжностей MDN називає три, і тримати їх окремо корисно, бо лікуються вони по-різному. Перша — вади й розбіжності реалізацій: браузери іноді мають баги або реалізують ту саму можливість по-різному. Друга — різний рівень підтримки можливостей: неминуче, коли йдеться про найновіші можливості або про давно заморожені браузери. Третя — обмеження самого пристрою: малий екран, слабкий процесор.
Типові проблеми HTML і CSS зводяться до двох областей — брак підтримки нових можливостей і проблеми розкладки. А головна властивість цього класу дефектів — тиша. Якщо браузер не розуміє CSS-оголошення чи правило, він просто пропускає його: без застосування й без помилки. Те саме з медіазапитами, @font-face і блоками @supports. Нерозпізнані HTML-елементи браузер трактує як анонімні рядкові — без семантичного значення, як span.
Пастка
«У консолі чисто» тут не доводить нічого: симптом «у Chrome є, у Safari немає» майже ніколи не супроводжується червоним рядком. Дивитися треба на вигляд і поведінку, а не на журнал помилок.
Далі — каталог, у якому впізнається більшість реальних тікетів:
- Один невалідний селектор вимикає цілий блок. У списку через кому помилковий селектор просто ні до чого не підійде, а невалідний — вимкне весь список разом зі стильовим блоком. Симптом кросбраузерний: у браузері, який один із селекторів списку не розпізнає, зникає цілий блок стилів, а там, де розпізнає, усе на місці.
- Самотній
-webkit-. Префікси вендорів (-moz-— Firefox,-webkit-— Chrome, Edge, Opera, Safari; у старому коді ще-ms-та-o-) призначалися для експериментальних реалізацій. Найпоширеніший дефект — узяти лише-webkit--версію властивості; це траплялося настільки часто, що інші вендори самі реалізували-webkit--префіксовані версії кількох властивостей. - Префікси в продакшені взагалі. Їх можуть змінити чи прибрати без попередження, вони бʼють по продуктивності старих версій і самі є джерелом кросбраузерних проблем. Правильний шлях — детекція можливостей через
@supports. - Конфлікт імен зі стороннім кодом. Клас із CSS-фреймворка або з розмітки, яку генерує стороннє API (наприклад, рекламний банер), збігається з вашим — і верстка їде.
- Помилки розмітки, яких не видно. У DevTools помилки HTML майже не спливають: браузер сам «лагодить» криву розмітку, тож шукати їх треба валідатором W3C — це окремий крок. Незастосовані CSS-оголошення інспектор натомість показує перекресленими з трикутником-попередженням.
- Адаптивність і роздільна здатність. Сайт гарний на десктопі й нестерпний на мобільному (дрібний вміст, важкі анімації); мобільним не потрібні важкі зображення, але дрібні картинки на щільних екранах виглядають пікселізовано.
Три довідники, які MDN називає основними для питання «а це взагалі підтримується»: сам MDN, stackoverflow.com і caniuse.com.
Рядок матриці — це рушій, а не логотип
(rendering engine) — частина браузера, яка перетворює HTML, CSS та інші ресурси сторінки на візуальне подання на екрані. Термінологічна деталь, на якій плутаються: «рушій рендерингу» і «рушій браузера» (browser engine) — назви одного поняття, а не двох підсистем; MDN уживає browser engine, rendering engine і layout engine як синоніми.
MDN називає поширеними чотири:
| Рушій рендерингу | Хто на ньому |
|---|---|
| Blink | Chromium, а отже й Chrome; починався як форк бібліотеки WebCore із WebKit |
| Gecko | Firefox — рушій розкладки від Mozilla Project |
| WebKit | Safari від Apple, а також багато мобільних браузерів |
| Trident | рушій Internet Explorer; його ж вмикає режим IE (IE mode) в Edge |
Це перелік рушіїв, а не браузерів, — і саме тому матриця має менше по-справжньому різних рядків, ніж логотипів:
MDN кладе Chrome, Edge й Opera в один пункт прикладу матриці саме тому, що Edge й Opera стоять на тому самому рушії рендерингу, що й Chrome; Microsoft, зі свого боку, називає Chromium рушієм, на якому побудований Edge, а рушій рендерингу Chromium — Blink. Safari стоїть на WebKit — окремий рядок, який перевіркою в Chrome не закривається.
Trident при цьому не суто історичний рядок: його вмикає режим IE в Edge, і оновлення безпеки для нього тривають до 2029 року. Тобто корпоративний Edge із увімкненим режимом IE рендерить сторінку не Blink-ом — це конкретний сценарій матриці, а не археологія.
І нюанс, який рятує від хибної класифікації: рушій — це не лише «малювання». Gecko, наприклад, містить ще й мережевий стек, графічний стек і віртуальну машину JavaScript, тож кросбраузерна різниця може виявитися не розкладкою, а поведінкою мережі чи JS-середовища. (Архітектура браузера як цілого й конвеєр рендерингу — глава «Архітектура браузера й рендеринг»; як окреме поняття — глава «Виконання JavaScript та event loop»; поширеність версій протоколу — глава «HTTP/2 і HTTP/3: еволюція протоколу».)
Наша практика (не канон). Далі — правило, яким користуються команди; окремого стандарту під нього немає. Один рушій рендерингу — один рядок матриці: дефект розкладки, знайдений у Chrome, з високою ймовірністю відтвориться в Edge, а перевірка в Chrome не заміняє перевірки в Safari. Джерела кладуть браузери зі спільним рушієм в один пункт матриці, але про ймовірність відтворення конкретного дефекту не говорить жодне з них.
Звідки беруться рядки матриці
Матриця — не список улюблених браузерів команди, а зріз аудиторії. Коли зрозуміло, які можливості потрібні продукту, наступний крок — дослідити, якими браузерами й пристроями користуються люди, для яких сайт роблять. Часто такі дані вже є у замовника: з попередніх досліджень, з інших його сайтів або з попередньої версії цього самого.
Типовий приклад із MDN: сайт електронної комерції для Північної Америки має повністю працювати в останніх кількох версіях найпопулярніших десктопних і мобільних браузерів — Chrome (разом з Edge й Opera, бо вони на тому самому рушії рендерингу), Firefox і Safari — і додатково відповідати WCAG рівня AA (самі критерії й рівні — предмет глави про доступність).
Якщо даних про аудиторію ще немає, є готовий мінімальний кістяк — базовий набір браузерів Baseline: Chrome (десктоп і Android), Edge, Firefox (десктоп і Android), Safari (macOS та iOS). Комбінаторику, яка з цього виростає (браузер × версія × операційна система), звужують конфігурацій — це техніка тест-дизайну, і її канон живе в розділі про тест-дизайн, не тут.
Baseline: чи можна вже користуватися цією можливістю
Baseline — спільна для індустрії позначка «наскільки безпечно вже користуватися цією можливістю вебплатформи»: замість ручного зіставлення версій браузерів вона дає одну відповідь про рівень сумісності. Позначку започаткувала команда Chrome, а нині її визначає спільнотна група WebDX — тобто це не мітка одного вендора.
Стадій у Baseline дві, і одразу варто зняти найпоширенішу плутанину: Limited availability — не третій рівень, а стан до Baseline.
| Стан | Що означає |
|---|---|
Limited availability (поза Baseline) | можливість ще не підтримана в усіх браузерах базового набору |
Newly available (стадія 1) | підтримують усі браузери базового набору, тобто можливість сумісна |
Widely available (стадія 2) | від дати сумісності минуло 30 місяців — більшість сайтів може користуватися, не переймаючись підтримкою |
Для тестувальника це обʼєктивний аргумент у суперечці «це баг чи просто не підтримується»: якщо можливість має стан Limited availability, вона ще не підтримана всюди, тож різна поведінка в частині браузерів матриці очікувана. Але й Newly available не означає «можна всюди»: сумісність зафіксовано щойно, а обіцянку «не перейматися підтримкою» джерело дає лише на другій стадії, через 30 місяців.
Наша практика (не канон). Причину 30-місячного відступу джерело не пояснює — воно дає лише число. Ми читаємо його так: на пристроях зі старішими версіями браузерів можливості ще немає, і саме на це закладено запас.
Адаптивність — це поведінка розкладки
Адаптивний вебдизайн (responsive web design) — підхід, за якого сторінка коректно відображається на всіх розмірах екрана й роздільностях зі збереженням зручності користування. Ключове слово — підхід: це не окрема технологія, а набір практик, тому «перевірити адаптивність» означає перевірити поведінку розкладки, а не наявність конкретної бібліотеки. Термін увів Ітан Маркотт у 2010 році, описавши тріаду: гумові сітки, гумові зображення й медіазапити.
Контрінтуїтивний факт, з якого варто починати: сам HTML адаптивний за природою — сторінка без CSS переливає текст під розмір області перегляду при зміні вікна. Ламає адаптивність уже CSS із фіксованими розмірами: фіксована ширина дає горизонтальну прокрутку на вузьких екранах і надлишок порожнечі на широких. Flexbox і CSS Grid адаптивні за замовчуванням: елементи стискаються й розтягуються за наявним місцем, тож цілитися пікселедосконало в кожен розмір пристрою не потрібно.
Медіазапит (media query) — набір перевірок (наприклад, чи ширший екран за певне значення), за якими вибірково застосовують CSS. Точку, у якій медіазапит спрацьовує й розкладка змінюється, називають брейкпоінтом (breakpoint). Поширений підхід — mobile first: проста одноколонкова розкладка для вузьких екранів, а багатоколонкова додається, коли ширини вистачає. Окрема рекомендація, яку ігнорують найчастіше: брейкпоінти задають у відносних одиницях, а не за розмірами конкретного пристрою. Медіазапити при цьому взагалі не обовʼязкові — гнучкі сітки, відносні одиниці та мінімальні й максимальні значення дають адаптивність і без них.
Пастка
«Перевірили на iPhone 14, iPad і ноутбуку» — це не план тестування адаптивності. Пристрої змінюються, а брейкпоінти — властивість вашої сторінки: перевіряти треба їх, а вже потім конкретні пристрої з матриці.
Звідки беруться числа брейкпоінтів
Питання «на яких саме ширинах перевіряти» звучить на кожному проєкті, і чесна відповідь дратує: канонічного списку «типових» значень немає, і це позиція джерел, а не прогалина в документації. Брейкпоінти не визначають за класами пристроїв, продуктами, брендами чи операційними системами — такий код важко підтримувати, і замість цього розкладку диктує сам вміст.
Метод підбору описаний прямо — від малого вгору: спершу зробити вміст придатним для вузького екрана, потім розширювати, доки черговий брейкпоінт не стане потрібним. Так їх виходить мінімальна кількість, і всі під вміст. Критерій «пора ставити точку» визнано субʼєктивним: у прикладі web.dev вирішують, що понад 600px порожнечі між елементами вже забагато, і саме під це число роблять два медіазапити — @media (max-width: 600px) і @media (min-width: 601px). Тобто 600px тут — результат розгляду конкретного компонента, а не значення зі списку «популярних розмірів». Другий приклад числа з вмісту: класична теорія читабельності радить 70–80 символів (приблизно 8–10 англійських слів) на рядок, тож брейкпоінт варто ставити, коли блок тексту переростає приблизно 10 слів у рядку.
Звідси два висновки для тестувальника. Перший: значення брейкпоінтів дізнаються з коду або з DevTools, а не з памʼяті. Другий: крім великих брейкпоінтів, де змінюється розкладка, бувають малі — між ними правлять відступи чи розмір шрифту. Візуальних змін більше, ніж «перемикань колонок», і частина дефектів живе саме там.
Базовий прийом проти горизонтальної прокрутки — не давати медіа вилазити за : img, picture, video { max-width: 100% }. Адаптивна типографіка робиться так само просто — зміною розмірів шрифту в медіазапитах або через одиниці області перегляду.
Область перегляду: чому адаптив «не працює на мобільному»
Це місце, де ламається найбільше верстки, і діагностується воно за секунди.
Область перегляду (viewport) — видима частина вікна, у якій показується вебконтент. Її розмір обчислюється до розкладки сторінки й задає, у скільки місця (насамперед по горизонталі) має вміститися вміст; що не вміщається — те браузер віддає на прокрутку.
Проблема в тому, що мобільні браузери схильні брехати про ширину своєї області перегляду. Частина мобільних пристроїв і вузьких екранів рендерить сторінку у віртуальній області перегляду, ширшій за екран, а потім стискає результат: при екрані 640px сторінка може рендеритися у віртуальній області 980px і масштабуватися вниз. Наслідок катастрофічний: якщо віртуальна область — 980px, медіазапити на 640px, 480px і менше не спрацюють ніколи. Адаптив написано, він коректний, і його ніхто не побачить.
Ліки — метатег viewport. Це не стиль і не скрипт, а підказка браузеру про те, яким має бути розмір області перегляду; поведінка задається парами «ключ=значення» в атрибуті content:
<meta name="viewport" content="width=device-width, initial-scale=1" />
width задає (мінімальну) ширину області перегляду — ціле число пікселів від 1 до 10000 або спеціальне значення device-width, тобто фізичну ширину екрана в CSS-пікселях; саме від неї рахується одиниця vw. initial-scale — співвідношення між шириною пристрою й розміром області перегляду, тобто початковий масштаб.
Пастка
Перший чек за звітом «на мобільному все поїхало» — не верстка, а head: чи є там метатег viewport і чи стоїть у ньому width=device-width. Без нього медіазапити на вузькі екрани не спрацюють узагалі, і шукати помилку в CSS марно.
Масштабування, щільність екрана й клавіатура
Ключ user-scalable дозволяє або забороняє користувачеві масштабувати сторінку. Браузер має право це проігнорувати — iOS від 10-ї версії ігнорує , — але сама спроба вже проблемна: вимкнення масштабування заважає людям із порушеннями зору читати й розуміти вміст. Це один із найдешевших чеків доступності в адаптивному тестуванні; сам предмет — у главі «Семантичний HTML і доступність (a11y)».
Друге, що плутають: CSS-піксель — не апаратний піксель. Роздільності виросли настільки, що окремі пікселі око не розрізняє, тому браузери малюють один CSS-піксель кількома апаратними. Наслідок: текст лишається чітким, а растрові зображення можуть не використати повну роздільність екрана — тобто виглядають нечітко, якщо не дати версію більшої роздільності. Кількість фізичних пікселів на один CSS-піксель називають співвідношенням пікселів пристрою (device pixel ratio, DPR); типове значення залежить від щільності екрана — 1.0 при щільності менше 200dpi, 1.5 при 200–300dpi і ціла частина density/150dpi при понад 300dpi, причому лише за масштабу області перегляду, що дорівнює 1.
Третє — інтерактивні віджети, насамперед віртуальна клавіатура. Їхній вплив задає ключ interactive-widget; за замовчуванням діє resizes-visual, і тут важливо не переказати джерело навпаки: за дефолтом клавіатура змінює лише візуальну область перегляду й розкладку сторінки не зачіпає. Щоб розкладка адаптувалася до клавіатури, значення треба явно поставити в resizes-content (є ще overlays-content, за яким не змінюється жодна з областей). Тож «верстка стрибає, коли відкривається клавіатура» — не очікуваний ефект дефолту: спершу перевірте, чи не стоїть у метатезі resizes-content, і лише потім заводьте дефект.
Режим пристрою в DevTools і де проходить його межа
Режим пристрою (device mode) — набір можливостей Chrome DevTools для симуляції мобільних пристроїв: симуляція мобільної області перегляду, обмеження ЦП і мережі, а через панель Sensors — геолокація, орієнтація, примусовий дотик і стан бездіяльності.
Найкорисніша для адаптивності функція — показ брейкпоінтів. Панель стартує в режимі Responsive: ширину тягнуть маркерами або вводять числом. Смуги над областю перегляду показують реальні брейкпоінти сторінки: синя — точки max-width, помаранчева — min-width; клацання між ними перемикає ширину так, щоб потрібна точка спрацювала, а через контекстне меню відкривається відповідне оголошення @media у вихідному коді. Тобто брейкпоінти не вгадують — їх бачать. Тут же виставляють DPR вручну й знімають екран цілою сторінкою, а не лише видимою частиною.
Друга важлива деталь: тип пристрою впливає не лише на вигляд. Він визначає, чи рендериться сторінка як мобільна чи як десктопна, який курсор показується і які події породжує взаємодія — сенсорні (touch) чи кліки. Тому баг «на мобільному не працює свайп» відтворюється саме перемиканням типу пристрою, а не звуженням вікна.
Обмеження мережі й ЦП зібрані в пресети: Mid-tier mobile — швидкий 3G і вчетверо повільніший ЦП, Low-end mobile — повільний 3G і вшестеро повільніший. Застереження, без якого з цього роблять хибний : сповільнення відносне до потужності вашої машини, тож цифри не переносяться між компʼютерами один в один. (Сама панель Network — глава «DevTools: вкладка Network і дебаг».)
Пастка
Головне обмеження названо в документації прямо: режим пристрою — «наближення першого порядку» того, як сторінка виглядає й почувається на мобільному. Код виконується не на пристрої, а на вашому компʼютері, і частину аспектів — наприклад, архітектуру мобільних ЦП, яка суттєво відрізняється від настільної, — DevTools не змоделює ніколи. Саме тут проходить межа між «перевірив адаптивність» і «перевірив на мобільному».
Реальні пристрої: лабораторія, ферми й порядок процесу
Процес MDN описує чотирма фазами — планування, розробка, тестування й виявлення, виправлення та ітерації — і одразу пояснює, чому це не «етап наприкінці»: якщо лишити все тестування на кінець проєкту, знайдені баги коштуватимуть значно дорожче й довше, ніж якби їх ловили дорогою.
Мінімальний ручний обхід теж названий: сучасні десктопні браузери — Firefox, Chrome, Opera, Edge й Safari, в ідеалі на macOS, Windows і Linux — плюс поширені мобільні: Safari на iPhone та iPad, Chrome і Firefox на iPhone, iPad та Android. Корисно перевіряти й передрелізні збірки, щоб зловити зміну поведінки до того, як вона доїде до користувачів. Зі зростанням проєкту ручний обхід матриці стає надто довгим — звідси аудит-інструменти, автоматизація й порівняння знімків екрана між браузерами (візуальна як інструмент — предмет розділу про інструменти автоматизації).
Реальний пристрій із потрібним браузером дає найбільшу точність щодо поведінки й загального досвіду користувача, тому мінімальна лабораторія пристроїв () починається з фізичного заліза: Mac, Windows-ПК, телефон і планшет на Android, телефон і планшет на iOS — кожен із потрібними браузерами. Окремим пунктом іде порада, яку зазвичай ігнорують: тримати ще й пару слабких мобільних пристроїв, щоб перевіряти продуктивність (наприклад, анімації) на слабких процесорах. Інакше «гальмує в користувачів» не відтвориться ніколи — на флагмані все плавно.
Далі — питання грошей. Великі компанії тримають лабораторії з дуже великим набором апаратів і ловлять дефекти на конкретних комбінаціях «браузер + пристрій»; менші команди обходяться меншими наборами, емуляторами (програмами, що відтворюють пристрій або його умови), віртуальними машинами й комерційними сервісами. Із комерційних ферм MDN називає Sauce Labs і Browser Stack; альтернатива — власна система автоматизації (популярний вибір — Selenium), яка вимагає налаштування, але окупається. Існують і публічні лабораторії пристроїв (Open Device Labs). Віртуальні машини лишаються потрібними там, де дві версії того самого браузера поруч не ставляться (класика — IE та Edge на Windows): під кожну версію тримають окремий .
Пастка
Ферма пристроїв — рядок бюджету, який має випливати з матриці, а не навпаки. Спочатку матриця браузерів і пристроїв, потім рішення: що з неї закриває емулятор, що — власне залізо, а що доводиться орендувати. «Перевірили на своєму телефоні» не закриває ані слабкого заліза, ані рушія, якого у вас немає.
Локалізація кросбраузерного дефекту
Тут головна навичка — звузити, а не описати. Порядок простий: спершу зібрати конфігурацію — платформу, пристрій і версію браузера від репортера; потім перевірити схожі конфігурації — ту саму версію браузера на різних платформах або кілька різних версій того самого браузера на одній платформі, щоб зрозуміти, наскільки широко дефект відтворюється; і третє, про що забувають, — припустити, що це може бути не ваша вина: дефект може бути в самому браузері, і тоді його заводять вендору, а в продукті шукають обхідний шлях.
Звідси й вимога до звіту: «на мобільному зʼїхала кнопка» без пристрою, платформи й версії браузера непридатний до роботи.
Типові помилки
- Виглядає як «у консолі чисто, отже CSS у порядку», а насправді нерозпізнане оголошення браузер пропускає мовчки — без застосування й без помилки.
- Виглядає як «сайт має виглядати однаково скрізь», а насправді критерій приймання — доступність базової функціональності, а різниця у вигляді часто є свідомим спрощенням.
- Виглядає як «перевірили Chrome, Firefox, Edge, Opera — чотири браузери», а насправді це два рушії рендерингу: Edge і Opera закриваються тим самим рядком, що й Chrome, а Safari — ні.
- Виглядає як «дефект розкладки в CSS», а насправді на мобільному немає метатегу viewport, і жоден медіазапит на вузькі екрани просто не вмикається.
- Виглядає як «перевірили на iPhone 14 і iPad — адаптивність готова», а насправді перевірено дві ширини, а брейкпоінти сторінки ніхто не подивився.
- Виглядає як «у режимі пристрою все добре, отже на мобільному працює», а насправді код виконався на вашому компʼютері: сенсорні події симульовані, а мобільний процесор не змодельований узагалі.
- Виглядає як баг верстки, а насправді можливість має стан
Limited availabilityі в частині браузерів матриці ще не підтримана — очікувана різниця.
Підсумок
- Периметр — не «браузери», а три речі: старіші браузери, класи пристроїв і люди з інвалідністю; діапазон підтримки — домовленість із власником продукту, а не «тестуємо все».
- Критерій приймання — доступність базової функціональності, а не піксельна ідентичність; пріоритет дефекту рахується від функції, а не від різниці у вигляді.
- Цей клас дефектів мовчить: нерозпізнаний CSS ігнорується без помилки, тож чиста не є доказом, а помилки розмітки шукають валідатором.
- Рядок матриці — це рушій рендерингу, а не логотип: Blink, Gecko й WebKit дають менше різних відповідей, ніж назв браузерів.
- Адаптивність перевіряють у брейкпоінтах конкретної сторінки й лише за наявності метатегу viewport; режим пристрою закриває адаптивність, але не заміняє реального пристрою.
Можливі питання
- «Що входить у кросбраузерне тестування?» Перевіряють ширину картини світу. Слабка відповідь — «перевірити сайт у Chrome, Firefox і Safari»; сильна називає три периметри й додає, що діапазон підтримки узгоджують із власником продукту.
- «Сайт у Safari виглядає інакше, ніж у Chrome. Це дефект?» Питання про критерій приймання. Очікують: залежить від того, чи доступна базова функціональність, — і приклад, коли різниця у вигляді прийнятна, а коли ні.
- «Скільки браузерів треба в матриці й звідки взяти список?» Дивляться, чи не почнете перелічувати улюблені браузери. Сильна відповідь: із даних про аудиторію, а рядки групуються за рушієм рендерингу; базовий набір Baseline — стартовий кістяк, коли даних ще немає.
- «Верстка не адаптується на мобільному. Ваші дії?» Міні-кейс, у якому слухають порядок: спершу метатег viewport, потім брейкпоінти сторінки в DevTools, і лише тоді сам CSS.
- «Чим режим пристрою в DevTools відрізняється від реального пристрою?» Перевіряють, чи розумієте межу інструмента. Очікують: код виконується на вашій машині, ширина й сенсорні події симульовані, обмеження ЦП відносне до вашого заліза, а мобільна архітектура не моделюється.
- «Як ви локалізуєте кросбраузерний баг?» Слухають метод звуження: конфігурація від репортера, схожі конфігурації (та сама версія на різних платформах і різні версії на одній), і допущення, що дефект може бути в самому браузері.
Джерела
Периметр: три різні речі під одним словом
- MDN — Introduction to cross-browser testing — периметр і означення, гасло «ти — не твій користувач», критерій «не піксельна ідентичність», діапазон підтримки як домовленість, три стратегії.
Чому цей клас дефектів мовчить
- MDN — Introduction to cross-browser testing — три причини дефектів і довідники підтримки можливостей.
- MDN — Handling common HTML and CSS problems — дві області проблем, мовчазне ігнорування нерозпізнаного й каталог дефектів.
Рядок матриці — це рушій, а не логотип
- MDN — Rendering engine (Glossary) — означення, синонімія назв, перелік поширених рушіїв.
- MDN — Blink (Glossary) — Blink як рушій Chromium і Chrome та його .
- MDN — Gecko (Glossary) — Gecko під Firefox і його склад: мережевий стек, графіка, віртуальна машина JavaScript.
- MDN — WebKit (Glossary) — WebKit під Safari й багатьма мобільними браузерами.
- MDN Glossary — Trident — рушій Internet Explorer, режим IE в Edge, підтримка до 2029 року.
- MDN — Introduction to cross-browser testing — Chrome, Edge й Opera одним пунктом матриці за спільним рушієм.
- Microsoft Learn — Site compatibility-impacting changes coming to Microsoft Edge — Chromium як рушій, на якому побудований Edge.
- MDN — Introduction to cross-browser testing — матриця з даних про аудиторію й приклад матриці для електронної комерції.
- web.dev — Baseline (Web Platform Baseline) — призначення позначки, походження (Chrome → WebDX), дві стадії,
Limited availabilityпоза Baseline, базовий набір браузерів.
Адаптивність — це поведінка розкладки
- MDN — Responsive web design — адаптивність як підхід, тріада Маркотта, гумовий за природою HTML, медіазапити й брейкпоінти, mobile first, відносні одиниці, обмеження медіа контейнером, адаптивна типографіка.
- web.dev — Responsive web design basics — відсутність канонічного списку значень, підбір від малого вгору, субʼєктивність критерію з прикладом 600px, великі й малі брейкпоінти, довжина рядка 70–80 символів.
Область перегляду: чому адаптив «не працює на мобільному»
- MDN —
<meta name="viewport">(viewport meta element) — область перегляду й метатег як підказка, віртуальна область 980px і зрив медіазапитів,width=device-widthтаinitial-scale,user-scalable, CSS-піксель проти апаратного й таблиця DPR, значенняinteractive-widget. - MDN — Responsive web design — «мобільні браузери схильні брехати про ширину області перегляду» і метатег як перший чек за звітом про поїхану мобільну верстку.
Режим пристрою в DevTools і де проходить його межа
- Chrome DevTools — Simulate mobile devices with device mode — склад режиму пристрою, смуги брейкпоінтів і перехід до
@media, ручний DPR і знімок повної сторінки, вплив типу пристрою на події, пресети обмежень та їхня відносність, наближення першого порядку.
Реальні пристрої: лабораторія, ферми й порядок процесу
- MDN — Introduction to cross-browser testing — чотири фази процесу й ціна відкладеного тестування, мінімальний набір браузерів, передрелізні збірки, пріоритет реальних пристроїв, перехід до автоматизації.
- MDN — Strategies for carrying out testing — точність реального пристрою, склад лабораторії, слабкі пристрої, емулятори й віртуальні машини, комерційні ферми, Open Device Labs.
- Chrome DevTools — Simulate mobile devices with device mode — межа симуляції: за сумнівів перевіряють на реальному пристрої.
Локалізація кросбраузерного дефекту
- MDN — Introduction to cross-browser testing — порядок локалізації, перевірка схожих конфігурацій, дефект на боці браузера.
Що таке кросбраузерне тестування і що входить у його периметр?
Це перевірка того, що продукт лишається придатним до користування не лише на машині, де його зробили. Периметр складається з трьох окремих напрямків, і плутати їх не варто, бо покриваються вони по-різному: браузери попередніх поколінь, які не знають свіжих можливостей JS і CSS; класи пристроїв із різним залізом — від настільних машин до планшетів, смартфонів і телевізорів; і користувачі допоміжних технологій — читачів екрана — та ті, хто працює самою клавіатурою. Слабка відповідь на співбесіді зупиняється на першому пункті й перелічує три-чотири браузери. Сильна називає всі три напрямки й додає головне: покрити все неможливо, тому діапазон підтримки фіксують домовленістю з власником продукту, а не власним відчуттям. MDN формулює вихідну установку як гасло «ти — не твій користувач»: працездатність на робочому ноутбуці не доводить нічого.
Сторінка в Safari виглядає інакше, ніж у Chrome. Це дефект?
Залежить від того, що саме відрізняється. — доступність базової функціональності, а не збіг до пікселя: продукт має право давати різний досвід у різних браузерах, доки людина може зробити те, заради чого прийшла. Зсунута на два пікселі тінь або трохи інше згладжування шрифту — здебільшого не дефект; кнопка оплати, яка не реагує на клік, — дефект безумовний і без обговорень. Між цими полюсами живе третій варіант: свідоме спрощення, коли в сучасному браузері елемент анімований і обʼємний, а в старішому — плаский, але несе ту саму інформацію. Практичний наслідок для роботи з тікетами: пріоритет рахують від функції, до якої дефект перекриває доступ, а не від величини візуальної різниці.
Чому цей клас дефектів так важко зловити автоматично?
Бо він мовчить. Коли браузер натрапляє на CSS-оголошення чи правило, якого не розуміє, він просто йде далі: стиль не застосовується, а помилка не породжується. Так само поводяться медіазапити, @font-face і блоки @supports. Нерозпізнаний HTML-елемент теж не викликає скарги — браузер трактує його як звичайний рядковий без семантики. Звідси головна пастка звітів: аргумент «у консолі чисто, значить із версткою все гаразд» тут не працює взагалі. Дефект класу «в одному браузері елемент є, в іншому його немає» червоного рядка в журналі за собою зазвичай не лишає, тож судити доводиться по вигляду й поведінці, а не по логу. Помилки самої розмітки теж непомітні: браузер тихо лагодить криву структуру, тож їх шукають окремим прогоном через валідатор W3C.
Один селектор у стильовому блоці невалідний. Що станеться з рештою блоку?
Тут важлива різниця між «селектор ні до чого не підійшов» і «селектор невалідний». Якщо в переліку через кому один із селекторів просто не знаходить елементів, решта працює нормально. А от невалідний селектор скасовує весь перелік разом зі стильовим блоком, який до нього прикріплений. Кросбраузерним це робить те, що валідність залежить від браузера: там, де синтаксис розпізнано, блок застосовується, а в браузері, який його не знає, зникає цілий шматок оформлення. Симптом дуже характерний — «в одному браузері блок на місці, а в іншому зник цілком», причому в порожньо. У DevTools допомагає інша деталь: незастосовані оголошення інспектор показує перекресленими й позначає трикутником-попередженням.
Що таке рушій рендерингу і чому це важливіше за назву браузера?
— частина браузера, яка перетворює розмітку, стилі та інші ресурси сторінки на те, що людина бачить на екрані. Термінологічна деталь, на якій часто спотикаються: browser engine, rendering engine і layout engine — три назви одного поняття, а не три різні підсистеми. Поширених рушіїв чотири: Blink (Chromium, а отже й Chrome), Gecko (Firefox), WebKit (Safari й багато мобільних браузерів) і Trident (Internet Explorer). Для тестувальника з цього випливає головне: Chrome і Edge стоять на одному рушії, тому в матриці це один рядок, а дефект розкладки з одного з високою ймовірністю відтвориться в другому; Safari ж дає окрему відповідь, якої не замінить ніщо. І окремий нюанс, який рятує від хибної класифікації дефекту: рушій відповідає не тільки за малювання. До Gecko, скажімо, входять ще й робота з мережею, графічний шар і власна віртуальна машина для JavaScript. Тому те, що в тікеті названо кросбраузерною різницею, іноді виявляється розбіжністю в мережевій поведінці або в JS-середовищі, а до розкладки стосунку не має взагалі.
Ми перевірили Chrome, Firefox, Edge й Opera. Скільки рядків матриці закрито?
Два. Edge й Opera рендерять сторінку тим самим рушієм, що й Chrome, — Blink (сам Microsoft називає Chromium рушієм, на якому побудований Edge), тож це один рядок; Firefox на Gecko — другий. Safari на WebKit не закритий узагалі, а це саме той рядок, де найчастіше вилазить різниця. Тому чотири логотипи в звіті про виглядають переконливо й насправді означають менше, ніж здається. Продовження відповіді, за яке дають бали: списувати Trident в історію теж рано. Він оживає щоразу, коли в Edge вмикають режим сумісності з IE, а виправлення безпеки під нього випускають аж до 2029 року, — тобто корпоративне середовище з таким режимом лишається живим рядком матриці, а не археологією.
Звідки взяти список браузерів для матриці?
З даних про аудиторію продукту, а не зі списку улюблених браузерів команди. Спершу зʼясовують, які можливості платформи потрібні продукту, потім дивляться, чим користуються люди, для яких його роблять; по ці цифри рідко доводиться йти з нуля — замовник зазвичай уже має аналітику: із досліджень, із сусідніх своїх продуктів або з попередньої версії того самого сайту. Далі рядки групуються за рушієм рендерингу, тому реальний перелік виходить коротшим за перелік назв. Типовий приклад з MDN: магазин для північноамериканського ринку має бездоганно працювати в кількох останніх версіях найходовіших браузерів на десктопі й на мобільних — це Chrome, під яким одним пунктом ідуть Edge й Opera, далі Firefox і Safari, — а понад те відповідати рівню AA за WCAG. Коли даних про аудиторію ще нема, беруть готовий стартовий кістяк — базовий набір Baseline: Chrome для настільних систем і Android, Edge, Firefox у тих самих двох варіантах і Safari під macOS та iOS. Комбінаторику «браузер × версія × ОС» далі підрізають конфігурацій.
Що таке Baseline і як він допомагає в суперечці «це баг чи просто не підтримується»?
Baseline — індустріальна позначка : вона відповідає на питання, чи можна вже спокійно брати конкретну можливість платформи в роботу. Замість того щоб вручну зводити таблиці версій по кожному браузеру, команда дивиться на один показник сумісності. Народилася позначка в команді Chrome, але тепер її веде спільнотна група WebDX, тож приписувати її одному вендору неправильно. Стадій у ній рівно дві: Newly available означає, що можливість підтримують усі браузери базового набору, а Widely available настає через 30 місяців після дати сумісності — і саме на цій стадії джерело обіцяє, що про підтримку можна не думати. Головна плутанина — Limited availability: це не третій, найнижчий рівень, а стан до Baseline, коли підтримка є ще не всюди. Для тестувальника це обʼєктивний аргумент замість суперечки на смак: якщо можливість має стан Limited availability, різна поведінка в частині матриці очікувана. Пастка навпаки — прочитати Newly available як дозвіл писати код без огляду: сумісність там щойно зʼявилася, і на пристроях, які ще не оновилися, можливості немає. Право не думати про підтримку джерело віддає аж наступній стадії, і саме тому між ними лежать 30 місяців.
Що таке адаптивний вебдизайн і що конкретно ви в ньому перевіряєте?
Це підхід, за якого сторінка лишається зручною й коректно показаною на всіх розмірах екрана й роздільностях. Ключове слово тут — «підхід»: жодної окремої бібліотеки чи технології за ним не стоїть. Тому задача з формулюванням «перевір адаптивність» зводиться до спостереження за тим, як розкладка поводиться при зміні ширини, а не до пошуку якогось інструмента в складі проєкту. Автором терміна є Ітан Маркотт, який 2010 року описав його через три складники: гумові сітки, гумові зображення та медіазапити. Контрінтуїтивна деталь, яка добре показує глибину розуміння: сама по собі HTML-сторінка адаптивна за природою — без стилів текст спокійно переливається під ширину вікна. Зіпсувати цю властивість здатні вже стилі: варто прописати ширину числом, і на вузькому екрані вилізе горизонтальна прокрутка, а на широкому лишиться незаповнене поле. Flexbox і Grid, навпаки, поводяться адаптивно без додаткових зусиль: елементи самі підлаштовуються під доступний простір, тому потреби вимірювати кожен розмір пристрою окремо не виникає.
Що таке брейкпоінт і на яких ширинах ви перевіряєте сторінку?
Медіазапит — набір перевірок (наприклад, чи ширший екран за задане значення), за якими вибірково вмикається CSS; ширина, на якій він спрацьовує й розкладка перебудовується, і називається . Відповідь «перевіряю на 320, 768, 1024 і 1920» звучить упевнено й хибна по суті. Загальноприйнятого переліку «правильних» ширин просто не існує — так кажуть самі джерела, і це їхня свідома позиція, а не недописана документація. Привʼязувати брейкпоінти до моделей, брендів чи операційних систем не рекомендують: підтримувати такий код важко, а розкладку має диктувати вміст. Метод підбору описаний як рух знизу вгору: спершу довести до ладу вузький екран, далі розтягувати, аж поки черговий брейкпоінт не стане справді необхідним. Момент, коли він стає необхідним, визнано справою смаку — в ілюстрації web.dev автори просто вирішують, що близько 600 пікселів пустого місця між елементами — це вже занадто, і саме навколо цього числа ставлять пару правил @media (max-width: 600px) та @media (min-width: 601px). Друге число, яке виростає з вмісту, — довжина рядка: за класичною теорією читабельності комфортні 70–80 символів, тобто приблизно десять слів, і переростання цієї межі теж є приводом для брейкпоінта. Практичний висновок один: конкретні значення дивляться у стилях або в DevTools, покладатися на памʼять тут нема на що.
«Перевірили на iPhone 14, iPad і ноутбуці — адаптивність готова». Що не так із цією фразою?
Перевірено три ширини, а брейкпоінти конкретної сторінки ніхто не подивився. Пристрої змінюються щороку, а брейкпоінти — властивість вашої верстки, тому починати треба з них, а вже потім брати конкретні апарати з матриці. Друга частина проблеми — уявлення, що всі брейкпоінти перемикають колонки. Крім великих, де розкладка справді перебудовується, бувають малі: між ними правляться відступи, розміри шрифту, поля. Візуальних змін набагато більше, ніж «перемикань сітки», і чимала частина дефектів живе саме в цих проміжках. Мінімальний технічний чек, який закриває найпоширеніший симптом горизонтальної прокрутки, теж варто памʼятати: медіа не мають вилазити за контейнер, для чого існує правило img, picture, video { max-width: 100% }.
Що таке область перегляду і чому «на мобільному адаптив не працює»?
— видима частина вікна, у якій показується вміст сторінки. Її розмір рахується ще до того, як почнеться розкладка, і саме він визначає, у скільки горизонтального простору мусить укластися вміст; надлишок віддається прокрутці. Складність у тому, що на мобільних заявлена ширина часто не збігається з реальною: пристрій малює сторінку у віртуальній області, ширшій за власний екран, а вже потім стискає намальоване. Класична ілюстрація — екран на 640 пікселів, для якого сторінку рендерять як 980-піксельну й масштабують донизу. Наслідок руйнівний і зовсім не очевидний: якщо для сторінки ширина дорівнює 980, медіазапити на 640, 480 і менші значення не спрацюють ніколи. Адаптив написаний, він коректний, і його ніхто не побачить. Саме тому за звітом «на мобільному все поїхало» першим дивляться не CSS, а секцію head.
Що робить метатег viewport і які його ключі треба знати?
До стилів і скриптів він не належить узагалі — це вказівка браузеру щодо бажаного розміру області перегляду. Налаштування пишуть парами «ключ=значення» всередині атрибута content, а канонічний рядок виглядає так: <meta name="viewport" content="width=device-width, initial-scale=1" />. Ключ width задає ширину області перегляду — або цілим числом пікселів у діапазоні від 1 до 10000, або спеціальним значенням device-width, тобто фізичною шириною екрана в CSS-пікселях; від неї ж рахується одиниця vw. Ключ initial-scale задає початковий масштаб — співвідношення між шириною пристрою й розміром області перегляду. Практичний висновок для QA: відсутність цього тегу або відсутність у ньому width=device-width пояснює цілий клас звітів про «зламану мобільну верстку», і шукати помилку в стилях, поки тег не перевірено, — марна витрата години.
Чому user-scalable=no вважають проблемою, якщо браузери його все одно ігнорують?
Ключ user-scalable дозволяє або забороняє користувачеві масштабувати сторінку, і браузер справді має право проігнорувати заборону — iOS робить це за замовчуванням починаючи з десятої версії. Але сама наявність заборони в коді лишається дефектом доступності: люди з порушеннями зору покладаються на масштабування, щоб прочитати й зрозуміти вміст, і команда, яка це вимкнула, свідомо чи ні прибрала їхній основний інструмент. Для тестувальника це один із найдешевших чеків у всій адаптивній перевірці: подивитися вміст метатегу займає секунди, а знахідка йде в ту саму категорію, що й решта критеріїв доступності. Аргумент «Safari все одно не слухається» тут не рятує, бо матриця не складається з одного Safari.
Растрові зображення на телефоні виглядають нечітко, хоча в макеті все гарно. Чому?
Тому що CSS-піксель і апаратний піксель — різні речі. Роздільності екранів виросли настільки, що око не розрізняє окремі точки, і браузер малює один CSS-піксель кількома фізичними. Текст від цього тільки виграє — він лишається чітким за будь-якої щільності. А растрове зображення без версії більшої роздільності просто не має чим заповнити зайві фізичні пікселі, тож на щільному екрані виглядає розмито або пікселізовано. Те, скільки фізичних точок припадає на один CSS-піксель, називають співвідношенням пікселів пристрою (device pixel ratio, DPR). Значення визначає щільність екрана: до 200dpi воно дорівнює 1.0, у проміжку 200–300dpi — 1.5, а вище за 300dpi береться ціла частина від density/150dpi. Ця таблиця справедлива лише тоді, коли масштаб області перегляду дорівнює одиниці. Практичний бік для тестування: DPR у режимі пристрою виставляється вручну, тож перевірити цей клас дефектів можна без флагманського телефона.
Верстка стрибає, коли на телефоні відкривається клавіатура. Заводити дефект?
Спершу подивитися метатег, бо є ненульова ймовірність, що це налаштування, а не баг. Вплив інтерактивних віджетів на область перегляду задає ключ interactive-widget, і за замовчуванням діє resizes-visual: віртуальна клавіатура змінює лише візуальну область перегляду, а розкладку сторінки не зачіпає взагалі. Реакція розкладки вмикається лише явним значенням resizes-content. Є й третій варіант — overlays-content, за якого клавіатура не зачіпає жодної з областей перегляду. Тому послідовність така: якщо в метатезі стоїть resizes-content, перебудова розкладки — заявлена поведінка, і предметом дефекту може бути хіба що її конкретний візуальний результат. Якщо ж нічого явно не задано, а верстка все одно скаче, це вже привід писати тікет — з обовʼязковою вказівкою пристрою, платформи й версії браузера.
Як у DevTools дізнатися реальні брейкпоінти сторінки, а не вгадувати їх?
Режим пристрою відкривається в стані Responsive, де ширину або тягнуть маркерами, або вводять числом. Над областю перегляду показуються смуги з брейкпоінтами самої сторінки: синя відповідає точкам max-width, помаранчева — min-width. Клік по смузі підганяє ширину під потрібну точку, щоб та гарантовано спрацювала, а контекстне меню веде просто до того оголошення @media, яке за неї відповідає, — від симптому до рядка у стилях виходить два кліки. Поруч лежать ще дві корисні речі: ручне значення DPR і знімок екрана з усією сторінкою, а не лише з тим, що видно у вікні. Це той інструмент, який перетворює розмову «а на якій ширині перевіряти» з питання смаку на питання факту: брейкпоінти не вгадують, їх видно.
Чим режим пристрою в DevTools відрізняється від реального телефона?
Тим, що код виконується на вашому компʼютері. Документація Chrome прямо називає цей режим наближенням першого порядку — приблизною моделлю мобільного досвіду, а не самим досвідом, — і межа проходить рівно там: ширина симульована, сенсорні події породжені емуляцією, а архітектура мобільного процесора не моделюється взагалі й змодельована не буде. Обмеження мережі й ЦП зібрані в пресети — Mid-tier mobile дає швидкий 3G і вчетверо повільніший процесор, Low-end mobile — повільний 3G і вшестеро повільніший, — але сповільнення рахується відносно потужності вашої машини, тому переносити ці цифри між компʼютерами як критерій приймання не можна. Що режим пристрою справді закриває добре: адаптивність, брейкпоінти, DPR і клас дефектів «на мобільному не працює свайп» — останнє відтворюється саме перемиканням типу пристрою, бо він визначає, чи рендериться сторінка як мобільна, який показується курсор і які події породжує взаємодія — сенсорні чи кліки. Що не закриває: продуктивність на слабкому залізі й усе, що впирається у справжній пристрій.
Із чого має складатися лабораторія пристроїв і що робити, якщо на неї немає бюджету?
Найбільшу точність щодо поведінки й загального досвіду дає реальний пристрій із потрібним браузером, тому мінімальний набір починається з фізичного заліза: машина на macOS, машина на Windows і по парі «телефон плюс планшет» для Android та iOS — з поставленими на них браузерами зі своєї ж матриці. Окремий пункт, який ігнорують найчастіше: пара свідомо слабких телефонів, бо продуктивність анімацій на флагмані не показує нічого, а скарга «у нас гальмує» без них не відтвориться ніколи. Якщо бюджету немає, набір закривають частково: емуляторами, віртуальними машинами й комерційними фермами на кшталт Sauce Labs чи Browser Stack, а іноді власною системою автоматизації. Віртуальні машини не зникають там, де дві версії одного браузера поруч на системі не уживаються: хрестоматійний приклад — IE поряд з Edge, і виходом лишається окремий під кожну версію. Головне правило: ферма пристроїв — це рядок бюджету, що випливає з матриці, а не навпаки; спершу фіксують перелік конфігурацій, і лише після цього розподіляють їх між емулятором, власним залізом і орендою в чужій фермі.
Як ви локалізуєте кросбраузерний баг?
Головна навичка тут — звузити, а не красиво описати. Крок перший: зібрати конфігурацію від репортера — платформу, пристрій і версію браузера; без цих трьох речей звіт «на мобільному зʼїхала кнопка» непридатний до роботи, і повертати його на уточнення — нормальна практика. Крок другий: перевірити схожі конфігурації, щоб зрозуміти масштаб — та сама версія браузера на різних платформах покаже, чи справа в ОС, а різні версії на одній платформі покажуть, з якого моменту почалося. Крок третій, який пропускають найчастіше: припустити, що винні не ви. Джерелом поведінки цілком може бути сам браузер: у такому разі тікет адресують його вендору, а на своєму боці підбирають обхідне рішення замість того, щоб по колу переписувати компонент. І супутня перевірка, яка часто закриває питання за хвилину: подивитися стан підтримки можливості за Baseline або caniuse — якщо вона ще не підтримана всюди, різна поведінка в частині матриці очікувана й дефектом продукту не є.
Три кейси, у яких тема перестає бути теорією: як за пʼять хвилин розібрати звіт «на мобільному все поїхало», як перетворити список логотипів на матрицю з бюджетом і що з адаптивності реально піддається автотесту, а що ні.
Кейс 1. «На мобільному все поїхало»: розбір за пʼять хвилин
У тікеті одне речення й з телефона. Спокуса — відкрити CSS і шукати підозріле правило; це найдовший з усіх можливих шляхів. Порядок огляду має йти від того, що вимикає адаптивність цілком, до того, що псує окрему деталь.
| Що бачите | Найімовірніша причина | Чим перевірити за хвилину |
|---|---|---|
| сторінка виглядає як зменшена копія десктопної, текст дрібний, макет десктопний | у head немає метатегу viewport або в ньому не width=device-width | подивитися head у переглядачі коду сторінки: без тегу медіазапити на вузькі екрани не вмикаються взагалі |
| на одній ширині все добре, на сусідній розсипається | брейкпоінт є, але розкладка після нього не продумана | у режимі Responsive клацнути по смузі брейкпоінтів й перейти з контекстного меню до відповідного @media |
| зʼявилася горизонтальна прокрутка, вміст вилазить за край | елемент із фіксованою шириною або медіа без обмеження контейнером | звузити вікно й порівняти scrollWidth із clientWidth; перевірити, чи є правило img, picture, video { max-width: 100% } |
| зникнув цілий блок оформлення, у консолі порожньо | невалідний селектор скасував увесь стильовий блок, або оголошення не підтримане цим рушієм | в інспекторі знайти перекреслені оголошення з трикутником-попередженням; звірити можливість за Baseline або caniuse |
| картинки розмиті, текст чіткий | не вистачає версії зображення під високий DPR | у режимі пристрою виставити DPR вручну й повторити |
| макет стрибає, коли зʼявляється клавіатура | у метатезі явно стоїть interactive-widget=resizes-content | прочитати вміст метатегу: за замовчуванням (resizes-visual) клавіатура розкладку не зачіпає |
| не спрацьовує свайп, хоча ширина мобільна | ви звузили вікно, а не перемкнули тип пристрою | увімкнути мобільний тип пристрою: від нього залежить, породжується сенсорна подія чи клік |
Три висновки, які економлять найбільше часу.
- Метатег viewport перевіряють першим, бо він вимикає не одне правило, а всю адаптивність. Якщо сторінка рендериться у віртуальній області близько 980 пікселів, жоден медіазапит на 480 чи 640 не спрацює — і години, витрачені на пошук помилки в стилях, підуть у нікуди. Ознака в тікеті дуже характерна: користувач описує не «поламану верстку», а «зменшений десктоп».
- Порожня — не алібі для CSS. Нерозпізнане оголошення браузер пропускає мовчки, а криву розмітку лагодить сам. Тому «помилок немає» тут означає рівно «помилок немає в JavaScript», і не більше.
- Тікет без конфігурації повертають, а не досліджують. Платформа, пристрій і версія браузера — це не бюрократія: без них неможливо зробити наступний крок, а він полягає в перевірці схожих конфігурацій — тієї самої версії браузера на іншій платформі й інших версій на тій самій.
Кейс 2. Від списку логотипів до матриці з бюджетом
Менеджер приносить вимогу: «підтримуємо Chrome, Firefox, Edge, Opera, Safari та мобільні». Виглядає як шість рядків роботи. Насправді рядків менше, а грошей потрібно більше — і те, і те стає видно після одного перетворення.
| Що в списку | Рушій рендерингу | Чи новий рядок матриці |
|---|---|---|
| Chrome (десктоп, Android) | Blink | так, базовий |
| Edge | Blink | ні — той самий рядок, що й Chrome |
| Opera | Blink | ні — той самий рядок |
| Firefox (десктоп, Android) | Gecko | так |
| Safari (macOS) | WebKit | так |
| Safari (iOS, iPadOS) | WebKit | так, окремо від десктопного — інший клас пристрою |
| корпоративний Edge із режимом IE | Trident | так, якщо аудиторія його має |
Шість назв згорнулися в три рушії, але розгорнулися назад по осі пристроїв — і саме ця друга вісь коштує грошей. Далі кожен рядок треба закрити чимось конкретним.
| Рядок матриці | Чим закривається дешево | Чого це не закриває |
|---|---|---|
| Blink, десктоп | локальний Chrome, він же покриває Edge й Opera | різницю в конкретній старій версії браузера |
| Gecko, десктоп | локальний Firefox | те саме на іншій ОС |
| WebKit, десктоп | Mac у команді; без Mac лишається лише оренда у фермі | локальну автоматизацію: збірка WebKit, яку водить інструмент, — не брендовий Safari |
| WebKit, iOS | режим пристрою закриває адаптивність і брейкпоінти | реальну поведінку на пристрої, продуктивність, жести |
| Blink, Android | режим пристрою плюс один фізичний телефон | продуктивність на слабкому залізі |
| слабке залізо | пресети Mid-tier mobile і Low-end mobile — орієнтовно | справжній мобільний процесор: він не моделюється |
| Trident (режим IE) | окрема віртуальна машина | ніщо інше: дві версії поруч не ставляться |
Що з цієї таблиці випливає для розмови з власником продукту:
- Скорочення за рушієм — це економія годин, а не «на око». Прибираючи Edge й Opera з ручного обходу, ви прибираєте дублікати одного рядка. Прибрати ж Safari на тій підставі, що «він теж сучасний браузер», не можна: це окрема відповідь, якої не дасть жоден Chromium.
- Ферма пристроїв випливає з матриці, а не навпаки. Спершу перелік конфігурацій, потім рішення, що з них бере емулятор, що фізичне залізо в офісі, а що доводиться орендувати в Sauce Labs чи Browser Stack. Зворотний порядок дає підписку, якою користуються двічі на квартал.
- Пара свідомо слабких телефонів — окремий рядок бюджету. На флагмані анімації плавні завжди, тому скарга «у вас гальмує» без слабкого апарата не відтворюється ніколи, а пресети DevTools сповільнюють ЦП відносно вашої машини й тому не переносяться між компʼютерами як .
Кейс 3. Що з адаптивності реально автоматизується
Автотест не замінює ока, але добре тримає ті інваріанти, які людина перевіряє нудно й тому нерегулярно: наявність метатегу, відсутність горизонтальної прокрутки на кожному й факт перемикання розкладки.
import { test, expect } from '@playwright/test';
// значення взяті з @media у стилях проєкту, а не з памʼяті:
// у режимі Responsive їх видно смугами над областю перегляду
const BREAKPOINTS = [360, 600, 601, 900, 1024, 1440];
test('метатег viewport на місці й не забороняє масштабування', async ({ page }) => {
await page.goto('/catalog');
const content = await page.locator('meta[name="viewport"]').getAttribute('content');
expect(content, 'без метатегу мобільні медіазапити не вмикаються взагалі').toBeTruthy();
expect(content).toContain('width=device-width');
// заборона масштабування — знахідка доступності, навіть якщо iOS її ігнорує
expect(content ?? '').not.toContain('user-scalable=no');
});
for (const width of BREAKPOINTS) {
test(`ширина ${width}px: вміст не вилазить за область перегляду`, async ({ page }) => {
await page.setViewportSize({ width, height: 900 });
await page.goto('/catalog');
const overflow = await page.evaluate(() => {
const el = document.documentElement;
return el.scrollWidth - el.clientWidth;
});
// допуск в один піксель — на субпіксельне округлення, а не на «майже норм»
expect(overflow, 'зʼявилася горизонтальна прокрутка').toBeLessThanOrEqual(1);
});
}
Перевірка самого перемикання розкладки виглядає так — іде на видимий наслідок брейкпоінта, а не на CSS-властивість:
test('на вузькому екрані меню згортається в кнопку', async ({ page }) => {
await page.setViewportSize({ width: 599, height: 900 });
await page.goto('/catalog');
await expect(page.getByTestId('burger')).toBeVisible();
await expect(page.getByTestId('nav-desktop')).toBeHidden();
// на пікселі по інший бік точки зламу картина дзеркальна
await page.setViewportSize({ width: 601, height: 900 });
await expect(page.getByTestId('nav-desktop')).toBeVisible();
await expect(page.getByTestId('burger')).toBeHidden();
});
А ось помилка, яку роблять на цьому ж місці: звузити й чекати, що сторінка почне поводитися як мобільна.
import { devices, expect, test } from '@playwright/test';
test('так мобільною сторінка не стає', async ({ page }) => {
// змінилася сама лише ширина: тип пристрою лишається десктопним —
// ні дотику, ні мобільного user agent, ні мобільного DPR
await page.setViewportSize({ width: 390, height: 844 });
await page.goto('/catalog');
});
test.describe('мобільний контекст', () => {
// правильно — узяти дескриптор пристрою: разом з ним приходять
// мобільний user agent, підтримка дотику (hasTouch) і відповідний DPR
test.use({ ...devices['iPhone 14'] });
test('карусель гортається жестом', async ({ page }) => {
await page.goto('/catalog');
await expect(page.getByTestId('carousel')).toBeVisible();
});
});
Що дивитися і чому:
- Список брейкпоінтів тримають синхронним зі стилями, а не з переліком популярних телефонів. Константа
BREAKPOINTSмає відповідати@mediaу коді; щойно розробник додає нову точку, тест без оновлення перевіряє вчорашню сторінку. Значення підглядають у DevTools або у стилях — саме тому це найкращий кандидат на коментар із посиланням на джерело чисел. - Перевірка на 599 і 601 пікселі коштує стільки ж, скільки на 320 і 1440, а ловить набагато більше. Дефекти адаптивності живуть на межах, а не в середині діапазону, тож пари «на пікселі до й на пікселі після» — найдешевший спосіб зафіксувати саме перемикання, а не загальний вигляд.
- Ширина області перегляду й тип пристрою — різні речі. Тип визначає, чи рендериться сторінка як мобільна, який курсор показується та які події породжує взаємодія; сама лише зміна розміру цього не вмикає. Тому клас багів «на телефоні не працює жест» перевіряють дескриптором пристрою, а не
setViewportSize. - Зелена не закриває рядок матриці. Запуск у складеному з перевіряє поведінку рушія — і це вже багато, — але не Safari з усіма його шарами й не реальний телефон з його процесором. Межа тут та сама, що й у режиму пристрою в DevTools: за сумнівів у функціональному дефекті останнє слово лишається за фізичним апаратом із матриці.
Периметр і критерій приймання
- Можу назвати три напрямки периметра — старіші браузери, класи пристроїв і користувачі допоміжних технологій — і не зводжу тему до переліку браузерів.
- Знаю різницю «інший вигляд» vs «недоступна функція»: — можливість зробити цільову дію, а не збіг до пікселя.
- Можу пояснити, чому діапазон підтримки — домовленість із власником продукту, і назвати три стратегії: вирівняти поведінку (зокрема поліфілами), свідомо спростити, відмовитися від старих браузерів.
Чому цей клас дефектів мовчить
- Розумію, чому чиста тут нічого не доводить: нерозпізнане CSS-оголошення браузер пропускає без застосування й без помилки, а криву розмітку тихо лагодить — тож її перевіряють валідатором W3C окремим кроком.
- Знаю різницю «селектор нічого не знайшов» vs «селектор невалідний»: перше нешкідливе, друге скасовує весь перелік разом зі стильовим блоком.
Рушії й матриця браузерів
- Знаю, що browser engine, rendering engine і layout engine — одне поняття під трьома назвами, і можу зіставити рушій із браузером: Blink (Chromium і Chrome), Gecko (Firefox), WebKit (Safari й багато мобільних), Trident (IE та режим IE в Edge, підтримка безпеки до 2029).
- Розумію, чому «Chrome, Firefox, Edge, Opera» — це два рядки матриці, а не чотири, і чому Safari не закривається перевіркою в Chrome.
- Можу сказати, звідки беруться рядки матриці — з даних про аудиторію, а за їх відсутності зі стартового набору Baseline.
Baseline
- Не називаю
Limited availabilityтретім рівнем: стадій дві, а це стан до Baseline, коли підтримка є ще не всюди. - Знаю різницю
Newly availablevsWidely available: перша фіксує щойно досягнуту сумісність, друга настає через 30 місяців і дає право не перейматися підтримкою.
Адаптивність і брейкпоінти
- Можу пояснити, чому адаптивність — підхід, а не технологія, і чому її ламає не HTML, а CSS із фіксованими розмірами.
- Знаю різницю медіазапит vs і памʼятаю, що канонічного списку «типових» ширин не існує: числа диктує вміст, а не бренди й моделі.
- Розрізняю великі брейкпоінти (перебудова розкладки) і малі (відступи, розмір шрифту) і знаю, що значення обох дивляться у стилях або в DevTools, а не в памʼяті.
Область перегляду
- Знаю, чим пояснюється звіт «на мобільному все поїхало»: без
width=device-widthсторінка рендериться у ширшій віртуальній області, і вузькі медіазапити не спрацьовують ніколи — тому перший чек цеhead, а не CSS. - Розумію значення ключів метатегу:
width(число абоdevice-width),initial-scale,user-scalable(заборона лишається дефектом доступності навіть там, де браузер її ігнорує). - Не плутаю дефолт
interactive-widget:resizes-visualзмінює лише візуальну область і розкладки не чіпає, а перебудову вмикає явнийresizes-content.
DevTools, реальні пристрої й локалізація
- Вмію знайти реальні брейкпоінти сторінки в режимі
Responsive(сині смуги —max-width, помаранчеві —min-width) і перейти звідти до потрібного@media. - Знаю, що тип пристрою керує не лише виглядом, а й подіями, тому «не працює свайп» відтворюють перемиканням типу, а не звуженням вікна.
- Можу назвати межу симуляції: код виконується на моїй машині, пресети сповільнюють ЦП відносно її потужності, а мобільна архітектура не моделюється — звідси й потреба у фізичних пристроях, зокрема свідомо слабких.
- Знаю порядок звуження дефекту: конфігурація від репортера (платформа, пристрій, версія браузера) → перевірка суміжних конфігурацій → допущення, що баг у самому браузері.
Квіз
Перед стартом
- Питань: 15
- Поріг «зараховано»: ≥70% правильних відповідей.
- Результат впливає на прогрес; завалені питання підуть у чергу повторення.
- Квіз впливає на компліт теми: тема стає «пройдено», лише коли прочитано теорію І квіз складено на ≥70%.
Питання
Що таке рушій рендерингу?

