Ulike Metoder for å Utvide en Boks og Samtidig Bevare Border-Radius

0
15

Jeg har nylig lagt merke til en interessant endring på CodePen: på svever penner på hjemmesiden, det er et rektangel med avrundede hjørner for å utvide i ryggen.

Utvide boksen effekt på CodePen hjemmeside.

Å være nysgjerrig skapning som jeg er, måtte jeg sjekke hvordan dette fungerer! Slår ut, rektangel på baksiden er en absolutt posisjonert ::etter pseudo-element.

Innledende ::etter stiler. En positiv offset går innover fra foreldrenes polstring grense, mens det negative går utover.

På :hover, sine kvoter overkjøres og, kombinert med overgangen, vi får utvide boksen effekt.

Av ::etter stiler på :hover.

Den rette eiendommen har samme verdi (-1rem) i både den første og den :hover regelsett, så det er unødvendig å overstyre det, men alle de andre er valgt, forskyves trekk ved 2rem utover (fra 1rem til-1rem for toppen og venstre kvoter og fra -1rem til-3rem for den nederste offset)

En ting å legge merke til her er at ::etter pseudo-element har en border-radius av 10px som blir bevart som det utvider seg. Som fikk meg til å tenke på hvilke metoder vi har for å utvide/krympe (pseudo-) elementer og samtidig bevare sin border-radius. Hvor mange kan du tenke på? La meg vet hvis du har ideer som ikke har blitt inkludert nedenfor, hvor vi tar en titt på en haug med alternativer og se hvilke som er best egnet for hva situasjonen.

Endre kvoter

Dette er den metoden som brukes på CodePen og det fungerer veldig bra i denne spesielle situasjonen for en haug av årsaker. First off, det har stor støtte. Det fungerer også når den voksende (pseudo-) element er responsiv, med noen faste mål, og på samme tid, det beløp som den utvider er fast (en rem-verdi). Det fungerer også for å utvide i mer enn to retninger (topp, bunn og venstre i dette tilfellet).

Det er imidlertid et par begrensninger vi må være klar over.

Først vår voksende element ikke har posisjon: statisk. Dette er ikke et problem i sammenheng med CodePen bruk tilfellet siden ::etter pseudo-element må være absolutt posisjonert likevel for å være plassert under resten av denne forelderens innhold.

For det andre, å gå over med offset-animasjoner (så vel som, generelt, animere noen eiendom som påvirker layout med boksen egenskaper måten forskyvninger, marginer, border bredde, polstring eller dimensjoner gjøre) kan ha negativ innvirkning på ytelsen. Igjen, dette er ikke noe av interesse her, vi har bare en liten overgang på :hover, ingen big deal.

Endre dimensjoner

I stedet for å endre kvoter, kan vi forandre dimensjoner i stedet. Dette er imidlertid en metode som fungerer hvis vi ønsker at våre (pseudo-) element for å utvide i, på de fleste, to retningene. Ellers må vi endre kvoter som godt. For å bedre forstå dette, la oss vurdere CodePen situasjon der vi vil ha våre ::etter pseudo-elementer til å utvide seg i tre retninger (topp, bunn og venstre).

Relevante første dimensjonering info er følgende:

.single-element::etter {
øverst: 1rem;
høyre: -1rem;
bunnen: -1rem;
venstre: 1rem;
}

Siden motstridende kvoter (topp-bunn og venstre-høyre-par) avbryter hverandre (1rem – 1rem = 0), er det resultatene som pseudo-element mål er lik de av sine foreldre (eller 100% av den overordnede dimensjoner).

Så kan vi skrive om de ovennevnte som:

.single-element::etter {
øverst: 1rem;
høyre: -1rem;
bredde: 100%;
høyde: 100%;
}

På :hover, øker vi bredden av 2rem til venstre og høyden av 4rem, 2rem til toppen og 2rem til bunnen. Men, bare å skrive:

.single-element::etter {
bredde: calc(100% + 2rem);
høyde: calc(100% + 4rem);
}

…er ikke nok, da dette gjør høyde øke den nedadgående retning av 4rem i stedet for å øke den ved 2rem opp og 2rem ned. Følgende demo illustrerer dette (sett :fokus på, eller hold musepekeren over elementer for å se hvordan ::etter pseudo-element utvider seg):

Se Pennen av thebabydino (@thebabydino) på CodePen.

Vi hadde behov for å oppdatere de beste eiendommen samt for å få ønsket effekt:

.single-element::etter {
øverst: -1rem;
bredde: calc(100% + 2rem);
høyde: calc(100% + 4rem);
}

Som fungerer, som det kan sees nedenfor:

Se Pennen av thebabydino (@thebabydino) på CodePen.

Men, for å være ærlig, dette føles mindre ønskelig enn å endre kvoter alene.

Imidlertid endre mål er en god løsning i en annen type situasjon, som når vi ønsker å ha noen barer med avrundede hjørner utvide/krympe i samme retning.

Se Pennen av thebabydino (@thebabydino) på CodePen.

Vær oppmerksom på at, hvis vi ikke har avrundede hjørner for å bevare, jo bedre løsning ville være å bruke retningsbestemt skalering via forvandle eiendommen.

Endre polstring/border-width

Lignende for å endre dimensjonene, kan vi endre polstring eller border-width (for en ramme som er gjennomsiktige). Vær oppmerksom på at akkurat som med å endre mål, må vi også oppdatere kvoter hvis utvide boksen i mer enn to dimensjoner:

Se Pennen av thebabydino (@thebabydino) på CodePen.

I demoen ovenfor, den rosa boksen representerer innhold-boksen av ::etter pseudo-element, og du kan se det forblir de samme størrelse, noe som er viktig for denne tilnærmingen.

For å forstå hvorfor det er viktig, bør du vurdere denne annen begrensning: vi trenger også å ha boksen mål definert av to kvoter pluss bredden og høyden i stedet for å bruke alle fire kvoter. Dette er fordi polstring/ border-width ville bare vokser innover hvis vi skulle bruke fire av kvoter i stedet for at to pluss bredden og høyden.

Se Pennen av thebabydino (@thebabydino) på CodePen.

Av samme grunn kan vi ikke ha box-dimensjonering: border-box på våre ::etter pseudo-element.

Se Pennen av thebabydino (@thebabydino) på CodePen.

På tross av disse begrensningene, er denne metoden kan komme godt med hvis vår voksende (pseudo-) element har tekst-innhold, ønsker vi ikke å se flytte rundt på :hover illustrert med Penn under, der de to første eksemplene endre kvoter/ dimensjoner, mens de to siste endre polstring/ grensen bredder:

Se Pennen av thebabydino (@thebabydino) på CodePen.

Endre margin

Ved hjelp av denne metoden, må vi først sette kvoter til :hover statens verdier og en margin for å kompensere og gir oss den første staten dimensjonering:

.single-element::etter {
øverst: -1rem;
høyre: -1rem;
bunnen: -3rem;
venstre: -1rem;
margin: 2rem 0 2rem 2rem;
}

Da vi null denne margin på :hover:

.single-element:hover::etter { margin: 0 }

Se Pennen av thebabydino (@thebabydino) på CodePen.

Dette er en annen tilnærming som fungerer bra for CodePen situasjon, selv om jeg kan egentlig ikke tenke på andre bruksmåter. Merk også at, akkurat som å endre kvoter eller dimensjoner, denne metoden påvirker størrelsen av innhold-boksen, slik at enhver tekst-innhold, kan det hende vi må flyttes og omorganisert.

Endre skriftstørrelse

Dette er trolig den vanskeligste en for alle og har mange begrensninger, er det viktigste som blir vi ikke har tekst-innhold, på den faktiske (pseudo-) element som utvider/krymper — men det er en annen metode som ville fungere godt i CodePen tilfelle.

Også, font-size-på sin egen egentlig ikke gjør noe for å gjøre en boks utvide seg eller krympe. Vi trenger å kombinere det med en av de tidligere diskutert egenskaper.

Vi kan For eksempel angi skrift-størrelse på ::etter å bli lik 1rem, sette av kvoter til utvidet saken og satt em marginer som ville tilsvare forskjellen mellom utvidet og den opprinnelige tilstand.

.single-element::etter {
øverst: -1rem;
høyre: -1rem;
bunnen: -3rem;
venstre: -1rem;
margin: 2em 0 2em 2em;
font-size: 1rem;
}

Deretter, på :hover, bringer vi font-size til 0:

.single-element:hover::etter en { font-size: 0 }

Se Pennen av thebabydino (@thebabydino) på CodePen.

Vi kan også bruke font-size-med klimakvoter, selv om det blir litt mer komplisert:

.single-element::etter {
øverst: calc(2em – 1rem);
høyre: -1rem;
nederst: calc(2em – 3rem);
venstre: calc(2em – 1rem);
font-size: 1rem;
}

.single-element:hover::etter en { font-size: 0 }

Likevel, hva er viktig er at det fungerer, slik det kan sees nedenfor:

Se Pennen av thebabydino (@thebabydino) på CodePen.

Ved å kombinere skrift-størrelse med dimensjoner er selv risikabelt, som vi også trenger å endre den vertikale forskyvningen verdien på :hold på toppen av alt:

.single-element::etter {
øverst: 1rem;
høyre: -1rem;
bredde: calc(100% + 2em);
høyde: calc(100% + 4em);
font-size: 0;
}

.single-element:hover::etter {
øverst: -1rem;
font-size: 1rem
}

Å, vel, i hvert fall virker det:

Se Pennen av thebabydino (@thebabydino) på CodePen.

Samme gjelder for bruk av font-size-med polstring/border-width:

.single-element::etter {
øverst: 1rem;
høyre: -1rem;
bredde: 100%;
høyde: 100%;
font-size: 0;
}

.single-element:nth-child(1)::etter {
polstring: 2em 0 2em 2em;
}

.single-element:nth-child(2)::etter {
border: solid 0 transparent;
border-width: 2em 0 2em 2em;
}

.single-element:hover::etter {
øverst: -1rem;
font-size: 1rem;
}

Se Pennen av thebabydino (@thebabydino) på CodePen.

Endre målestokk

Hvis du har lest stykker på animasjon ytelse, så du har sikkert lest at det er bedre å animere forvandler i stedet for egenskaper som påvirker layout, som forskyvninger, marginer, grenser, polstring, mål — ganske mye hva vi har brukt så langt!

Det første problemet som skiller seg ut her er at skalering et element også skalaer hjørnet, avrunding, som illustrert under:

Se Pennen av thebabydino (@thebabydino) på CodePen.

Vi kan komme rundt dette ved også å skalere border-radius på annen måte.

La oss si at vi skalerer et element med en faktor $fx langs x-aksen og med en faktor $fy langs y-aksen, og vi ønsker å holde sin border-radius på en konstant verdi $r.

Dette betyr at vi også må dele $r av tilsvarende skaleringsfaktor langs hver akse.

border-radius: #{$r/$fx}/ #{$r/$fy};
forvandle: skala($fx, $fy)

Se Pennen av thebabydino (@thebabydino) på CodePen.

Imidlertid, vær oppmerksom på at med denne metoden, må vi bruke skalering faktorer, ikke beløp som vi utvider vår (pseudo-) element i denne eller i den retningen. Å få skaleringsfaktorer fra mål og utvidelse beløp er mulig, men bare hvis de er uttrykt i enheter som har en viss fast forhold mellom dem. Mens preprocessors kan blande enheter som i eller px på grunn av det faktum at 1i er alltid 96px, som de ikke kan løse hvor mye 1em eller 1% eller 1vmin eller 1ch er i px som de mangler kontekst. Og calc – () er ikke en løsning, da den ikke tillater oss å dele en lengde verdi av en annen lengde verdi å få en unitless skala faktor.

Dette er grunnen til skalering er ikke en løsning i CodePen tilfelle, hvor ::etter boksene har dimensjoner som er avhengige av viewport og, på samme tid, kan du utvide ved fast rem beløp.

Men hvis vår skala beløpet er gitt, eller kan vi lett beregne det, dette er et alternativ å vurdere, spesielt siden gjør skaleringsfaktorer egendefinerte egenskaper vi animer med en bit av Houdini magic kan i stor grad forenkle vår kode.

border-radius: calc(#{$r}/var(–fx))/ calc(#{$r}/var(–fy));
forvandle: skala(var(–fx), var(–fy))

Vær oppmerksom på at Houdini fungerer bare i Krom nettlesere med den Eksperimentelle Web-Plattformen har flagget er aktivert.

Vi kan For eksempel lage denne flis rutenett animasjon:

Looping flis rutenett animasjon (Demo, Krom med flagg bare)

Den kvadratiske fliser har en kant lengde $l og med et hjørne avrunding av $k*$l:

.flis {
bredde: $l;
høyde: $l;
border-radius: calc(#{$r}/var(–fx))/ calc(#{$r}/var(–fy));
forvandle: skala(var(–fx), var(–fy))
}

Vi registrerer våre to egendefinerte egenskaper:

CSS.registerProperty({
name: ‘–fx’,
syntaks: ‘<tall>’,
initialValue: 1,
arver: false
});

CSS.registerProperty({
name: ‘–fy’,
syntaks: ‘<tall>’,
initialValue: 1,
arver: false
});

Og så kan vi animere dem:

.flis {
/* samme som før */
animasjon: a $t uendelig letthet-i alternativ;
animasjon-navn: fx, fy;
}

@keyframes fx {
0%, 35% { –fx: 1 }
50%, 100% { –fx: #{2*$k} }
}

@keyframes fy {
0%, 35% { –fy: 1 }
50%, 100% { –fy: #{2*$k} }
}

Til slutt, vil vi legge til en forsinkelse avhengig av den horisontale (–jeg) og vertikale (–j) grid-indekser for å skape en forskjøvet animasjon effekt:

animasjon-forsinkelse:
calc((var(–jeg) + var(–m) – var(–j))*#{$t}/(2*var(–m)) – #{$t}),
calc((var(–jeg) + var(–m) – var(–j))*#{$t}/(2*var(–m)) – #{1.5*$t})

Et annet eksempel er den følgende, hvor punktene er opprettet ved hjelp av pseudo-elementer:

Looping pigger animasjon (Demo, Krom med flagg bare)

Siden pseudo-elementer blir skalert sammen med sine foreldre, må vi også reversere skalering forandre på dem:

.spike {
/* andre spike stiler */
forvandle: var(–stilling) scalex(var(–fx));

&::før, &::etter {
/* andre pseudo stiler */
forvandle: scalex(calc(1/var(–fx)));
}
}

Endring… clip-banen?!

Dette er en metode jeg liker, selv om det skjærer ut pre-Krom Kanten og Internet Explorer støtte.

Ganske mye hver eneste eksempel på bruk av klipp-banen der ute har enten et polygon() verdi eller en SVG-referanse verdi. Imidlertid, hvis du har sett noen av mine tidligere artikler, så har du sannsynligvis vet det er andre grunnleggende former vi kan bruke, som inset(), som fungerer som illustrert under:

Hvordan inset () – funksjonen fungerer. (Demo)

Så, for å gjenskape CodePen effekt med denne metoden, har vi satt ::etter kvoter til utvidet staten verdier, og deretter klippe ut hva vi ikke ønsker å se ved hjelp av klipp-banen:

.single-element::etter {
øverst: -1rem;
høyre: -1rem;
bunnen: -3em;
venstre: -1em;
klipp-bane: inset(2rem 0 2rem 2rem)
}

Og så, i :hover staten, vi null alle innfellinger:

.single-element:hover::etter {
klipp-bane: inset(0)
}

Dette kan sees i aksjon under:

Se Pennen av thebabydino (@thebabydino) på CodePen.

Ok, dette fungerer, men vi trenger også et hjørne avrunding. Heldigvis, inset() gir oss muligheten til å angi det også som uansett border-radius-verdien vi kan ønske.

Her, en 10px en for alle hjørnene langs begge retninger gjør du det:

.single-element::etter {
/* samme stiler som før */
klipp-bane: inset(2rem 0 2rem 2rem runde 10px)
}

.single-element:hover::etter {
klipp-bane: inset(0 runde 10px)
}

Og dette gir oss akkurat det vi skulle til:

Se Pennen av thebabydino (@thebabydino) på CodePen.

Videre, det betyr egentlig ikke ødelegge noe i ikke-støtter nettlesere, er det bare alltid forblir i den utvidede staten.

Imidlertid, selv om dette er en metode som fungerer bra for mange situasjoner — inkludert CodePen use case — det virker ikke når våre utvide/krympe elementer har etterkommere som går utenfor sitt avkuttede forelder, border-box, som det er tilfelle for den siste eksemplet med den tidligere diskutert skalering metode.