Co robi clamp()
clamp(MIN, PREFERRED, MAX) przyjmuje trzy wartości i zwraca środkową, dopóki mieści się ona między dwiema pozostałymi. Klasyczne zastosowanie to nagłówek, który rośnie razem z ekranem, ale zatrzymuje się na rozsądnych granicach, bez media query:
Wartość preferowana to 1rem + 3vw: 16px plus 3% szerokości. W podglądzie o szerokości 800px to 16 + 24 = 40px, czyli między 24px (1.5rem) a 48px (3rem), więc nagłówek ma 40px. Na telefonie o szerokości 320px wartość preferowana to 25.6px. Powyżej 1067px przekroczyłaby 48px, więc zatrzymuje się na 48px. Zmień rozmiar okna i obserwuj, jak zmienia się liczba; vw oznacza tu procent szerokości ramki podglądu.
Zobacz to bez zmiany rozmiaru okna
vw podąża za obszarem widoku, którego nie zmienisz łatwo podczas czytania. Jednostki zapytań kontenerowych podążają za kontenerem: cqi to 1% szerokości kontenera. Przesuń suwak, żeby zmienić pudełko, a ten sam rodzaj clamp() zareaguje:
Przesuń suwak na początek, a tytuł zatrzyma się na 20px (MIN). Przesuń na koniec, a zatrzyma się na 40px (MAX). Pomiędzy podąża za 0.5rem + 6cqi. To ten sam mechanizm co w wersji z vw, tylko z mniejszą linijką.
Trzy argumenty
font-size: clamp(1rem, 0.8rem + 1vw, 1.5rem);
/* MIN PREFERRED MAX */
| Argument | Rola | Typowa jednostka |
|---|---|---|
| MIN | najmniejsza możliwa wartość | rem |
| PREFERRED | wartość, która zmienia się z ekranem | rem + vw (albo cqi) |
| MAX | największa możliwa wartość | rem |
Obliczenia działają w każdym argumencie bez pisania calc(): 1rem + 2vw jest poprawne w tej postaci. + i - potrzebują spacji z obu stron, bo inaczej cała deklaracja jest niepoprawna.
Jeśli MIN jest większe niż MAX, wygrywa MIN: clamp(3rem, 5vw, 2rem) to zawsze 3rem.
Obliczanie wartości środkowej
Żeby czcionka rosła od 16px na ekranie 320px do 24px na ekranie 1280px:
- Nachylenie: (24 − 16) ÷ (1280 − 320) = 8 ÷ 960 = 0.00833, czyli 0.833vw (vw liczy się na 100px).
- Punkt startowy: 16px − 0.00833 × 320px = 13.33px, czyli 0.833rem.
- Dodaj granice wokół:
font-size: clamp(1rem, 0.833rem + 0.833vw, 1.5rem);
Przy szerokości 320px daje to 13.33 + 2.67 = 16px, przy 1280px daje 13.33 + 10.67 = 24px, a poza tym zakresem wartość zostaje na granicach. Internetowe "kalkulatory clamp" wykonują dokładnie te obliczenia.
min() i max()
clamp() to połączenie dwóch prostszych funkcji:
min(a, b)zwraca mniejszą wartość, więc ustawia górną granicę.max(a, b)zwraca większą wartość, więc ustawia dolną granicę.clamp(MIN, VAL, MAX)to to samo comax(MIN, min(VAL, MAX)).
Nazwy na początku wydają się odwrócone: żeby powiedzieć "najwyżej 600px", używasz min().
W szerokim podglądzie pierwsza karta zatrzymuje się na 420px. Wewnątrz rodzica o szerokości 260px mniejszą wartością jest 100%, więc druga karta ma 260px. max(12px, 3%) daje pierwszej karcie 3% szerokości rodzica (body: około 23.5px w podglądzie 800px), a drugiej 12px, bo 3% z 260px (7.8px) jest poniżej dolnej granicy.
width: min(100%, 420px) zastępuje starszą parę width: 100%; max-width: 420px; jedną deklaracją.
Nie tylko czcionki: odstępy i szerokości
clamp() działa w każdej właściwości, która przyjmuje długość. Procenty w wartości środkowej sprawiają, że komponent jest płynny względem rodzica, a nie obszaru widoku:
W rodzicu o szerokości 300px karta ma 240px (80%) i 15px paddingu (5% z 300px). W rodzicu 760px 80% dałoby 608px, więc karta zatrzymuje się na maksimum 520px, a 5% z 760px to 38px, więc padding zatrzymuje się na 32px.
Dostępność: trzymaj rem w wartości środkowej
Rozmiar czcionki zbudowany tylko z vw, na przykład font-size: 5vw, nie rośnie, gdy czytelnik zwiększy domyślny rozmiar czcionki w ustawieniach przeglądarki, i nie rośnie też przy powiększeniu strony, bo powiększenie zwęża obszar widoku liczony w pikselach CSS. Dodanie części rem (1rem + 2vw) i granic w rem wiąże tekst z ustawieniem czytelnika. Jednostki rem i vw szczegółowo omawia strona o jednostkach.
Częste błędy
- Używanie
min()jako minimum.min()wybiera mniejszą wartość, czyli górną granicę. Dla "co najmniej 12px" użyjmax(12px, ...). - Brak spacji wokół
+albo-.clamp(1rem, 1rem+2vw, 3rem)jest niepoprawne i właściwość wraca do poprzedniej wartości. - Samo
vww środku. Tekst ignoruje wtedy ustawienie rozmiaru czcionki czytelnika. Dodaj składnikrem. - MIN większe niż MAX. Wynikiem zawsze jest MIN, co rzadko było zamierzone.
- Granice w
pxdla rozmiarów czcionek. Ograniczają tekst nawet u czytelników, którzy potrzebują większego. Użyjrem.
Najczęściej zadawane pytania
Co robi clamp() w CSS?
clamp(MIN, PREFERRED, MAX) używa wartości preferowanej, dopóki mieści się ona między dwiema granicami, a w przeciwnym razie najbliższej granicy. font-size: clamp(1rem, 4vw, 2rem) podąża za 4% szerokości obszaru widoku, ale nigdy nie spada poniżej 1rem ani nie przekracza 2rem.
Jak zrobić responsywny rozmiar czcionki z clamp?
Umieść w środku wartość zależną od obszaru widoku, a po bokach stałe granice, i dodaj do środka rem, żeby tekst nadal reagował na ustawienie rozmiaru czcionki czytelnika: font-size: clamp(1.5rem, 1rem + 2vw, 3rem);.
Co się dzieje, gdy minimum w clamp() jest większe niż maksimum?
Wygrywa minimum. clamp(3rem, 5vw, 2rem) zawsze daje 3rem, bo clamp() stosuje minimum po maksimum.
Czym różni się min() od max() w CSS?
min() zwraca najmniejszą ze swoich wartości, więc działa jak górna granica: width: min(100%, 600px) nigdy nie jest szersze niż 600px. max() zwraca największą, więc działa jak dolna granica: font-size: max(1rem, 2vw) nigdy nie jest mniejsze niż 1rem.
Czy clamp() działa we wszystkich przeglądarkach?
Tak, clamp(), min() i max() działają we wszystkich obecnych wersjach Chrome, Edge, Firefoksa i Safari i można ich używać w każdej właściwości, która przyjmuje długość, liczbę, procent albo kąt.