Elastyczna i płynna typografia z funkcjami CSS Baseline

Data publikacji: 16 grudnia 2025 r.

Elastyczny projekt witryny to podejście do tworzenia stron internetowych, które dobrze wyglądają i działają w różnych przeglądarkach, rozmiarach widocznego obszaru, na różnych urządzeniach i przy różnych preferencjach użytkowników. W przypadku typografii głównym problemem jest często dostosowywanie font-size na podstawie szerokości przeglądarki, co może mieć również wpływ na wartości odstępów, takie jak line-height i margin.

Jako projektanci powinniśmy zastanowić się, ile miejsca jest dostępne w przeglądarce, i odpowiednio dostosować typografię. Pamiętaj też, że różni użytkownicy mają różne font-size potrzeby na różnych urządzeniach, w zależności od okoliczności osobistych, na które nie masz wpływu i o których nie wiesz. Dlatego niebezpieczne jest podejmowanie działań, które pozbawiają użytkownika kontroli nad ostatecznym wynikiem. Podczas przeglądania internetu użytkownicy mogą wpływać na rozmiar czcionki na 2 główne sposoby:

  • Ustawienie domyślne font-size we wszystkich witrynach.
  • powiększanie lub pomniejszanie widoku w poszczególnych witrynach;

Celem tej wersji demonstracyjnej jest dostosowanie typografii do rozmiaru widocznego obszaru przeglądarki i danych wprowadzanych przez użytkownika. Pamiętaj jednak, że im bardziej typografia reaguje na rozmiar okna przeglądarki, tym mniej będzie reagować na preferencje użytkownika. Jeśli zamierzasz wdrożyć responsywną typografię, musisz to zrobić ostrożnie i sprawdzić, czy wyniki są nadal dostępne.

Negocjowanie podstawowej wartości font-size na podstawie preferencji użytkownika

Pierwszym krokiem w określaniu typografii online jest ustalenie początkowego rozmiaru czcionki na podstawie font-size preferencji użytkownika. Będzie on używany w większości tekstu na stronie i jako podstawa dla innych rozmiarów czcionek, np. nagłówków. Najprostszym rozwiązaniem jest przyznanie użytkownikowi pełnej kontroli za pomocą opcji 1em bez żadnych korekt. Jeśli nie ustawisz żadnej innej wartości font-size, 1em odnosi się do preferencji użytkownika. Z drugiej strony ustawienie wartości font-size w pikselach lub innych jednostkach bezwzględnych (a nawet w jednostkach względnych do obszaru widocznego) całkowicie zastąpi ustawienia użytkownika, czego należy unikać.

Różne przypadki użycia wymagają jednak różnej typografii. Artykuł może być łatwiejszy do czytania w dużym tekście, a witryny z dużą ilością danych mogą wymagać bardziej kompaktowego projektu z mniejszym tekstem. W obu przypadkach możesz zaproponować domyślne ustawienie, które pasuje do projektu, ale jednocześnie umożliwić użytkownikowi dostosowanie wyniku do jego indywidualnej sytuacji.

Opcja 1. Obliczanie mnożnika na podstawie założeń

Jednym z częstych kompromisów jest zdefiniowanie skorygowanej wartości font-size w jednostkach em lub % w stosunku do domyślnej wartości font-size użytkownika. Zwykle ta metoda zakłada, że przeglądarki zapewniają 16px domyślne ustawienie, a większość użytkowników pozostawi je bez zmian. Jeśli uważasz, że rozmiar czcionki 20px będzie lepiej pasować do Twojej witryny, wartość font-size wynosząca 1.25em lub 125% zwykle da oczekiwany rezultat:

html {
  /* 20px preferred, 16px expected: 20/16 = 1.25 */
  font-size: 1.25em;
}

Możesz też użyć tutaj funkcji calc(), aby pokazać działanie matematyczne, ale nadal musisz znać równanie: rozmiar docelowy podzielony przez oczekiwany rozmiar pomnożony przez 1em:

html {
  font-size: calc(20 / 16 * 1em);
}

Użytkownicy z większymi lub mniejszymi preferencjami będą mieli pewien wpływ na wynik, ponieważ Twoja wartość domyślna jest teraz względna w stosunku do ich preferencji – w tym przypadku jest to 1,25 raza ich preferencji. Może to jednak dziwić, jeśli zarówno Ty, jak i użytkownik prosicie o wartości domyślne 20px, a wynikiem jest 25px – skorygowane wartości domyślne pomnożone ponownie przez 1,25 – rozmiar, o który nikt nie prosił.

Opcja 2. Pozwól clamp() wykonać pracę

Bardziej złożone podejście obejmuje funkcje porównywania CSS bez żadnych obliczeń. Zamiast zakładać, że 1em jest równy 16px, i przeprowadzać niewiarygodne konwersje z px na em, możesz traktować 1em jako zmienną, która odnosi się do preferencji użytkownika. Niezależnie od tego, jaką wartość piksela reprezentuje 1em, wartość font-size równa max(1em, 20px) zawsze zwróci większą z wartości preferowanej przez projektanta (20px) i wartości preferowanej przez użytkownika (1em). Dzięki temu użytkownik może wybrać większy, ale nie mniejszy rozmiar czcionki.

Przełączając się na funkcję clamp(), możesz zezwolić użytkownikowi na skalowanie w obu kierunkach, gdy preferowany rozmiar zbytnio odbiega od wybranego przez Ciebie rozmiaru domyślnego. Na przykład font-size o wartości clamp(1em, 20px, 1.25em) będzie domyślnie ustawiony na 20px, o ile jest to wartość większa niż domyślna wartość użytkownika, ale nie większa niż 125% domyślnej wartości użytkownika.

Dzięki temu Twój projekt będzie miał priorytet, gdy będzie zbliżony do preferencji użytkownika, ale użytkownik nadal będzie miał priorytet, gdy jego preferencje będą wykraczać poza określony zakres. Nie ma tu żadnych obliczeń konwersji, założeń dotyczących preferowanego rozmiaru użytkownika ani mnożenia wartości projektanta i użytkownika.

Ustawiając tę wartość jako główną font-size w elemencie html, możesz teraz odwoływać się do 1rem w dowolnym miejscu w witrynie jako wynegocjowanego rozmiaru podstawowego.

Dodawanie elastyczności

Aby element font-size reagował na widoczny obszar, możesz dodać punkty przerwania zapytania o media (lub zapytania o kontener). Możesz na przykład zmienić ograniczoną wartość w zależności od rozmiaru ekranu:

html {
  font-size: clamp(1em, var(--base-font-size, 16px), 1.25em);
  @media (width > 30em) { --base-font-size: 18px; }
  @media (width > 45em) { --base-font-size: 20px; }
}

Inną opcją jest dodanie jednostek widocznego obszaru lub kontenera do statycznej wartości bazowej:

html {
  font-size: clamp(1em, 16px + 0.25vw, 1.25em);
}

Jednostki vw (szerokość widocznego obszaru) lub vi (rozmiar w linii widocznego obszaru) reprezentują 1% całego widocznego obszaru, czyli części przeglądarki, która renderuje Twoją witrynę. Podobnie jednostki cqwcqi stanowią 1% kontenera o rozmiarze w linii na stronie. Więcej informacji znajdziesz w demonstracji zapytań i jednostek kontenera.

Takie podejście jest często określane jako płynna typografia, ponieważ zmiana font-size jest stała w zakresie szerokości widocznego obszaru, a nie skokowa w przypadku punktów przerwania multimediów lub kontenerów. Nie daj się jednak zwieść płynności przejścia – ta różnica jest zwykle widoczna tylko podczas testowania, jeśli płynnie dostosujesz rozmiar okna. Użytkownicy rzadko (lub nigdy) nie widzą tego efektu. Użytkownicy mogą regularnie zmieniać rozmiar przeglądarki lub poziom powiększenia, ale aby zauważyć różnicę między punktem przerwania a jednostką widocznego obszaru, muszą wprowadzać te zmiany powoli i płynnie. Wpływa to tylko na przejście, a nie na wynik po zmianie rozmiaru.

Główną zaletą elastycznego określania rozmiaru czcionki jest to, że nie musisz ręcznie obliczać ani określać punktów przerwania, ponieważ w przypadku każdego rozmiaru otrzymujesz interpolowany wynik. Ustawiasz tylko punkt początkowy (16px) i szybkość zmiany (0.25vw będzie oznaczać 0.25px wzrost font-size przy każdym 100px wzroście obszaru wyświetlania) oraz ewentualnie wartości minimalne i maksymalne. Gdy szerokość obszaru wyświetlania wynosi 1000px, wartość font-size będzie równa 16px + 2.5px lub 18.5px, ale to obliczenie jest w całości obsługiwane przez przeglądarkę. W wersji demonstracyjnej zastosowano to podejście, używając jednostek cqi do pokazania elastyczności opartej na kontenerach. Gdy są używane w elemencie głównym (html), w którym nie ma zdefiniowanego kontenera, jednostki cqi nadal odnoszą się do rozmiaru obszaru wyświetlania.

Jeśli wolisz myśleć w kategoriach określonych font-size przy danym rozmiarze obszaru wyświetlania, rozważ użycie bardziej bezpośredniego podejścia z zapytaniem o media, które jest nieco bardziej przejrzyste. Sytuacja się komplikuje, gdy próbujesz obliczyć jednostki widocznego obszaru na podstawie zamierzonych punktów przerwania. Wiele osób kopiuje i wkleja wartości z narzędzi innych firm, ale wynikowy kod jest znacznie trudniejszy do zrozumienia lub bezpośredniej zmiany. Ogólnie w przypadku CSS najlepsza opcja to ta, która najdokładniej wyraża Twoje intencje.

Ostrzeżenie: zmiany widocznego obszaru nie zawsze oznaczają to samo.

Zapytania multimedialne i jednostki vi są stosowane w różny sposób, ale obie metody opierają się na tym samym pomiarze widocznego obszaru. Jeśli widoczny obszar ma szerokość 600px, wartość 100vw będzie równa 600px, a style w zapytaniu o media (width > 500px) zostaną zastosowane.

Co jednak oznacza, że widoczny obszar ma szerokość 600px? W rzeczywistości piksel nie ma jednego stałego rozmiaru ani jednego znaczenia w każdej sytuacji. Chociaż wydaje się naturalne, że obszar widoku z mniejszą liczbą pikseli w poprzek znajduje się na mniejszym ekranie (np. telefonu) lub w wąskim oknie przeglądarki, nie jest to wiarygodne założenie. W rzeczywistości powiększenie i zmniejszenie okna przeglądarki będą miały taki sam wpływ na zmierzoną szerokość widocznego obszaru. Jedna czynność (powiększanie) zmienia rozmiar piksela, a druga (zmiana rozmiaru) zmienia rozmiar samej przeglądarki, ale obie wpływają na liczbę pikseli na szerokość przeglądarki. Pomiar obszaru widocznego w przeglądarce daje nam zależność między bieżącym rozmiarem piksela a bieżącym oknem przeglądarki.

Dla użytkownika powiększanie i zmiana rozmiaru służą zupełnie innym celom. Użytkownik, który zmienia poziom powiększenia, próbuje powiększyć lub pomniejszyć zawartość strony, ale użytkownik, który zmienia rozmiar przeglądarki, zarządza tylko przestrzenią na różnych ekranach. Chociaż intencje użytkowników są różne, wynik pomiarów w usłudze porównywania cen jest taki sam. Gdy okno się zmniejsza lub piksel się powiększa, na szerokości przeglądarki jest mniej pikseli.

Ten brak połączenia sprawia, że typografia responsywna jest niewiarygodna. Jeśli rozmiar tekstu jest dostosowywany tylko na podstawie widocznego obszaru lub kontenera, powiększenie przez użytkownika nie będzie miało wpływu na rozmiar tekstu.

Zmiana wartości jednostki względnej widocznego obszaru na 1vw lub 100vw zmieni dokładną zależność między rozmiarem czcionki a widocznym obszarem. Czcionka 1vw będzie powiększać się o 1px na każde 100px rozmiaru widocznego obszaru, a czcionka 100vw będzie miała dokładnie taki sam rozmiar jak widoczny obszar. Możesz zmienić tę wartość, aby czcionka rosła wolniej lub szybciej w stosunku do przeglądarki. Wartość względna widocznego obszaru pozostanie jednak stała, gdy użytkownik będzie powiększać lub pomniejszać obraz – nie będzie reagować na jego działania.

Podobnie ani konto 1vw, ani konto 100vw nie są domyślnym kontem użytkownika font-size.

Używanie jednostek względnych w stosunku do widocznego obszaru lub kontenera w przypadku font-size jest zawsze niekorzystne dla użytkownika. Gdy font-size w pełni reaguje na swój kontener, nie może też reagować na ustawienia domyślne użytkownika ani na jego dostosowania. Nawet przy najlepszych intencjach i zabezpieczeniach należy unikać odbierania użytkownikom ostatecznej font-size kontroli. Nie tylko pogarsza to wrażenia użytkowników, ale może też naruszać wytyczne dotyczące ułatwień dostępu, które często są wymagane przez prawo. W szczególności sekcja 1.4.4 wytycznych WCAG wymaga, aby „tekst można było powiększyć bez użycia technologii wspomagających do 200%”.

Jak zapewnić, że wartości font-size reagują na powiększenie

Aby zapewnić, że jednostka font-size jest dostosowywana do powiększenia, wartość względna do widocznego obszaru musi być stosowana jako korekta do innej wartości. W CSS jest to możliwe dzięki funkcji calc() lub dowolnej innej funkcji matematycznej, która akceptuje obliczenia, np. min(), max() i clamp(). Wartość font-size wynosząca calc(16px + 1vw) zależy zarówno od rozmiaru widocznego obszaru, jak i od bieżącego (względnego w stosunku do powiększenia) rozmiaru piksela. Na vw jednostkę nie będzie miał wpływu zoom, ale na wartość bazową już tak.

W rezultacie otrzymasz font-size, który reaguje zarówno na rozmiar widocznego obszaru, jak i na ustawienia powiększenia użytkownika. Jeśli użytkownik powiększy obraz do 200%, wartość podstawowa będzie 2 razy większa (32px), a wartość dostosowana nie ulegnie zmianie. 1000px widoczny obszar początkowo da Ci font-size o wartości 16px + 10px = 26px, ale przy powiększeniu 200% rozmiar czcionki wzrośnie tylko do 42px, czyli nieco ponad 160%. Może się to nie wydawać poważnym problemem, ale im bardziej font-size zależy od obszaru widocznego, tym mniej skuteczny staje się zoom.

Na małych ekranach wartość font-size będzie pochodzić głównie z podstawowej wartości piksela i będzie dobrze reagować na powiększenie. Na większych ekranach rozmiar obszaru wyświetlania stanowi jednak większą część renderowanego rozmiaru czcionki, co zmniejsza skuteczność powiększania. Staje się to szczególnie niebezpieczne, gdy powiększenie o 500% (maksymalne w większości przeglądarek) nie zapewnia już 200-procentowego zwiększenia rozmiaru czcionki wymaganego przez WCAG 1.4.4. Jednak nawet wcześniej może być frustrujące, gdy powiększenie przestaje być skuteczne.

Wykres przedstawiający rozmiar czcionki i skuteczność powiększenia w zależności od szerokości obszaru wyświetlania. Rozmiar czcionki, obliczany jako „calc(17px + 2.5vw)”, rośnie liniowo wraz z szerokością widocznego obszaru. Linia powiększenia 500%, która reprezentuje maksymalne możliwe powiększenie, pokazuje, że powiększenie staje się mniej skuteczne wraz ze wzrostem szerokości widocznego obszaru. Nie zapewnia ono 200-procentowego zwiększenia rozmiaru czcionki powyżej szerokości widocznego obszaru wynoszącej 2040 pikseli.
Oś pozioma przedstawia rozmiar widocznego obszaru w zakresie od 0 do 2600px pikseli szerokości. Oś pionowa dla font-size jest również podana w pikselach i pokazuje wynik calc(17px + 2.5vw). 500% Linia powiększenia korzysta z tej samej osi poziomej o szerokości widocznego obszaru, ale oś pionową traktuje jako wartość procentową.

Na lewej krawędzi wykresu (0 szerokość obszaru wyświetlania) 500% powiększenie jest w pełni skuteczne. Jednak skuteczność ta szybko spada wraz ze wzrostem rozmiaru przeglądarki, a jednostki widoku (których nie można powiększać) stają się ważniejszym czynnikiem w font-size. Gdy szerokość przeglądarki wynosi 2040px, maksymalne powiększenie 500% pozwala tylko na zwiększenie rozmiaru czcionki o 200%. Po przekroczeniu tej wartości 200% nie będzie już możliwe.

Przenosząc to obliczenie do funkcji clamp() z wartościami minimalną i maksymalną, możesz wymusić granice, które zapewnią możliwość powiększania tekstu. Według Maxwella Barviana:

Jeśli maksymalny rozmiar czcionki jest nie większy niż 2,5-krotność minimalnego rozmiaru czcionki, tekst zawsze będzie zgodny z kryterium sukcesu 1.4.4 WCAG, przynajmniej we wszystkich nowoczesnych przeglądarkach.

Zapytania @media@container są oparte na tych samych pomiarach co jednostki vwcqw, więc ta sama logika ma zastosowanie, gdy używasz punktu przerwania do zmiany rozmiaru czcionki. Gdy powiększenie jest zbyt duże, staje się nieskuteczne. W tej wizualizacji możesz sprawdzić, jak te wartości na siebie wpływają:

Jak zadbać o to, aby wartości font-size reagowały na ustawienia domyślne użytkownika

Jednak calc(16px + 1vw) nadal nie reaguje na domyślne ustawienia czcionki użytkownika. Aby to zrobić, możesz ustawić wartość bazową lub wartości minimalne i maksymalne, używając jednostek em lub rem zamiast px. Po połączeniu tych elementów otrzymasz znany wynik, który pasuje do połączonej wersji demonstracyjnej:

html {
  font-size: clamp(1em, 17px + 0.24vw, 1.125em);
}

Uwaga:

  • Zarówno minimalna, jak i maksymalna wartość używają jednostek em, które są oparte na preferencjach użytkownika (i reagują na powiększenie).
  • Dodatkowa wartość vw jest utrzymywana na minimalnym poziomie, aby nie wpływać zbytnio na powiększenie.
  • Maksymalny rozmiar (1.125em) jest znacznie mniejszy niż 2,5-krotność minimalnego rozmiaru (1em), co zapewnia, że efektywna wartość font-size wynosząca 200% jest zawsze możliwa.

Skale typograficzne z pow()

Większość projektów korzysta z więcej niż jednego rozmiaru czcionki. Skala typograficzna opisuje relację między wieloma rozmiarami czcionek. Można to wyrazić jako rozmiar podstawowy i serię mnożników do obliczania innych rozmiarów. CSS udostępnia wbudowaną skalę typograficzną względem słowa kluczowego medium, które odnosi się do preferowanego rozmiaru czcionki użytkownika lub domyślnego rozmiaru 16px. Pełna skala słów kluczowych to:

  • xx-small: 3/5 (0,6)
  • x-small: 3/4 (0,75)
  • small: 8/9 (0,89)
  • medium: 1 (rozmiar podstawowy, przez który mnożone są inne rozmiary)
  • large: 6/5 (1.2)
  • x-large: 3/2 (1,5)
  • xx-large: 2/1 (2)
  • xxx-large: 3/1 (3)

Ta skala jest względna w stosunku do domyślnego rozmiaru czcionki użytkownika, a nie do głównego rozmiaru czcionki font-size, więc nie działa tak dobrze po zmianie głównego rozmiaru czcionki font-size w witrynie. Większość autorów tworzy podobną skalę typograficzną z użyciem właściwości niestandardowych – czasami używają tych samych nazw rozmiarów koszulek, a czasami wolą serię kroków w górę i w dół skali matematycznej. Istnieje wiele narzędzi innych firm, które generują te skale na podstawie typowych proporcji, głównie zaczerpniętych z zachodniej skali muzycznej:

html {
  /* musical ratios */
  --minor-second: calc(16/15);
  --major-second: calc(9/8);
  --minor-third: calc(6/5);
  --major-third: calc(5/4);
  --perfect-fourth: calc(4/3);
  --augmented-fourth: sqrt(2);
  --perfect-fifth: calc(3/2);
  --major-sixth: calc(5/3);

  /* the golden ratio*/
  --golden-ratio: calc((1 + sqrt(5)) / 2);
}

Nie musisz jednak używać zewnętrznych narzędzi, aby utworzyć własną skalę w usłudze porównywania cen. Nowa funkcja pow() może wygenerować ją za Ciebie, a 1rem będzie Twoim rozmiarem podstawowym.

html {
  /* choose a ratio */
  --scale: 1.2;

  /* generate the scale using pow() */
  --xx-small: calc(1rem * pow(var(--scale), -0.5));
  --x-small: calc(1rem * pow(var(--scale), -0.25));
  --small: calc(1rem * pow(var(--scale), -0.125));
  --medium: 1rem;
  --large: calc(1rem * pow(var(--scale), 1));
  --x-large: calc(1rem * pow(var(--scale), 2));
  --xx-large: calc(1rem * pow(var(--scale), 3));
  --xxx-large: calc(1rem * pow(var(--scale), 4));

  /* change the ratio for different viewport sizes */
  @media (width > 50em) {
    --scale: var(--perfect-fourth);
  }
}

Aby zachować spójność skali, nie musisz używać całych kroków. W rzeczywistości popularna skala typograficzna 12pt wykorzystuje około 5 ułamków na krok. Duże rozmiary są tu skalowane w całych krokach, a małe – w ułamkach, co pozwala na wolniejsze skalowanie.

Funkcje i miksowanie CSS umożliwiają jeszcze większe skondensowanie tej logiki, a inne wbudowane narzędzia, takie jak progress(), ułatwiają tworzenie skal, które płynnie dostosowują się od jednej wartości do drugiej. Te funkcje nie są jednak objęte tym demo.

dostosowywać się do rozmiaru kontenerów na stronie;

Aby wszystkie te obliczenia działały w przypadku zapytań o kontener, możesz użyć jednostki cqi zamiast vw lub vi. Warto jednak pozostawić jednostkę font-size użytkownika w elemencie html, aby każdy kontener ustawień typu mógł odwoływać się do preferencji użytkownika jako 1rem. W wersji demonstracyjnej zobaczysz, że cała skala typograficzna jest stosowana do elementu body, a nie do elementu głównego html w przypadku globalnego typu, a następnie resetowana na podstawie rozmiaru kontenera dla każdego elementu z atrybutem type-set.

Zawsze wiąże się to z kompromisem w przypadku rozmiarów czcionek względnych względem kontenera. Uzyskujesz bardziej płynne skalowanie czcionek w przypadku poszczególnych elementów w kontekście, ale kosztem spójności na całej stronie. To, która z nich jest dla Ciebie ważniejsza, zależy od konkretnego przypadku użycia. Pamiętaj, że płynna typografia to kompromis, który sprawia, że elementy sterujące, takie jak powiększenie, są mniej skuteczne.

Elastyczna typografia i skale typograficzne to świetne narzędzia dla projektantów, ale jeśli nie musisz, nie komplikuj sobie pracy. Domyślna i wbudowana skala typów użytkownika to też świetna opcja. Jeśli jednak zdecydujesz się na typografię elastyczną, sprawdź, jak wyniki zachowują się w przypadku różnych ustawień domyślnych użytkownika i ustawień powiększenia. Miłej zabawy!