Skip to content
Powrót do bloga
Poradniki

PX vs REM vs EM: kompletny przewodnik po jednostkach CSS

px vs rem vs em: co oznacza każda jednostka CSS, kiedy używać rem dla dostępności, pułapka zagnieżdżonych em i ściąga według właściwości.

12 min czytania

PX vs REM vs EM: kompletny przewodnik po jednostkach CSS

Oto krótka odpowiedź na pytanie px vs rem vs em, jeszcze przed jakimkolwiek wyjaśnieniem. Używaj rem do niemal całego wymiarowania — rozmiarów czcionek, paddingu, marginesów, odstępów, border-radius i punktów przełamania (breakpointów) — bo skaluje się wraz z ustawieniem rozmiaru czcionki w przeglądarce czytelnika. Używaj px do tych nielicznych rzeczy, które nigdy nie powinny się skalować, jak obramowanie o szerokości 1px czy precyzyjne przesunięcie cienia. Używaj em do rzadkiego, lokalnego przypadku, gdy wartość ma rosnąć wraz z rozmiarem czcionki samego elementu — na przykład padding przycisku, który podąża za jego tekstem.

Ta reguła obejmuje 90% decyzji. Pozostałe 10% to miejsce, gdzie kryją się kłopoty: matematyka kumulacji em, która za pierwszym razem zaskakuje każdego, błąd w media query psujący układy przy powiększeniu oraz przypadki, w których px jest faktycznie bardziej dostępnym wyborem. Dalej znajdziesz wszystkie trzy z gotowym do uruchomienia CSS, a na końcu ściągę według właściwości, którą warto mieć otwartą podczas pisania stylów.

Co px, rem i em naprawdę oznaczają

Trzy jednostki mają trzy różne punkty odniesienia, i na tym polega cała różnica.

px to jednostka absolutna. Jeden px to jeden piksel CSS i zachowuje ten rozmiar bez względu na otoczenie. border: 1px solid to jeden piksel, kropka. Haczyk w tym, że „absolutny” oznacza też, że jednostka ignoruje preferencje użytkownika — o tym, dlaczego to ma znaczenie, będzie później.

rem jest względny wobec rozmiaru czcionki elementu głównego (root). Elementem głównym jest <html>, a przeglądarki domyślnie ustawiają jego rozmiar czcionki na 16px. Zatem 1rem równa się 16px w standardowej konfiguracji, wszędzie na stronie, niezależnie od zagnieżdżenia. Cała zaleta sprowadza się do tej spójności: masz jedną wartość kotwiczną i nie musisz pilnować niespodzianek.

em jest względny wobec rozmiaru czcionki bieżącego elementu (lub jego rodzica, dla właściwości innych niż font-size). Ponieważ ten punkt odniesienia zmienia się wraz z zagnieżdżaniem elementów, wartości em przesuwają się zależnie od kontekstu. Ten sam 1.5em może w jednym miejscu dawać 24px, a w innym 30px.

Kotwica, którą warto zapamiętać, to 16px = 1rem. Jeśli masz zapamiętać tylko jedno, zapamiętaj właśnie to. Gdy musisz przeliczyć konkretną wartość, konwerter px na rem wykonuje dzielenie względem dowolnej bazy, którą wybierzesz.

px vs rem vs em w skrócie

JednostkaWzględem czegoSkaluje się z czcionką użytkownika?Typowe zastosowanieZachowanie przy zagnieżdżeniu
pxNiczego (absolutna)NieObramowania, przesunięcia cieni, włoskowate linieZawsze ten sam rozmiar
remRozmiar czcionki głównego <html>TakRozmiar czcionki, odstępy, breakpointyZawsze ten sam rozmiar
emRozmiar czcionki bieżącego elementuTakWartości lokalne związane z komponentemKumuluje się — może dryfować

Dwie kolumny rozstrzygające większość sporów to „skaluje się z czcionką użytkownika” oraz „zachowanie przy zagnieżdżeniu”. rem wygrywa w obu: respektuje preferencję czytelnika i pozostaje przewidywalny. em dzieli pierwszą zaletę, ale rezygnuje z drugiej.

Jak oblicza się każdą jednostkę

To zwykła arytmetyka. Kłopot sprawia zwykle jedno: przez jaką liczbę dzielić albo mnożyć.

rem korzysta z rozmiaru czcionki elementu głównego:

rem = px ÷ root-font-size

Przy domyślnym roocie 16px, 24px ÷ 16 = 1.5rem. Aby wrócić, pomnóż: 1.5rem × 16 = 24px. Każdy rem na stronie używa tej samej 16 (lub czegokolwiek, co ustawisz jako root), i dokładnie dlatego rem jest przewidywalny.

em korzysta z rozmiaru czcionki samego bieżącego elementu:

em = px ÷ current-element-font-size

Jeśli font-size elementu wynosi 20px, to 1em na tym elemencie to 20px, 0.5em to 10px, a padding 1.5em to 30px. Zmień rozmiar czcionki elementu, a każda przypisana do niego wartość em zmieni się razem z nim. To lokalne sprzężenie jest sensem em, ale bywa też jego pułapką.

Pułapka kumulacji em

Wiele poradników pomija ten fragment. Gdy zagnieżdżasz elementy, które wszystkie używają em do rozmiaru czcionki, wartości mnożą się w dół drzewa. Każdy poziom dziedziczy obliczony rozmiar czcionki rodzica i nakłada na to swój własny współczynnik em.

.menu      { font-size: 1.2em; } /* rodzic ma 16px → 19.2px */
.menu .item { font-size: 1.2em; } /* rodzic ma 19.2px → 23.04px */
.menu .item .sub { font-size: 1.2em; } /* rodzic ma 23.04px → 27.648px */

Każdy poziom to „120% swojego rodzica”, co brzmi niegroźnie. Ale ponieważ rodzic już urósł, trzeci poziom to 1.2 × 1.2 × 1.2 = 1.728em względem oryginalnych 16px — około 27.6px, a nie 19.2px, które mógłbyś odczytać z reguły w izolacji. Zagnieźdź listę w liście wewnątrz komponentu, a tekst rozrasta się w sposób trudny do prześledzenia.

rem całkowicie to omija. 1.2rem to 19.2px, czy siedzi na samej górze dokumentu, czy dwanaście poziomów głębiej, bo zawsze mierzy względem roota, nigdy względem rodzica. Gdy wartość daje rozmiar, którego się nie spodziewałeś, pierwsze pytanie brzmi: czy to em (względny wobec rodzica, kumuluje się) czy rem (względny wobec roota, stabilny). Jeśli debugujesz zabłąkany rem i chcesz szybko zobaczyć jego rozmiar w pikselach, konwerter rem na px przelicza go natychmiast.

Kiedy używać rem

Po rem sięgaj domyślnie. To właściwa jednostka do rozmiarów czcionek, paddingu, marginesów, odstępów, border-radius i breakpointów w media query — wszystkiego, co powinno się skalować, gdy czytelnik dostosowuje rozmiar tekstu.

To ostatnie zdanie to argument za dostępnością i nie jest on hipotetyczny. Ankiety WebAIM wśród użytkowników czytników ekranu i osób słabowidzących konsekwentnie pokazują, że duża część użytkowników zmienia domyślny rozmiar czcionki przeglądarki lub systemu, wielu z nich znacznie powyżej standardowych 16px. Układ wymiarowany w rem honoruje tę zmianę: podbij domyślny rozmiar do 20px, a każda wartość oparta na rem rośnie proporcjonalnie. Układ wymiarowany w px całkowicie to ignoruje: tekst pozostaje zablokowany na zaszytym rozmiarze, niezależnie od tego, jak bardzo czytelnik potrzebuje go większego.

:root {
  font-size: 16px; /* 1rem = 16px */
}

h1   { font-size: 2rem;     } /* 32px, skaluje się z preferencją użytkownika */
p    { font-size: 1rem;     } /* 16px */
.card { padding: 1.5rem;    } /* 24px */
.card { border-radius: 0.5rem; } /* 8px */

Ponieważ każda wartość jest tutaj zakotwiczona w tym samym roocie, pojedyncza zmiana rozmiaru czcionki roota przeskalowuje cały interfejs proporcjonalnie. To również utrzymuje spójność design systemu: odstępy i typografia poruszają się razem, zamiast się rozjeżdżać.

Sztuczka z 62.5%

Istnieje popularny skrót, który czyni arytmetykę rem trywialną. Ustaw rozmiar czcionki roota na 62.5%, czyli 62.5% × 16px = 10px:

html {
  font-size: 62.5%; /* teraz 1rem = 10px */
}

body {
  font-size: 1.6rem; /* przywróć czytelny tekst 16px */
}

h1 { font-size: 2.4rem; } /* 24px */
p  { font-size: 1.6rem; } /* 16px */

Przy roocie 10px rachunek pamięciowy sprowadza się do „podziel wartość w pikselach przez 10”: 24px → 2.4rem, 12px → 1.2rem. Jedyny haczyk to przywrócenie czytelnego rozmiaru tekstu za pomocą body { font-size: 1.6rem }, bo surowa baza 10px daje domyślny tekst o wiele za mały. Użycie 62.5% jako procentu, a nie 10px, zachowuje względność, więc czytelnik, który przeskaluje domyślne ustawienia przeglądarki, nadal otrzymuje proporcjonalny wzrost. Jeśli przyjmiesz tę bazę, ustaw rozmiar czcionki roota w konwerterze na 10, aby pasował do twojego arkusza stylów.

Kiedy używać em

Używaj em, gdy chcesz, by wartość skalowała się wraz z własnym rozmiarem czcionki elementu, a nie roota. Klasycznym przypadkiem jest przycisk:

.btn {
  font-size: 1rem;      /* wymiarowany względem roota */
  padding: 0.75em 1.5em; /* padding podąża za tekstem przycisku */
}

.btn--large {
  font-size: 1.25rem;   /* jedna zmiana zmienia rozmiar wszystkiego */
}

Ponieważ padding jest w em, modyfikator .btn--large zmienia rozmiar tekstu i jego paddingu razem, z jednej deklaracji, więc przycisk pozostaje proporcjonalny przy dowolnym rozmiarze. Ta sama logika dotyczy ikony wymiarowanej w em, by pasowała do linii tekstu, w której się znajduje, albo letter-spacingu, który ma rosnąć wraz z czcionką.

Strategia, która sprawdza się w praktyce, to rem dla globalnego szkieletu, em dla lokalnych proporcji. Ustaw rozmiar czcionki w rem, by odpowiadał roocie i preferencji użytkownika; ustaw tę garstkę wartości, które mają podążać za tym elementem, w em. Tylko trzymaj em z dala od czegokolwiek, co głęboko się zagnieżdża, bo inaczej wcześniejsza pułapka kumulacji znów się wkrada.

Kiedy używać px

Niektóre wartości naprawdę nie powinny się skalować i px jest dla nich właściwy: włoskowate obramowanie 1px, precyzyjne przesunięcie box-shadow, pierścień fokusa 2px. To detale renderowania, nie treść. Obramowanie, które „skaluje się” do 1.25px, gdy użytkownik powiększa tekst, nic nie zyskuje i może wyrenderować się jako rozmyta linia. px utrzymuje je ostrym.

.divider { border-bottom: 1px solid; }     /* powinno pozostać 1px */
.card    { box-shadow: 0 2px 4px rgba(0,0,0,0.1); } /* stałe przesunięcie */
.input:focus { outline: 2px solid; }       /* ostry pierścień fokusa */

Zaskakujący niuans — kiedy px jest bardziej dostępny

Większość porad „zawsze używaj rem” pomija jeden niuans. Dostępny wybór to nie „rem wszędzie”, tylko „skaluj to, co powinno się skalować, i ustal na stałe to, co nie powinno”.

Obramowanie 1px to stały detal. Wymuszenie go w rem, by rosło, gdy użytkownik powiększa tekst, nie poprawia czytelności, a jedynie rozmywa włoskowatą linię. Dla tych właściwości px jest bardziej dostępnym wyborem właśnie dlatego, że pozostaje na miejscu.

Błąd, który ludzie faktycznie popełniają, jest odwrotny: użycie px do rzeczy, które powinny reagować, jak rozmiary czcionek i breakpointy. To tutaj px szkodzi dostępności. Reguła nie dotyczy więc jednostki, lecz właściwości. Zapytaj, czy wartość jest treścią, z którą czytelnik wchodzi w interakcję (skaluj ją — rem), czy stałym detalem renderowania (przypnij ją — px). Jednostka wynika z odpowiedzi.

Pułapka media query

Ta psuje prawdziwe układy i prawie żaden przewodnik przed nią nie ostrzega. Punkty przełamania w media query napisane w px nie reagują na powiększenie rozmiaru czcionki przeglądarki tak, jak byś tego oczekiwał.

Wyobraź sobie breakpoint przy width: 600px, gdzie zwija się pasek boczny. Użytkownik o ograniczonym wzroku ustawia domyślny rozmiar przeglądarki na 24px, by czytać komfortowo. Twoja treść potrzebuje teraz więcej miejsca w poziomie — większy tekst chce się wcześniej przełamać. Ale breakpoint w px nie wie, że tekst urósł; nadal przełącza się dokładnie przy 600px szerokości viewportu, więc układ zmienia się w niewłaściwym momencie, a treść robi się ściśnięta lub się nakłada.

Porównaj oba podejścia:

/* breakpoint px — ignoruje preferencję rozmiaru czcionki użytkownika */
@media (min-width: 600px) {
  .sidebar { display: block; }
}

/* breakpoint em/rem — reaguje na rozmiar czcionki użytkownika */
@media (min-width: 37.5em) {
  .sidebar { display: block; }
}

37.5em to 600px przy domyślnych 16px (600 ÷ 16 = 37.5). Różnica jest behawioralna: gdy użytkownik podwoi domyślny rozmiar czcionki, breakpoint em efektywnie też się podwaja, więc układ przełącza się przy szerokości viewportu proporcjonalnej do tekstu, czyli dokładnie wtedy, gdy treść tego potrzebuje. Breakpoint px pozostaje zamrożony.

Jeden niuans warto znać: w warunkach media query zarówno em, jak i rem rozwiązują się względem domyślnego rozmiaru czcionki przeglądarki, a nie żadnego nadpisania na html, więc zachowują się tam identycznie. Każda z tych jednostek naprawia błąd; px go powoduje.

Tabela decyzyjna według właściwości

Gdy masz wątpliwości, ta tabela je rozstrzyga. To najszybszy sposób na podjęcie decyzji bez ponownego wyprowadzania logiki za każdym razem.

WłaściwośćZalecana jednostkaDlaczego
font-sizeremSkaluje się z preferencją rozmiaru czcionki użytkownika
padding / marginremOdstępy skalują się razem z tekstem
borderpxWłoskowate linie powinny pozostać ostre i stałe
przesunięcie box-shadowpxPrecyzyjny detal renderowania, nie treść
border-radiusremUtrzymuje zaokrąglenie narożników proporcjonalne do skali
media queryem / remBreakpointy muszą reagować na powiększenie czcionki
width / max-widthrem (często ch dla tekstu)Skalowalne szerokości układu; ch ogranicza długość wiersza
line-heightbez jednostkiBezjednostkowy mnożnik dziedziczy się poprawnie

Wiersz line-height zasługuje na uwagę, bo to częsty błąd. Zawsze pisz line-height: 1.5, bez jednostki. Wartość bez jednostki to mnożnik, który każdy element oblicza względem własnego rozmiaru czcionki, więc zagnieżdżone elementy pozostają czytelne. Napisz zamiast tego line-height: 1.5em lub 24px, a obliczona długość zostanie odziedziczona, co oznacza, że dziecko z większą czcionką zachowuje wysokość wiersza rodzica i jego tekst zaczyna się zlewać. Brak jednostki omija cały problem.

Przeliczanie między px a rem

Arytmetyka jest na tyle prosta, by zrobić ją w głowie, gdy tylko utrzymasz kotwicę: 16px = 1rem. Podziel przez 16, by przejść na rem, pomnóż przez 16, by wrócić do px.

pxrem (baza 16px)
8px0.5rem
12px0.75rem
16px1rem
24px1.5rem
32px2rem

Jeśli używasz sztuczki z 62.5%, baza staje się 10px, a rachunek jest jeszcze prostszy — wystarczy podzielić lub pomnożyć przez 10, więc 24px = 2.4rem. Jedyna zasada to zawsze przeliczać względem bazy, którą faktycznie ustawia twój arkusz stylów.

Do wszystkiego innego — nietypowych wartości, niestandardowego roota czy masowej konwersji eksportu z Figmy — pomiń liczenie w głowie i użyj konwertera px na rem lub konwertera rem na px. Oba pozwalają ustawić dowolny rozmiar czcionki roota i przeliczać w obu kierunkach w czasie rzeczywistym. A jeśli porządkujesz potem arkusz stylów pełen mieszanych jednostek, formater CSS znormalizuje za ciebie odstępy i wcięcia.

Częste błędy

Kilka wzorców powoduje większość kłopotów związanych z jednostkami:

Ustawianie rozmiaru czcionki roota w px. Napisanie html { font-size: 16px } (zamiast pozostawienia domyślnej wartości lub użycia 100% / procentu) całkowicie nadpisuje preferencję rozmiaru czcionki przeglądarki użytkownika. Wartości rem nadal liczą się względem niej, ale czytelnik nie może już przeskalować całej strony. Zostaw root w domyślnej wartości albo użyj procentu.

Mieszanie px i rem bez systemu. Niektóre rozmiary czcionek w px, niektóre w rem, odstępy podzielone między oba: w efekcie układ skaluje się nierównomiernie, gdy użytkownik dostosowuje tekst. Wybierz rem jako domyślną jednostkę, a px zarezerwuj dla świadomych wyjątków z tabeli decyzyjnej.

Używanie em do globalnych odstępów. Em na szeroko zagnieżdżonych kontenerach przywraca pułapkę kumulacji, więc padding głęboko w drzewie daje coś, czego nikt nie zamierzał. Trzymaj globalne odstępy w rem; em zachowaj dla lokalnych wartości w obrębie komponentu.

Nadawanie line-height jednostki. Jak opisano wyżej, line-height: 24px lub 1.5em zostaje odziedziczone jako obliczona długość i psuje się na elementach o różnych rozmiarach czcionek. Zawsze używaj bezjednostkowego mnożnika.

FAQ

Czy rem jest lepszy od px?

W przypadku większości wymiarowania tak: rem jest lepszy od px, bo skaluje się z preferencją rozmiaru czcionki przeglądarki użytkownika, którą px ignoruje. Ale „lepszy” zależy od właściwości: px jest właściwym wyborem dla stałych detali, jak obramowania 1px i przesunięcia cieni, które mają pozostać ostre. Używaj rem do wymiarowania treści, px do detali renderowania.

Ile to 1rem w pikselach?

1rem równa się rozmiarowi czcionki roota w pikselach, czyli domyślnie 16px w praktycznie wszystkich przeglądarkach. Zatem 1rem = 16px, 1.5rem = 24px, a 2rem = 32px w standardowej konfiguracji. Jeśli arkusz stylów nadpisuje html { font-size } — na przykład na 10px sztuczką z 62.5% — wtedy 1rem równa się tej wartości.

Powinienem używać rem czy em do font-size?

Używaj rem do font-size w niemal każdym przypadku. Rem mierzy względem roota, więc pozostaje przewidywalny bez względu na to, jak głęboko element jest zagnieżdżony. Em mierzy względem rozmiaru czcionki rodzica, co kumuluje się w dół drzewa i sprawia, że zagnieżdżony tekst nieoczekiwanie się rozrasta. Em zarezerwuj dla lokalnych wartości związanych z pojedynczym komponentem.

Kiedy używać px zamiast rem?

Używaj px do wartości, które nie powinny się skalować z rozmiarem czcionki użytkownika: obramowań 1px, precyzyjnych przesunięć box-shadow, pierścieni fokusa i innych stałych detali renderowania. To ostre detale projektowe, a nie treść, więc przypięcie ich w px jest bardziej dostępnym wyborem. Wszystko związane z treścią nadal powinno używać rem.

Dlaczego media query psują się, gdy używam px?

Punkty przełamania w media query w px nie reagują na powiększenie rozmiaru czcionki przeglądarki. Gdy użytkownik powiększa domyślną czcionkę, jego treść potrzebuje więcej miejsca, ale breakpoint px nadal przełącza się przy tej samej szerokości viewportu, więc układ zmienia się w niewłaściwym momencie. Używaj breakpointów em lub rem, które skalują się z rozmiarem czcionki użytkownika.

Czym jest sztuczka z czcionką 62.5%?

Sztuczka z 62.5% ustawia html { font-size: 62.5% }, czyniąc rozmiar czcionki roota równym 10px (62.5% z 16). Przy bazie 10px matematyka rem staje się „podziel przez 10”: 24px = 2.4rem, 12px = 1.2rem. Programiści ustawiają następnie body { font-size: 1.6rem }, by przywrócić czytelny tekst 16px.

Czy można mieszać px, rem i em?

Tak, mieszanie px, rem i em jest prawidłowe, gdy każda jednostka podąża za właściwością, do której pasuje: rem do typografii i odstępów, px do stałych detali, em do lokalnych wartości w obrębie komponentu. Kłopoty sprawia mieszanie ich bez systemu — na przykład niektóre rozmiary czcionek w px, a niektóre w rem. Wybierz rem jako domyślną jednostkę, a px i em traktuj jako świadome wyjątki.

Jakiej jednostki używać do paddingu i marginesu?

Używaj rem do paddingu i marginesu, by odstępy skalowały się razem z tekstem, gdy użytkownik dostosowuje rozmiar czcionki. To utrzymuje układ proporcjonalnym i dostępnym. Em zarezerwuj dla paddingu, który ma podążać za własnym rozmiarem czcionki elementu, jak przycisk, którego padding rośnie wraz z tekstem, i unikaj em na głęboko zagnieżdżonych kontenerach, gdzie się kumuluje.

Tagi: css rem em frontend accessibility responsive-design

Powiązane artykuły

Zobacz wszystkie artykuły