Hoppa till huvudinnehåll

Från fysiska till logiska egenskaper

· 9 min att läsa
Filip Tammergård
Programmerare på Frilans Finans

De senaste månaderna har jag dykt ner i logiska egenskapers vackra värld. CSS-specifikationen har en mening som jag tycker beskriver vad logiska egenskaper är på ett bra sätt:

[Logiska] egenskaper är writing-mode-relativa motsvarigheter till sina fysiska motsvarigheter.

Fysiska egenskaper är enkla att resonera kring eftersom de representerar fysiska riktningar. Top, right, bottom och left är absoluta riktningar. Vänster är alltid vänster – så enkelt är det. Logiska egenskaper är däremot relativa – den fysiska riktningen de motsvarar varierar.

Som nämnts gör den absoluta naturen hos fysiska egenskaper att de är enkla att resonera kring. Men den absoluta naturen är också en begränsning.

Problemet med fysiska egenskaper

Säg att vi vill visa ett citat med en röd ram till vänster och lite padding:

<blockquote>Hello</blockquote>
blockquote {
border-left: 2px solid red;
padding-left: 1rem;
}

Resultat:

Hello

Coolt!

Men vad händer om vi översätter stycket till arabiska? Arabiska har textriktning från höger till vänster, så vi anger det med dir="rtl" och markerar att arabiska används i stycket med lang="ar". Vi testar att ändra textriktning medan vi behåller samma CSS:

<blockquote dir="rtl" lang="ar">أهلا</blockquote>

Resultat:

أهلا

Det är inte vad vi vill ha... 😕

När textriktningen ändras vill vi att marginalen ska följa med. Men vänster är fortfarande vänster, även när textriktningen ändras.

In med logiska egenskaper

Vi testar med logiska egenskaper i stället!

<blockquote>Hello</blockquote>
blockquote {
border-inline-start: 2px solid red;
padding-inline-start: 1rem;
}

Resultat:

Hello

Vi tittar på vad som händer nu när vi översätter till arabiska.

Vi byter textriktning igen och behåller samma CSS.

<blockquote dir="rtl" lang="ar">أهلا</blockquote>

Resultat:

أهلا

Ja! 🎉

Jag kliade mig mycket i huvudet när jag började konvertera fysiska egenskaper till deras logiska motsvarigheter. Under processen gjorde jag några konverteringstabeller för framtida referens.

Konvertera till logiska egenskaper

I följande konverteringstabeller är basriktningen vänster-till-höger och uppifrån-och-ner, som vanlig engelska (eller svenska).

Padding

Så här konverteras fysiska padding-egenskaper till logiska:

Fysisk egenskapLogisk egenskap
padding-toppadding-block-start
padding-rightpadding-inline-end
padding-bottompadding-block-end
padding-leftpadding-inline-start

Shorthands

Egenskapen padding är en shorthand som låter dig sätta padding i flera riktningar i en deklaration. padding: 1rem; sätter 1rem padding i alla fyra riktningar. Eftersom samma padding sätts åt alla håll behövs ingen konvertering till logisk – den skulle ge samma resultat.

Men betrakta den här padding-deklarationen:

p {
padding: 1rem 2rem;
}

Det är en shorthand för de här deklarationerna:

p {
padding-top: 1rem;
padding-bottom: 1rem;
padding-left: 2rem;
padding-right: 2rem;
}

I logisk-egenskaps-land är det här motsvarigheten:

p {
padding-block: 1rem;
padding-inline: 2rem;
}
anteckning

I fysisk-egenskaps-land sätter man ofta padding uppåt och nedåt med shorthand padding: 1rem 0;. Men det sätter samtidigt vänster- och högerpadding till default-värdet 0 som en "biverkan". Den logiska padding-block: 1rem; är inte exakt likvärdig, eftersom vänster- och högerpadding inte sätts i det fallet.

Att sätta default-värden där det inte behövs, bara för att kunna använda shorthand-formen, kan ses som en dålig vana. Det är ett annat skäl till varför padding-block och padding-inline är bra ersättare för padding-shorthanden i många fall!

Margin

Logiska margin-egenskaper fungerar exakt som logiska padding-egenskaper. Här är konverteringstabellen:

Fysisk egenskapLogisk egenskap
margin-topmargin-block-start
margin-rightmargin-inline-end
margin-bottommargin-block-end
margin-leftmargin-inline-start

Margin-egenskapen har också shorthands som motsvarar padding-shorthanden.

Förslag på flow-relativ margin-shorthand

I framtiden får vi kanske en margin-logical som logisk shorthand-motsvarighet till den fysiska margin-shorthanden. Se diskussionen här:

https://github.com/w3c/csswg-drafts/issues/1282

Borders

Här är konverteringstabellen för border-egenskaper:

Fysisk egenskapLogisk egenskap
border-topborder-block-start
border-rightborder-inline-end
border-bottomborder-block-end
border-leftborder-inline-start

border-top-{color|style|width} kan också konverteras till border-block-start-{color|style|width}, precis som du gissar. Jag lägger inte till dem i tabellen för att inte göra den för rörig.

Shorthands

En shorthand-finess hos logiska egenskaper är att du kan sätta block- och inline-borders var för sig i en deklaration:

Fysisk deklarationLogisk deklaration
border-top: 1px solid red;
border-bottom: 1px solid red;
border-block: 1px solid red;
border-left: 1px solid red;
border-right: 1px solid red;
border-inline: 1px solid red;

Border radius

Att konvertera border-radius till logisk kräver att man tänker noga på ordningen. Formatet är border-{block-direction}-{inline-direction}-radius:

Fysisk egenskapLogisk egenskap
border-top-left-radiusborder-start-start-radius
border-top-right-radiusborder-start-end-radius
border-bottom-right-radiusborder-end-end-radius
border-bottom-left-radiusborder-end-start-radius

Storlek

Här är konverteringstabellen för storleksegenskaper:

Fysisk egenskapLogisk egenskap
heightblock-size
min-heightmin-block-size
max-heightmax-block-size
widthinline-size
min-widthmin-inline-size
max-widthmax-inline-size

Justering

Som du kanske märkt finns fysiska riktningar som left och right inte alls i logisk-egenskaps-land. Det gäller inte bara egenskapsnamn utan också värden. left kan oftast konverteras till start och right till end.

Fysisk deklarationLogisk deklaration
text-align: left;text-align: start;
text-align: right;text-align: end;
justify-content: left;justify-content: start;
justify-content: right;justify-content: end;
anteckning

Egenskapen justify-content accepterar start och end som värden, men också flex-start och flex-end. Vad är skillnaden? Främst webbläsarstöd. flex-{start|end} har bättre stöd, men start|end kommer så småningom ersätta flex-värdena.

Positionering

För positionering kommer vi jobba mycket med inset i olika former.

Fysisk egenskapLogisk egenskap
topinset-block-start
rightinset-inline-end
bottominset-block-end
leftinset-inline-start

Shorthands

Det finns några bra shorthands också!

Fysisk deklarationLogisk deklaration
top: 0;
bottom: 0;
inset-block: 0;
left: 0;
right: 0;
inset-inline: 0;
top: 0;
right: 0;
bottom: 0;
left: 0;
inset: 0;
anteckning

Det finns också en inset-shorthand som sätter offsets i alla riktningar. Den definierar dock fysiska offsets, inte logiska.

Scroll margin och scroll padding

Här är konverteringstabellen för scroll margin och scroll padding:

Fysisk egenskapLogisk egenskap
scroll-padding-topscroll-padding-block-start
scroll-padding-rightscroll-padding-inline-end
scroll-padding-bottomscroll-padding-block-end
scroll-padding-leftscroll-padding-inline-start
scroll-margin-topscroll-margin-block-start
scroll-margin-rightscroll-margin-inline-end
scroll-margin-bottomscroll-margin-block-end
scroll-margin-leftscroll-margin-inline-start

Shorthands

Här är några shorthands:

Fysisk deklarationLogisk deklaration
scroll-margin-top: 1px;
scroll-margin-bottom: 1px;
scroll-margin-block: 1px;
scroll-margin-left: 1px;
scroll-margin-right: 1px;
scroll-margin-inline: 1px;
scroll-padding-top: 1px;
scroll-padding-bottom: 1px;
scroll-padding-block: 1px;
scroll-padding-left: 1px;
scroll-padding-right: 1px;
scroll-padding-inline: 1px;

Webbläsarstöd

Webbläsarstödet för logiska egenskaper är generellt utmärkt.

Det finns dock ett par undantag.

Logiska vs fysiska egenskaper

Det kan vara frestande att göra en fullständig migrering från fysiska till logiska egenskaper, och kanske till och med lägga till en lint-regel som förbjuder fysiska egenskaper. Men fysiska egenskaper är inte deprecated på något sätt. I vissa situationer är det inte vettigt att konvertera. Här är ett exempel från CSS-specifikationen:

Dokument kan behöva både logiska och fysiska egenskaper. Till exempel måste skuggorna under knappar på en sida vara konsekventa genomgående, så deras offset väljs utifrån visuella överväganden och fysiska riktningar, och varierar inte beroende på skriftsystem.

Det är viktigt att minnas att vänster alltid är vänster. Om du säger att något är placerat på skärmens vänstra sida bör left användas snarare än inset-inline-start.

Var pragmatisk!

Logiska enheter

Vi har pratat mycket om logiska egenskaper här och lite om logiska värden. Men hur är det med enheter? Jag förklarar med ett exempel:

inline-size: 70vw;

Känns det igen? Det borde det. I deklarationen används den logiska inline-size-egenskapen, men värdet 70vw är fysiskt. Med andra ord: inline-size kan definiera horisontell eller vertikal storlek beroende på writing mode, medan 70vw alltid beräknas utifrån den horisontella storleken oberoende av writing mode. I praktiken vill vi förmodligen att värdet också ska vara flow-relativt i det här fallet.

Enheterna vb och vi kan lösa det! vb är procent av viewportens block-storlek, och vi är procent av viewportens inline-storlek. Så här kan du göra för att få ett flow-relativt värde:

inline-size: 70vi;

Här i tabellform:

Fysisk enhetLogisk enhet
vh vb
vw vi

Slutsats

  • Logiska egenskaper är fantastiska!
  • Både logiska och fysiska egenskaper kan behövas. Fundera på om något ska vara relativt till writing mode eller inte när du väljer mellan dem.
  • Tänk på webbläsarstöd innan du börjar använda logiska egenskaper.

Referenser