Julen står for døren, men det er ikke bare gaver vi pakker inn. I årevis har kanskje ditt verktøyvalg for å pakke inn elementer falt på border. Men hva om jeg fortalte deg at det finnes en mer fleksibel og layout-vennlig egenskap enn dette? Denne guiden vil utforske hvordan box-shadow kan brukes som et alternativ til tradisjonelle borders, og hvordan dette kan hjelpe oss å unngå layout-problemer.
Innpakning med border
La oss først ta en titt på den tradisjonelle måten å pakke inn elementer. Ta en titt på gaven under treet:
Her er en liten utfordring, så ikke scroll for raskt ned til løsningen. Hva tror du skjer hvis du hovrer over den?
button {
background-color: red;
color: white;
padding: 1rem;
border: 4px solid green;
}
button.border:hover {
border-width: 16px;
}
Ikke overraskende, blir selvfølgelig borderen større. Men det fører også til et layout-shift — det at border blir større, fører til at knappen blir større, og den dytter på elementene rundt. Dette er ofte en uønsket effekt. Om du har knappen i et skjema, ønsker du ikke at resten av ønskelista di skal forskyves.
Jeg skal først foreslå noen veier rundt dette, og så vil jeg foreslå en alternativ løsning med box-shadow.
Unngå layout-shift med fiksert høyde og bredde
Årsaken til layout-shift er at border
er en del av et elements faktiske størrelse. Så om et element blir større, vil det også flytte på elementer rundt.
I skjemaelementer, inkludert button, er border og padding bakt inn i et elements størrelse via CSS-deklarasjonen box-sizing: border-box. Dette gjør det enklere å styre størrelsen på et element, og er også noe vi kan bruke for å unngå layout-shift med border
.
En løsning for å unngå layout-shift er å definere en stor nok høyde og bredde til at den forstørrede grensen ikke overskrider størrelsen den allerede har:
button {
background-color: red;
color: white;
padding: 1rem;
border: 4px solid green;
width: 140px;
height: 100px;
}
button.border:hover {
border-width: 16px;
}
Om medberegnet border-width
ikke er større enn høyden og bredden som er satt, vil det ikke føre til layout-shift:
Unngå layout-shift ved å kalkulere padding
En annen løsning for å unngå layout-shift er å kalkulere padding
med hensyn til border-width
. Så når border-width
øker, vil vi også minske padding
, så knappens størrelse forblir den samme:
button {
--border-width: 4px;
background-color: red;
color: white;
padding: calc(1rem - var(--border-width));
border: var(--border-width) solid green;
}
button.border:hover {
--border-width: 16px;
}
button.with-transition {
transition: padding 0.3s ease, border 0.3s ease;
}
Resultatet ser slik ut, her en knapp med og uten transition:
Som dere ser, ser det ut til å fungere fint uten transition. Men om du ser nøye på pakken med transition, er det som om innholdet prøver å hoppe ut. Årsaken er at padding endrer størrelse på en annen rate enn border-width.
Konklusjonen er at det er mulig å kalkulere med padding
, men bare hvis du ikke skal bruke transition
— eller ønsker å lage en stilig effekt.
Bruk skyggelegging som border
Siden border har noen utfordringer ved seg, kan vi heller se til et annet verktøy. Box-shadow er en annen tilnærming for å pakke inn et element. Det oppfører seg annerledes enn en border, og har dermed flere fordeler når det kommer til endringer. Først og fremst påvirker ikke box-shadow et element sin størrelse, som fører til at vi ikke trenger å ta hensyn til å kalkulere høyde eller padding.
Å bruke box-shadow som en border kan se slik ut, hvor vi henheldsvis bruker en ytre- eller en indre skygge:
Legg merke til at når vi har en indre skygge uten interaktivitet, ligner den på en grense satt med border
. sMen den ytre skyggen legger seg utenpå elementets størrelse, som er ulikt border
. Vi kan velge om vi skal ha en ytre- eller indre grense med inset
-verdien.
box-shadow
-egenskapen lar deg styre hvor spredd skyggen er, men når vi bruker det som en grense, bryr vi oss kun om 3 verdier: om border skal være utenfor elementet, grense-bredde og fargen (henholdsvis inset, 4px og green):
button {
background-color: red;
color: white;
padding: 1rem;
border: none;
}
button.outer {
box-shadow: 0 0 0 4px green;
}
button.outer:hover {
box-shadow: 0 0 0 16px green;
}
button.inner {
box-shadow: inset 0 0 0 4px green;
}
button.inner:hover {
box-shadow: inset 0 0 0 16px green;
}
Du kan fint bruke box-shadow alene for å style en grense, men det kan også være nyttig å vite at du kan kombinere box-shadow og border.
Siden border har visse stiler som ikke følger med i box-shadow, kan det hende du vil ha en viss border-style når den er i ro, men en ytre grense ved hover:
button.combo {
border: 4px solid green;
border-style: dotted;
}
button.combo:hover {
box-shadow: inset 0 0 0 8px green;
}
button.box {
border: none;
box-shadow: inset 0 0 0 4px green;
}
button.box:hover {
box-shadow: inset 0 0 0 8px green;
}
Bør jeg alltid bruke box-shadow over border?
Både border og box-sizing har god støtte på tvers av enheter, men det kan være visse nettleserversjoner og enheter som overstyrer box-shadow. Jeg har opplevd at Safari 15 på iPhone har fjernet box-shadow, men det har blitt løst ved å ikke tillate overstyring via CSS-egenskapen appearance. Noen epost-klienter rapporterer problemer med box-shadow, så også her bør du teste om stylingresultatet ditt er som forventet.
Konklusjonen er altså at du bør starte med border. Om du også trenger dynamiske størrelser på avgrensningen, benytt box-shadow
. Du kan bruke den i kombinasjon eller alene. Men sørg for å teste om resultatet er som forventet på tvers av enheter og nettlesere.
Avsluttende ord
Jeg tror de fleste av oss har brukt border
for å sette en grense. Det fungerer godt så lenge størrelsen forblir den samme, men med en gang størrelsen er dynamisk, kan det hende du bør se til andre løsninger. Dette løser box-shadow
på en god måte, og er et verktøy du bør vurdere neste gang du skal ha en dynamisk grense.