Буває дуже проста на вигляд задача: змінити margin, padding або інший стиль.
Я змінюю SCSS, оновлюю сторінку - і нічого не відбувається.
Перша реакція може бути: "CSS не працює". Але на практиці проблема часто взагалі не в самому CSS-правилі.
Нещодавно в мене знову був такий випадок. Замість того щоб продовжувати змінювати значення навмання, я пройшла весь шлях зміни по кроках і перевірила, на якому саме етапі вона загубилася.
Спочатку я перевіряю, чи змінила саме той файл
У великих або старих проєктах одна сторінка може одночасно мати кілька джерел стилів.
- старий CSS;
- новий SCSS;
- окремі стилі сторінки;
- стилі компонента;
- зібраний CSS у
public; - перевизначення в іншому файлі.
Тому перше питання для мене не "чому не працює margin?", а "чи файл, який я редагую, взагалі бере участь у формуванні цієї сторінки?"
rg -n "my-selector" resources public # Real example:rg -n "lot-removed" resources publicgit diff -- path/to/file.scssЯкщо selector зустрічається в кількох файлах, це вже достатня причина перевірити, який із них реально потрапляє на сторінку.
git diff тут теж корисний не лише перед commit. Він швидко показує, що я справді змінила той блок і те значення, яке мала намір змінити.
Потім перевіряю, чи SCSS взагалі був зібраний
Зміна файлу .scss сама по собі ще не означає, що браузер її побачить.
Браузер не читає мій source SCSS напряму. Він отримує вже скомпільований CSS.
Тому наступне питання: чи пройшла моя зміна через frontend build?
cat package.json # Or only the scripts section:cat package.json | grep -A 20 '"scripts"'npm run dev # Or, depending on the project:npm run buildУ старих проєктах я не припускаю наперед, що команда обов’язково буде npm run dev або npm run build. Спочатку дивлюся package.json.
Це важливо, бо проєкт може використовувати іншу збірку, кілька entry points або окремі команди для різних частин frontend.
Перевіряю, чи правило потрапило в compiled CSS
git status --short rg -n "my-selector" publicЦей крок добре відділяє проблему source від проблеми build.
Якщо в SCSS нове правило є, а серед compiled assets його немає, я вже знаю, що немає сенсу перевіряти specificity або cache. Зміна ще навіть не дійшла до браузера.
Тобто проблема вже локалізована значно точніше: потрібно дивитися frontend build, entry point або pipeline збірки.
Якщо CSS зібрався, відкриваю DevTools
На цьому етапі я більше не змінюю CSS навмання.
Відкриваю потрібний елемент у browser DevTools і у вкладці Styles перевіряю:
- чи є моє правило взагалі;
- з якого CSS-файлу воно прийшло;
- чи перекреслене значення;
- який selector фактично перемагає;
- яке computed value отримав елемент.
.my-selector { margin-top: 16px;} .some-parent .my-selector { margin-top: 0;}У такій ситуації перший selector справді завантажився. Build працює. Cache тут теж ні до чого.
Але другий selector специфічніший, тому саме його значення використає браузер.
Це принципово інший клас проблеми, і DevTools показує його майже одразу.
Перевіряю порядок підключення стилів
.my-selector { margin-top: 16px;} /* Loaded later */.my-selector { margin-top: 0;}Навіть однакові selectors можуть поводитися по-різному залежно від порядку, в якому браузер отримав CSS.
Якщо specificity однакова, пізніше правило зазвичай перемагає раніше.
Тому в DevTools я дивлюся не лише на саме значення, а й на файл і номер рядка. Це часто одразу показує, що мій стиль перекривається іншим bundle або файлом, який підключений пізніше.
Перевіряю, чи selector взагалі відповідає DOM
.purchase .status { margin-top: 10px;}<div class="purchase"> <div class="status-wrapper"> ... </div></div>Це ще одна дуже проста причина, яку легко пропустити: HTML уже відрізняється від того, що я пам’ятаю або бачу в іншому шаблоні.
У прикладі CSS може бути синтаксично правильним, build може пройти, bundle може завантажитися, але класу .status у DOM просто немає.
У такій ситуації selector не має до чого застосовуватися.
Лише після цього я думаю про cache
Cache - популярне пояснення майже будь-якої проблеми зі стилями. Але я не починаю з нього.
Спочатку хочу знати, що потрібне правило:
- є в source;
- потрапило в compiled CSS;
- завантажилося в браузер;
- відповідає фактичному DOM.
Після цього вже має сенс зробити hard reload або увімкнути Disable cache у вкладці Network.
rg -n "my-selector" publicУ Network я також дивлюся, який саме CSS asset реально завантажив браузер, і за потреби відкриваю його Response.
Якщо локально я щойно зібрала одне правило, а браузер отримує інший asset, тоді вже перевіряю versioning, manifest, CDN або інший рівень кешування.
Я не використовую !important як перший fix
.my-selector { margin-top: 16px !important;}Коли стиль не застосувався, дуже легко додати !important і побачити бажаний результат.
Але це не відповідає на головне питання: чому попереднє правило не працювало?
Якщо причина в неправильному selector, іншому source-файлі, старому bundle або порядку стилів, !important лише приховає цю проблему і зробить наступні зміни складнішими.
Тому я спочатку знаходжу джерело поведінки, а вже потім вирішую, як правильно виправити CSS.
Мій короткий debugging flow
# 1. Переконатися, що змінила потрібний sourcegit diff -- path/to/file.scss # 2. Знайти всі місця з цим selectorrg -n "my-selector" resources public # 3. Подивитися frontend scriptscat package.json | grep -A 20 '"scripts"' # 4. Перезібрати assetsnpm run dev # 5. Переконатися, що правило потрапило в compiled CSSrg -n "my-selector" public # 6. Перевірити стан репозиторіюsource | vbuild | vcompiled asset | vloaded asset | vselector matches DOM | vcascade / specificity / orderПісля перевірки з термінала я переходжу в DevTools і дивлюся фактичний DOM та CSS cascade.
Для мене головна зміна в підході дуже проста: якщо стиль не застосувався, я більше не починаю одразу змінювати CSS ще раз.
Спочатку визначаю, на якому етапі загубилася зміна.
CSS-зміна проходить цілий ланцюжок: source -> build -> loaded asset -> selector -> cascade -> browser. Якщо знайти етап, на якому вона загубилася, проблема зазвичай стає набагато простішою.
Такий підхід здається довшим, ніж просто кілька разів змінити margin і перезавантажити сторінку.
Але в реальному проєкті він майже завжди економить час, тому що кожна перевірка відсікає цілий клас можливих причин.
Я більше не налагоджую CSS як одне правило. Я налагоджую шлях, яким це правило доходить від source-файлу до браузера.

