Fluid Typescaling ​
INFO
Even een heads up, alle voorbeelden in deze gids gebruiken lettergrootte om de magie van responsieve schaal te demonstreren. Maar onthoud, clamp is niet alleen voor fonts. Je kunt het gebruiken om elke numerieke eigenschap responsief te schalen, zoals padding, marges, afmetingen en nog veel meer.
Vroeger draaiden design systems om statische lettergroottes. Je had een basislettergrootte, en vervolgens een reeks variabelen voor grotere en kleinere lettergroottes:
html {
--cds-sys-typescale-title-large-font-size: 1.38rem;
--cds-sys-typescale-title-medium-font-size: 1rem;
--cds-sys-typescale-title-small-font-size: 0.88rem;
--cds-sys-typescale-body-large-font-size: 1rem;
--cds-sys-typescale-body-medium-font-size: 0.88rem;
--cds-sys-typescale-body-small-font-size: 0.75rem;
}Maar er was een probleem: Omdat elke stap in de typeschaal een vaste lettergrootte had, moest je vaak media queries schrijven om de lettergrootte aan te passen op verschillende viewport-breedtes om de leesbaarheid te waarborgen. Dit zorgde niet alleen voor meer CSS, maar het was ook een beetje omslachtig om te implementeren—je had vaak twee sets waarden nodig voor mobiele en desktoplettergroottes van de designers. Bovendien veranderden de lettergroottes plotseling wanneer het scherm een bepaalde breakpoint bereikte, in plaats van vloeiend op en neer te schalen.
Vloeiende typografie is de nieuwe oplossing die dit probleem oplost. Het maakt het mogelijk dat elke lettergrootte in een typeschaal responsief varieert tussen een minimum en maximum. Het is een hot topic in de CSS-wereld: er zijn talloze artikelen over hoe je vloeiende schaling in CSS kunt implementeren, en er zijn diverse open-source tools beschikbaar waarmee je vloeiende lettergrootte-declaraties rechtstreeks in je project kunt kopiëren. Dit alles is mogelijk dankzij de clamp-functie van CSS en de kracht van viewport-eenheden.
Een van de lastigste delen van het gebruik van clamp is het bepalen van de juiste voorkeurswaarde. Dit zou je handmatig kunnen doen, maar het denken in viewport-eenheden is niet echt intuïtief, tenzij je met veelvoorkomende percentages werkt. Om het makkelijker te maken, kunnen we een handige Sass-functie maken die de native clamp van CSS omwikkelt en automatisch de voorkeurswaarde berekent, gegeven een minimale en maximale lettergrootte en een minimale en maximale breakpoint.
De Magie van clamp Begrijpen ​
Kort samengevat neemt clamp een voorkeurswaarde en houdt deze binnen een onder- en bovengrens:
.element {
font-size: clamp(min, preferred, max);
}clamp zal altijd proberen de voorkeurswaarde te gebruiken, zolang die waarde binnen de minimum- en maximumwaarden valt. Als de voorkeurswaarde kleiner is dan het minimum, zal clamp de minimumwaarde retourneren. Aan de andere kant, als de voorkeurswaarde groter is dan het maximum, zal clamp de maximumwaarde retourneren. Vandaar de naam clamp—het klemt een waarde tussen twee grenzen.
De Kracht van clamp en Viewport-eenheden: Een Dynamisch Duo ​
Op het eerste gezicht lijkt de clamp-functie van CSS misschien wat eenvoudig. Echter, in combinatie met viewport-breedte (vw) eenheden, wordt het een krachtig hulpmiddel voor het maken van responsieve ontwerpen die zich naadloos aanpassen aan verschillende schermgroottes. Door gebruik te maken van clamp en vw-eenheden kun je media queries voor lettergroottes achterwege laten en vertrouwen op dynamische waarden die vloeiend schalen.
Stel je vw voor als een meetlint dat meebeweegt met de breedte van het scherm. Eén vw is gelijk aan één procent van de huidige viewport-breedte. Bijvoorbeeld, 10vw vertegenwoordigt 10% van de viewport-breedte. Als de viewport 600px breed is, komt 10vw overeen met 60px.
De clamp-functie werkt door een waarde binnen een gedefinieerd bereik te houden. Het neemt drie argumenten: een minimumwaarde, een voorkeurswaarde en een maximumwaarde. De browser probeert de voorkeurswaarde te gebruiken, maar als die buiten het bereik valt, past hij de minimum- of maximumwaarde toe, zodat de waarde binnen de gedefinieerde grenzen blijft.
Laten we een voorbeeld bekijken van hoe clamp en vw kunnen worden gebruikt om een responsieve lettergrootte in te stellen:
p {
font-size: clamp(1rem, 4vw, 1.5rem);
}In dit voorbeeld definiëren we het volgende bereik voor de lettergrootte:
- Minimum:
1rem(16px) - Voorkeur:
4vw - Maximum:
1.5rem(24px)
De browser zal eerst proberen de voorkeurswaarde toe te passen, wat 4vw is. De daadwerkelijke waarde hangt echter af van de viewport-breedte. Bijvoorbeeld:
| Viewport-breedte | Voorkeurswaarde | Waarde van Clamp |
|---|---|---|
320px | 12.8px | 1rem |
500px | 20px | 20px |
1000px | 40px | 1.5rem |
Zoals je kunt zien, past de lettergrootte zich dynamisch aan op basis van de viewport-breedte, wat zorgt voor optimale leesbaarheid op verschillende apparaten.
Hoewel deze aanpak effectief is, kan het handmatig berekenen van de voorkeurswaarde tijdrovend en foutgevoelig zijn. Om dit proces te vereenvoudigen, kunnen we gebruik maken van Sass, een CSS-preprocessor waarmee we aangepaste functies kunnen maken. Met Sass kunnen we een aangepaste clamp-functie definiëren die de voorkeurswaarde automatisch berekent op basis van de gewenste lettergrootte bij een referentie-viewport-breedte. Dit elimineert de noodzaak van handmatige berekeningen en vereenvoudigt het proces van het creëren van responsieve lettergroottes.
Voordat we in de aangepaste clamp-functie duiken, laten we eerst dieper ingaan op de relatie tussen lettergrootte en viewport-breedte om de wiskundige formule achter de voorkeurswaarde-berekening te begrijpen.
De Voorkeurswaarde Bepalen voor Clamp met Lineaire Interpolatie ​
Tot nu toe hebben we niet bekeken hoe de voorkeurswaarde voor clamp precies berekend wordt. In theorie kun je een willekeurige waarde invullen en hopen dat deze werkt, zoals we eerder deden. Maar het blijkt dat we met wiskundige precisie de juiste voorkeurswaarde kunnen bepalen.
Eerst moeten we ons realiseren dat we meestal niet zomaar een minimale en maximale lettergrootte willen instellen zonder dat deze gekoppeld zijn aan een schermbreedte. Dus in plaats van te zeggen dat we een minimale lettergrootte van 16px en een maximale van 19px willen, moeten we het probleem anders formuleren. Bijvoorbeeld:
"Ik wil een minimale lettergrootte van
16pxbij een viewportbreedte van400pxen een maximale lettergrootte van19pxbij een viewportbreedte van1000px."
Nu hebben we vier waarden in plaats van slechts twee:
- Een minimale lettergrootte (
16px). - Een maximale lettergrootte (
19px). - De viewportbreedte waarbij
clampde minimale waarde moet gebruiken (400px). - De viewportbreedte waarbij
clampde maximale waarde moet gebruiken (1000px).
Omdat het minimumkader overeenkomt met de minimale lettergrootte en het maximumkader overeenkomt met de maximale lettergrootte, is het logisch om deze waarden samen te voegen als een set van twee (x, y) punten in de vorm (schermbreedte, lettergrootte):
- Minimaal:
(400px, 16px) - Maximaal:
(1000px, 19px)
Op de grafiek hieronder zien we dit terug: op de x-as staat de viewportbreedte en op de y-as de lettergrootte. Terwijl de viewportbreedte toeneemt van het minimum- naar het maximumkader, neemt ook de lettergrootte toe. De lijn tussen het minimum en maximum stelt de voorkeurswaarde voor clamp voor.

Wat is nu de formule voor deze lijn? Als we deze kunnen bepalen, hebben we een uitdrukking die we kunnen invoegen voor de voorkeurswaarde van clamp. We hebben het minimum en maximum voor clamp al, dus deze formule is het ontbrekende stukje.
De formule voor een lijn wordt gegeven door de richtingscoëfficiënt:
Om de helling van deze lijn
Ontsleutelen van de Formule voor de Voorkeurswaarde
De formule voor de voorkeurswaarde in clamp() is afgeleid van de richtingscoëfficiëntvorm van een lineaire vergelijking:
In deze context vertegenwoordigt
Om de waarden van
Berekening van de Helling
De helling
Met de waarden van ons minimum- en maximumpunt krijgen we:
Dit betekent dat voor elke één eenheid toename in viewportbreedte de lettergrootte met 0.005 pixels toeneemt.
Berekening van het y-snijpunt
Het y-snijpunt
Dus het y-snijpunt
Complete Formule voor de Voorkeurswaarde
Nu we clamp()-functie opschrijven:
Deze formule berekent de gewenste lettergrootte voor elke gegeven viewportbreedte 100 te vermenigvuldigen, krijgen we:
Deze formule kan direct in de clamp()-functie worden gebruikt om de lettergrootte dynamisch aan te passen op basis van de viewportbreedte.
Met de waarden uit ons voorbeeld krijgen we deze uitkomst:
m = (19px - 16px) / (1000px - 400px) = 3px/600px = 0.005We hebben bepaald dat de helling van de lijn die de gewenste overgang in lettergrootte weergeeft 0.005 is. Dit betekent dat voor elke eenheid toename in viewportbreedte de lettergrootte met 0.005 pixels toeneemt.
Vervolgens berekenen we het y-snijpunt met behulp van de helling en een van de oorspronkelijke punten (minimum of maximum). In dit geval, door het minimale punt (400px, 16px) te gebruiken, vinden we dat het y-snijpunt 14px is.
Nu hebben we twee cruciale onderdelen van de vergelijking:
- Helling: 0.005
- y-snijpunt: 14px
Met deze waarden kunnen we de voorkeurswaarde voor de clamp()-functie bepalen:
voorkeurswaarde = y = mx + b = 0.005(x) + 14pxWaarbij x de viewportbreedte vertegenwoordigt.
Aangezien CSS viewport-eenheden gebruikt, moeten we de helling omzetten naar een percentage. Door de helling met 100 te vermenigvuldigen, krijgen we:
voorkeurswaarde = y = 0.5vw + 14pxNu kunnen we deze voorkeurswaarde direct in de clamp()-functie gebruiken om de lettergrootte dynamisch te laten schalen op basis van de viewportbreedte.
p {
font-size: clamp(16px, 0.5vw + 14px, 19px);
}We hebben nu de perfecte voorkeurswaarde bepaald voor de CSS clamp()-functie, wat zorgt voor een vloeiende en adaptieve overgang in lettergrootte over verschillende schermgroottes.
Om onze formule te testen, kunnen we enkele getallen invullen en zien of de berekende voorkeurswaarden overeenkomen met onze verwachtingen:
| Viewportbreedte | Voorkeurswaarde |
|---|---|
400px (minimale breekpunt) | 0.005 * 400px + 14px = 16px |
700px (halverwege) | 0.005 * 700px + 14px = 17.5px |
1000px (maximale breekpunt) | 0.005 * 1000px + 14px = 19px |
Zoals verwacht, stemmen de berekende voorkeurswaarden precies overeen met de verwachte waarden voor elke viewportbreedte, wat de geldigheid van onze formule bevestigt.
Om ervoor te zorgen dat lettergroottes harmonieus schalen met de lettergrootte-instellingen van de browser, moeten we de pixelwaarden omzetten naar rem. Aangezien de standaard root-lettergrootte voor alle browsers 16px is, delen we elke pixelwaarde door 16px:
p {
font-size: clamp(1rem, 0.5vw + 0.875rem, 1.1875rem);
}Hieronder de stappen die we hebben genomen om tot deze oplossing te komen:
Bepaal Min en Max Punten: Stel twee punten in die de gewenste fontgroottes vertegenwoordigen bij specifieke viewport-breedtes. Bijvoorbeeld
(400px, 16px)geeft een fontgrootte van 16px aan bij een viewport van 400px breed.Bereken Helling
: Gebruik de formule , waarbij en de fontgroottes zijn op de maximale en minimale punten, en en de bijbehorende viewport-breedtes. Bereken Y-intercept
: Gebruik de helling en één van de oorspronkelijke punten (minimum of maximum) om de y-intercept te vinden met de vergelijking . Bepaal de Voorkeurswaarde: De voorkeurswaarde wordt gegeven door de formule
( voorkeurswaarde = y = mx + b).Converteer Pixels naar Rems: Deel de pixelwaarden (fontgroottes) door 16px (de root font size) om ze in rems uit te drukken. Dit zorgt voor een betere responsiviteit op basis van browser-instellingen voor tekstgrootte.
Door deze stappen te volgen, kun je de voorkeurswaarde voor clamp() bepalen en een responsieve fontgrootte-schaal implementeren met CSS.
Een Custom Clamp Functie in Sass Maken ​
Een Sass-functie werd gemaakt die een minimum en maximum waarde accepteert, samen met hun bijbehorende minimum- en maximum-schermgroottes.
p {
font-size: unit.to-fluid-scale(16px, 19px, 400px, 1000px);
}Standaardwaarden voor de breekpunten worden ingesteld zodat deze niet telkens opnieuw moeten worden opgegeven. De functie retourneert dan de volgende CSS, waarbij alle berekeningen achter de schermen plaatsvinden:
p {
font-size: clamp(1rem, 0.5vw + 0.875rem, 1.1875rem);
}De standaardwaarden voor de minimale en maximale breekpunten worden opgeslagen in het configuratiebestand van ons theming-module (libs/theming/src/lib/config/_index.scss):
$_initial-config: (
//[...]
//voor vloeiende schaalverdeling,
min-screen-width: 320px,
max-screen-width: 1280px,
//[...]
);Helling en Intercept Berekenen ​
Eerst moet de helling worden berekend voor de vergelijking die de voorkeurs clamp-waarde vertegenwoordigt. Deze helling wordt berekend door het verschil tussen de maximale en minimale waarden te delen door het verschil tussen de bijbehorende schermgroottes. Zodra de helling bekend is, kan de intercept worden berekend door een bekende schermgrootte in de vergelijking te plaatsen en de clamp-waarde te berekenen.
@use 'sass:math';
$slope: math.div(($max-size - $min-size), ($max-screen - $min-screen));
$y-intercept: (-$min-screen-width * $slope) + $min-size;
$slope-vw: $slope * 100;Zodra de helling en intercept zijn bepaald, kan een standaard CSS clamp-declaratie worden geretourneerd vanuit de Sass-functie, waarbij alle relevante waarden worden geïnterpoleerd.
@return clamp(#{$min-px}, #{$slope-vw}vw + #{$y-intercept}, #{$max-px});Het is echter beter om geen pixels te gebruiken voor font sizing. Om dit probleem op te lossen, kan een andere Sass-functie worden gemaakt om pixels om te zetten naar rems.
@use 'sass:meta';
@use 'sass:math';
@function px-to-rem($px) {
@if $px == null {
@return null;
}
@if meta.type-of($px) != 'number' or $px == 0 or not math.compatible($px, 1px) {
// De waarde is iets anders dan px, gebruik deze zoals hij is.
@return $px;
}
@return math.div($px, 16px) * 1rem;
}De px-to-rem functie zal worden gebruikt om alle pixels om te zetten naar rems. Hier is de uiteindelijke code:
@use 'sass:math';
@function to-fluid-scale($min-size, $max-size, $min-screen, $max-screen) {
@if $min-size == 0 and $max-size == 0 {
@return 0;
}
$min-size: px-to-rem($min-size);
$max-size: px-to-rem($max-size);
$min-screen-width: px-to-rem($min-screen);
$max-screen-width: px-to-rem($max-screen);
$slope: math.div(($max-size - $min-size), ($max-screen-width - $min-screen-width));
$y-intercept: (-$min-screen-width * $slope) + $min-size;
$slope-vw: $slope * 100;
@return clamp(#{$min-size}, #{$y-intercept} + #{$slope-vw}vw, #{$max-size});
}Houd er rekening mee dat afhankelijk van de waarden die in deze functie worden doorgegeven, het resultaat lange decimale getallen kan bevatten. Een aangepaste afrondingsfunctie kan worden gebruikt om deze getallen af te ronden.