Skip to main content

Різниця між CSS reset та normalize

CSS Reset та Normalize.css - Reset скидає всі браузерні стилі до нуля; Normalize виправляє розбіжності між браузерами, зберігаючи корисні стандарти на зразок жирних заголовків і маркерів списків.

Теорія

TL;DR

  • Reset = зносимо все до голої землі; Normalize = вирівнюємо нерівну підлогу в різних будинках, не руйнуючи їх
  • Reset обнуляє відступи, маркери списків і жирність шрифтів; Normalize залишає ієрархію заголовків і маркери списків
  • Normalize v8.0.1 важить 7.3KB мінімізованим; більшість Reset-файлів займають 1-5KB залежно від автора
  • Повністю кастомний дизайн (ігровий UI, дашборд) → Reset; продакшн-застосунок із семантичним HTML → Normalize

Швидкий приклад

css
/* За замовчуванням: Chrome додає ~21px margin-top до h1, жирний шрифт */ /* Підхід A: CSS Reset */ *, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; } /* Результат: h1 впритул до верху сторінки, не жирний, без відступу */ /* ul без маркерів і відступу зліва - все пишеш сам */ /* Підхід Б: Normalize v8.0.1 */ h1 { font-size: 2em; margin: .67em 0; } /* ієрархія заголовків збережена */ /* Результат: h1 жирний з відступом, ul тримає маркери */ /* Chrome і Firefox відображають однаково */

Обидва підходи вирішують одну проблему: браузери не домовились про стандарти. Просто кожен по-своєму.

Ключова різниця

Reset націлений на уніфікацію: він обнуляє margin, padding, border і list-style на кожному елементі. Ти будуєш з порожнього полотна. Normalize виправляє тільки те, де браузери розходяться, наприклад розмір базового шрифту в Chrome проти Firefox, і залишає семантичні стилі (жирний h1, маркери ul) недоторканими. Один обнуляє все, інший патчить тільки поламане.

Коли що використовувати

  • Повністю кастомний дизайн без семантичних стандартів (ігровий UI, data dashboard) → Reset
  • Продакшн-застосунок, контентний сайт, React або Next.js → Normalize
  • Tailwind CSS → Normalize поєднується природно; у Tailwind є власний Preflight для utility-first підходу, але Normalize краще підходить для форм поза цією системою
  • Підтримка старих браузерів, де потрібні передбачувані нулі → Reset

Більшість React-кодових баз, які я бачив, за замовчуванням беруть Normalize саме з цієї причини: застосунок спирається на семантичний HTML, і ніхто не хоче переписувати жирність заголовків тільки тому, що все обнулили на старті.

Таблиця порівняння

АспектCSS ResetNormalize.css
ПідхідОбнуляє всі стандартиВиправляє розбіжності, зберігає корисне
Розмір файлу~1-5KB (залежить від автора)7.3KB мінімізований (v8)
ЗаголовкиЗвичайна жирність, без відступуЖирні, відступ 0.67em
СпискиБез маркерів і відступівМаркери збережені, однакові в усіх браузерах
Формиborder та margin обнуленіОднакові стани focus
Коли братиДизайн з нуля, повний контрольПродакшн із семантичним HTML

Як браузери це обробляють

Браузери застосовують власні user agent stylesheets (UA-стилі) під час CSS-каскаду, ще до того як парсяться твої стилі. Reset вставляє правило * { margin: 0 } з високою специфічністю, яке перекриває всі UA-стилі одним махом. Normalize використовує точкові селектори на зразок textarea { resize: vertical } і лише в 5 місцях (v8) додає !important, виправляючи конкретні баги в Blink, Gecko і WebKit. Тому Normalize краще уживається з твоїм власним каскадом.

Типові помилки

Підключати Reset і Normalize одночасно:

css
/* Неправильно: правило * з Reset перекриває точкові фікси Normalize */ * { margin: 0; padding: 0; } h1 { margin: .67em 0; } /* вже обнулено через * - безглуздо */

Обирай одне. Обидва разом дають непередбачувані результати.

Забути box-sizing у власному Reset:

css
/* Неправильно: content-box ламає розрахунок ширини */ div { width: 100%; padding: 10px; } /* рендериться на 20px ширше очікуваного */ /* Правильно: завжди включай box-sizing */ *, *::before, *::after { box-sizing: border-box; }

Це найпоширеніший баг у Reset-підходах, який досі зустрічається в code review.

Брати Reset Еріка Мейєра 2008 року без змін: Він не покриває сучасні SVG-елементи, стани форм і все, що з'явилось за останнє десятиліття CSS. Краще перейти на Normalize або актуальний maintained reset.

Вважати, що Normalize нічого не змінює візуально: Він виправляє 200+ браузерних багів, зокрема градієнт кнопок у Firefox і розмір шрифту html в Safari. Візуально схоже, але крос-браузерна поведінка набагато передбачуваніша. Перевір через DevTools: інспектуй button:focus до і після підключення Normalize.

Де зустрічається в реальних проектах

  • Create React App: підключає Normalize v8.0.1 за замовчуванням для однакових форм і заголовків
  • Bootstrap 5: будує грід і компоненти поверх Normalize
  • Next.js: підключає Normalize через globals.css за замовчуванням
  • Tailwind CSS: використовує власний Preflight внутрішньо; Normalize рекомендується для форм поза Tailwind

Питання на співбесіді

Q: Чому не написати просто * { margin: 0; padding: 0; } самостійно замість підключення бібліотеки?
A: Одне правило пропускає 100+ браузерних специфічних багів, зокрема quirk розміру шрифту елемента html в Safari. Підтримувані бібліотеки закривають ці edge cases автоматично.

Q: Чи використовує Normalize !important?
A: Рідко. У v8 таких правил 5, і кожне виправляє конкретний відомий баг браузера. Широкого !important немає, щоб не ламати твій каскад.

Q: Яка різниця між Tailwind Preflight і Normalize?
A: Preflight схожий на Reset, але заточений під Tailwind і додає власні налаштування на зразок ring-кольорів. Поза Tailwind-проектами Normalize є нейтральнішим варіантом.

Q: Як побачити, що Normalize реально виправляє?
A: Відкрий DevTools у Chrome, обери будь-який елемент, зайди в панель Styles і шукай записи "user agent stylesheet". Саме ці стандарти Normalize вирівнює між браузерами.

Q: Як Normalize поводиться в CSS-in-JS (наприклад, Emotion) зі скоупованими стилями?
A: Normalize підключають глобально. Твої скоуповані селектори перебивають його правила через специфічність. Але перевіряй UA-витоки в iframe, наприклад у вбудованих віджетах Stripe, де стилі можуть не наслідуватись.

Приклади

Reset і Normalize на базових HTML-елементах

html
<!DOCTYPE html> <html> <head> <style> /* Сценарій A: CSS Reset */ *, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; } /* h1 впритул до верху, не жирний, без відступу */ /* ul без маркерів і відступу зліва */ /* Сценарій Б: Normalize v8.0.1 */ /* h1 { font-size: 2em; margin: .67em 0; } */ /* h1 жирний з відступом; маркери ul на місці */ </style> </head> <body> <h1>Заголовок</h1> <ul> <li>Перший пункт</li> <li>Другий пункт</li> </ul> </body> </html>

З Reset h1 впритул до верху без жирності і відступу, список без маркерів. З Normalize h1 тримає відступ 0.67em і жирний шрифт, список залишається з маркерами. Обидва варіанти однакові в Chrome і Firefox, просто з різної стартової точки.

React-застосунок із Normalize як базовим шаром

css
/* index.css - Create React App підключає normalize.css автоматично */ @import 'normalize.css'; /* Стилі компонентів будуються поверх Normalize */ .article-title { font-size: 2.5rem; color: #1a1a2e; /* Normalize вже встановив жирний шрифт і базовий font-size для h1 */ } /* Форми однакові без зайвих обнулень */ input[type="text"] { border: 1px solid #ccc; padding: 8px 12px; /* Normalize вже виправив font-family і padding для input у різних браузерах */ }

Create React App підключає Normalize за замовчуванням, бо React-застосунки спираються на семантичний HTML. Ієрархія заголовків і стилі списків несуть смислове навантаження. Normalize дає змогу зберегти цей сенс без написання базових стилів вручну.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.

Дочитали статтю?