Olika Metoder för att Utöka en Låda Samtidigt som Gränsen Radie

0
14

Jag har nyligen lagt märke till en intressant förändring på CodePen: svävar på pennor på hemsidan, det är en rektangel med rundade hörn och växer till i ryggen.

Expandera rutan effekt på CodePen hemsida.

Att vara nyfiken varelse som jag är, var jag tvungen att kolla hur det fungerar! Det visar sig, att rektangeln i ryggen är en absolut positionerat ::after pseudo-element.

Första ::efter stilar. En positiv offset går inåt från föräldrarnas utfyllnad gräns, medan en negativ som går utåt.

På :hover, dess förskjutningar är åsidosatt och i kombination med övergången, vi får utöka rutan effekt.

De ::efter stilar på :hover.

Rätt fastighet har samma värde (-1rem) i både den första och den :hover regeluppsättningar, så det är onödigt att åsidosätta det, men alla andra motprestationer drag av 2rem utåt (från 1rem att 1rem för den övre och vänstra förskjutningar och från -1rem att 3rem för botten offset)

En sak att notera här är att ::after pseudo-element har en border-radius av 10px som blir bevarad som den expanderar. Som fick mig att tänka på vilka metoder vi har för att utöka/krymper (pseudo-) element, samtidigt som border-radius. Hur många kan du tänka dig? Låt mig veta om du har idéer som inte har tagits med nedan, där vi tar en titt på ett gäng alternativ och se vilka som är bäst lämpade för vilken situation.

Växlande förskjutningar

Detta är den metod som används på CodePen och det fungerar riktigt bra i den här situationen för en massa skäl. Första off, det har stort stöd. Det fungerar även när den expanderande (pseudo-) element är lyhörd, med inga fasta mått och, på samma gång, det belopp med vilket det expanderar är åtgärdat ett rem-värde). Det fungerar också för att expandera i mer än två riktningar (upp, ned och vänster i det här fallet).

Det finns dock ett par varningar att vi måste vara medvetna om.

För det första, vårt växande element inte har position: statisk. Detta är inte ett problem i samband med CodePen använda eftersom ::after pseudo-element måste vara absolut positionerat i alla fall för att placeras under resten av denna förälder innehåll.

För det andra, att gå överbord med offset-animationer (samt, i allmänhet, animera någon egendom som påverkar layout med fält egenskaper som kompenserar, marginaler, gränsen bredder, stoppningar eller dimensioner göra) kan negativt påverka prestanda. Återigen, detta är inte något av intresse här, vi har bara lite övergången på :hover, ingen big deal.

Ändra mått

Istället för att ändra offset, vi kan ändra dimensioner i stället. Detta är dock en metod som fungerar om vi vill att våra (pseudo-) element för att expandera i, som mest, två riktningar. Annars måste vi ändra förskjutningar också. För att bättre förstå detta, låt oss överväga CodePen situation där vi vill att vår ::after pseudo-element för att expandera i tre riktningar (upp, ner och till vänster).

Den relevanta initiala dimensionering info är följande:

.enda-post::efter {
topp: 1rem;
rätt: -1rem;
botten: -1rem;
vänster: 1rem;
}

Sedan motsatta förskjutningar (top-bottom och left-right-par) avbryter varandra (1rem – 1rem = 0), ger det resultatet att pseudo-element mått är samma som för sin förälder (eller 100% av den överordnade dimensioner).

Så kan vi skriva om ovan:

.enda-post::efter {
topp: 1rem;
rätt: -1rem;
width: 100%;
höjd: 100%;
}

På :hover vi öka bredden av 2rem till vänster och i höjd med 4rem, 2rem till toppen och 2rem till botten. Men att bara skriva:

.enda-post::efter {
bredd: calc(100% + 2rem);
höjd: calc(100% + 4rem);
}

…är inte tillräckligt, eftersom detta gör höjden att öka den nedåtgående riktning genom 4rem istället för att öka den genom att 2rem upp och 2rem ner. Följande demo illustrerar detta (uttryckt :att fokusera på eller för muspekaren över objekten för att se hur ::after pseudo-element expanderar):

Se Pennan genom att thebabydino (@thebabydino) på CodePen.

Vi skulle behöva uppdatera den övre egendom samt för att få önskad effekt:

.enda-post::efter {
toppen: -1rem;
bredd: calc(100% + 2rem);
höjd: calc(100% + 4rem);
}

Som fungerar, som det kan ses nedan:

Se Pennan genom att thebabydino (@thebabydino) på CodePen.

Men, för att vara ärlig, det känns mindre bra, än att ändra förskjutningar ensam.

Men förändrade dimensioner är en bra lösning i en annan typ av situation, som när vi vill ha några barer med rundade hörn för att expandera eller krympa i en enda riktning.

Se Pennan genom att thebabydino (@thebabydino) på CodePen.

Observera att om vi inte har rundade hörn för att bevara den bättre lösning skulle vara att använda riktad skalning via omvandla fastigheten.

Ändra padding/margin-bredd

Liknande för att ändra dimensionerna, som vi kan ändra padding eller border-width (till en gräns som är öppet). Observera att, precis som med att ändra dimensioner, vi behöver också uppdatera motkrav om att utöka rutan i mer än två dimensioner:

Se Pennan genom att thebabydino (@thebabydino) på CodePen.

I demo ovan, rosa ruta representerar innehållet-box av ::after pseudo-element, och du kan se det förblir samma storlek, vilket är viktigt för denna strategi.

För att förstå varför det är viktigt, anser att denna begränsning: vi måste också ha rutan mått definieras av två förskjutningar plus bredden och höjden i stället för att använda alla fyra förskjutningar. Detta beror på att stoppningen/ border-width skulle bara växa inåt om vi kunde använda fyra motverkar snarare än två plus bredd och höjd.

Se Pennan genom att thebabydino (@thebabydino) på CodePen.

Av samma anledning, vi kan inte ha en box-sizing: border-box på vår ::after pseudo-element.

Se Pennan genom att thebabydino (@thebabydino) på CodePen.

Trots dessa begränsningar, är denna metod kan komma till hands om vårt växande (pseudo-) element har sms: a innehåll som vi inte vill se att flytta runt på :hover, som illustreras av Pennan nedan, där de första två exempel ändra motprestationer/ dimensioner, medan de två sista ändra stoppningar/ border bredder:

Se Pennan genom att thebabydino (@thebabydino) på CodePen.

Ändra marginal

Med hjälp av denna metod, måste vi först ställa motkrav till :hover state värderingar och en marginal för att kompensera och ge oss det ursprungliga tillståndet storlek:

.enda-post::efter {
toppen: -1rem;
rätt: -1rem;
botten: -3rem;
vänster: -1rem;
marginal: 2rem 0 2rem 2rem;
}

Då vi noll marginal på :hover:

.enda-post:hover::efter { margin: 0 }

Se Pennan genom att thebabydino (@thebabydino) på CodePen.

Detta är en annan metod som fungerar bra för CodePen situation, men jag kan inte riktigt tänka i andra fall. Observera också att, precis som att ändra offset eller dimensioner, som den här metoden påverkar storleken på innehållet-box, så all text innehåll som vi kanske får flyttas och möbleras.

Ändra teckenstorlek

Detta är förmodligen den svåraste av dem alla och har många begränsningar, av vilka de viktigaste är vi kan inte ha text på den faktiska (pseudo-) faktorer som ökar/minskar — men det är en annan metod som skulle fungera bra i CodePen fall.

Även font-size på sina egna egentligen inte göra någonting för att göra en låda expandera eller krympa. Vi måste kombinera det med en av de tidigare diskuterade egenskaper.

Vi kan till exempel ställa in font-size på ::efter att vara lika med 1rem, ställa motkrav för att den utökade fall och ställa em marginaler som skulle motsvara skillnaden mellan expanderade och det ursprungliga tillståndet.

.enda-post::efter {
toppen: -1rem;
rätt: -1rem;
botten: -3rem;
vänster: -1rem;
margin: 2em 0 2em 2em;
font-size: 1rem;
}

Klicka sedan på :hover, vi tar font-size till 0:

.enda-post:hover::efter { font-size: 0 }

Se Pennan genom att thebabydino (@thebabydino) på CodePen.

Vi kan också använda font-size med förskjutningar, även om det blir lite mer komplicerat:

.enda-post::efter {
topp: calc(2em – 1rem);
rätt: -1rem;
botten: calc(2em – 3rem);
vänster: calc(2em – 1rem);
font-size: 1rem;
}

.enda-post:hover::efter { font-size: 0 }

Fortfarande, vad som är viktigt är att det fungerar, som det kan ses nedan:

Se Pennan genom att thebabydino (@thebabydino) på CodePen.

Kombinera font-size med dimensioner är ännu hairier, som vi också behov av att ändra den vertikala förskjutningen värdet på :hover på toppen av allt:

.enda-post::efter {
topp: 1rem;
rätt: -1rem;
bredd: calc(100% + 2em);
höjd: calc(100% + 4em);
font-size: 0;
}

.enda-post:hover::efter {
toppen: -1rem;
font-size: 1rem
}

Åh, ja åtminstone fungerar det:

Se Pennan genom att thebabydino (@thebabydino) på CodePen.

Samma sak är det med hjälp av font-size med stoppning/border-width:

.enda-post::efter {
topp: 1rem;
rätt: -1rem;
width: 100%;
höjd: 100%;
font-size: 0;
}

.enda-post:nth-child(1)::efter {
stoppning: 2em 0 2em 2em;
}

.enda-post:nth-child(2)::efter {
border: solid 0 transparent.
border-width: 2em 0 2em 2em;
}

.enda-post:hover::efter {
toppen: -1rem;
font-size: 1rem;
}

Se Pennan genom att thebabydino (@thebabydino) på CodePen.

Ändra skala

Om du har läst bitar på animation prestanda, så har du förmodligen läst att det är bättre att animera förvandlar stället för egenskaper som påverkar layouten, som motkrav, marginaler, gränser, stoppningar, mått — ganska mycket vad vi har använt hittills!

Den första frågan som sticker ut här är att skalning en del också skalor sitt hörn av avrundning enligt nedan:

Se Pennan genom att thebabydino (@thebabydino) på CodePen.

Vi kan komma runt detta genom att också skalning border-radius på andra sätt.

Låt oss säga att vi skala av en del av en faktor $fx längs x-axeln och med en faktor $fy längs y-axeln och vi vill behålla sitt border-radius på ett konstant värde $r.

Det betyder också att vi måste dela upp $r av motsvarande skalfaktor längs varje axel.

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

Se Pennan genom att thebabydino (@thebabydino) på CodePen.

Observera dock att med denna metod, måste vi använda skalning faktorer, inte mängder av, som vi kan öka vår (pseudo-) element i den ena eller andra riktningen. Få skalning faktorer från de dimensioner och expansion belopp är möjligt, men bara om de är uttryckt i enheter som har en viss relation mellan dem. Medan förbehandling kan blanda enheter som i eller px på grund av det faktum att 1i är alltid 96px, de kan inte lösa hur mycket 1em eller 1% eller 1vmin eller 1ch är i px som de saknar sammanhang. Och calc() är inte heller någon lösning, eftersom det tillåter oss inte att dela en längd värdet av en annan längd värde för att få en unitless skala faktor.

Det är därför skalning är inte en lösning i CodePen fall, där ::efter boxar har måtten som beror på visningsområdet, och samtidigt expandera genom att fasta rem belopp.

Men om vår skala belopp eller att vi enkelt kan beräkna det, detta är ett alternativ att överväga, särskilt eftersom att skala faktorer anpassade egenskaper som vi sedan animera med en bit av Houdini magi kan förenkla vår kod.

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

Observera att Houdini fungerar bara i Krom webbläsare med Experimentell Plattform för Webben har flaggan aktiverad.

Vi kan till exempel skapa denna platta rutnät animation:

Looping kakel nätet animation (Demo, Chrome med flaggan bara)

Den kvadratiska plattor har en kant längd $l och med en avrundning av hörn $k*$l:

.kakel {
bredd: $l.
höjd: $l.
border-radius: calc(#{$r}/var(–fx))/ calc(#{$r}/var(–fy));
transform: skala(var(–fx), var(–fy))
}

Vi registrerar våra två egna egenskaper:

CSS.registerProperty({
namn: ‘–fx’,
syntax: ‘<nummer>’,
initialValue: 1,
ärver: falskt
});

CSS.registerProperty({
namn: ‘–fy’,
syntax: ‘<nummer>’,
initialValue: 1,
ärver: falskt
});

Och vi kan sedan animera dem:

.kakel {
/* samma som innan */
animation: a $t oändliga lätthet-i alternativ;
animation-namn: fx, fy;
}

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

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

Slutligen, vi lägger in en fördröjning beroende på den horisontella (- jag) och vertikala (–j) grid index för att skapa ett utspritt animation effekt:

animation-fördröjning:
calc((var (- jag) + var(–m) – var(–j))*#{$t}/(2*var(–m)) – #{$t}),
calc((var (- jag) + var(–m) – var(–j))*#{$t}/(2*var(–m)) – #{1.5*$t})

Ett annat exempel är följande, där punkterna är skapade med hjälp av pseudo-element:

Looping spikar animation (Demo, Chrome med flaggan bara)

Eftersom pseudo-element skalas tillsammans med sina föräldrar, måste vi också vända skalning omvandla dem:

.spike {
/* andra spik stilar */
förändra: var(–position) scalex(var(–fx));

&::före, &::efter {
/* andra pseudo stilar */
förändra: scalex(calc(1/var(–fx)));
}
}

Ändra… clip-väg?!

Detta är en metod som jag verkligen gillar, trots att det skär in pre-Krom Kant och Internet Explorer stöd.

Ganska mycket varje användning exempel på clip-vägen ut har det antingen en polygon () – värde eller en SVG-referensvärdet. Dock, om du har sett några av mina tidigare artiklar, så har du förmodligen vet att det finns andra grundläggande former som vi kan använda, som infälld(), som fungerar som illustreras nedan:

Hur infälld () – funktionen fungerar. (Demo)

Så, för att återge de CodePen effekt med denna metod, som vi ::efter kompenserar för att den utökade statliga värden och skär sedan ut det vi inte vill se med hjälp av klipp-väg:

.enda-post::efter {
toppen: -1rem;
rätt: -1rem;
botten: -3em;
vänster: -1em;
clip-bana: infälld(2rem 0 2rem 2rem)
}

Och sedan, i :hover state, vi noll alla inläggningar:

.enda-post:hover::efter {
clip-bana: infälld(0)
}

Detta kan ses i aktion nedan:

Se Pennan genom att thebabydino (@thebabydino) på CodePen.

Okej, detta fungerar, men vi behöver också ett hörn av avrundning. Lyckligtvis, infälld() låter oss ange det också som att allt border-radius värde som vi kanske vill.

Här, en 10px en för alla hörnen längs båda riktningarna gör det:

.enda-post::efter {
/* samma stil som innan */
clip-bana: infälld(2rem 0 2rem 2rem runda 10px)
}

.enda-post:hover::efter {
clip-bana: infälld(0 omgången 10px)
}

Och detta ger oss precis vad vi går för:

Se Pennan genom att thebabydino (@thebabydino) på CodePen.

Dessutom är det egentligen inte bryta något i icke-bärande webbläsare, det är bara stannar alltid i expanderat tillstånd.

Men även om detta är en metod som fungerar bra för en hel del situationer — bland annat CodePen använder fall — det fungerar inte när vår expanderande/krympande delar har ättlingar som går utanför deras klippt förälder border-box, som det är fallet för den förra exemplet med den tidigare diskuterade scaling-metoden.