Verschillende Methoden voor het Uitbreiden van een Doos met Behoud van de Border Radius

0
12

Ik heb onlangs gemerkt dat een interessante verandering op CodePen: op door de pennen op de homepage, er is een rechthoek met afgeronde hoeken uit te breiden in de rug.

Het uitbreiden van het vak effect op de CodePen homepage.

De merkwaardig schepsel dat ik ben, had ik om te zien hoe dit werkt! Blijkt, de rechthoek in de rug is een absoluut gepositioneerd ::after pseudo-element.

Eerste ::na het stijlen. Een positieve instelling gaat naar binnen van de ouders padding beperken, terwijl een negatief gaat naar buiten.

Op :hover, zijn verschuivingen worden overschreven, en gecombineerd met de overgang, krijgen we de groeiende vak effect.

De ::na het stijlen op :hover.

De woning heeft dezelfde waarde (-1rem) in zowel de eerste als de :hover regel sets, dus het is onnodig om dit te overschrijven, maar alle andere offsets verplaatsen door 2rem naar buiten (van 1rem te 1rem voor de boven-en linkerkant offsets en uit -1rem te 3rem voor de onderkant offset)

Een ding om op te merken is dat de ::after pseudo-element heeft een border-radius van 10px, dat wordt bewaard als het zich uitbreidt. Dat zette me aan het denken over wat methoden die we hebben voor het uitbreiden/krimpen (pseudo-) elementen met behoud van hun border-radius. Hoeveel kun je bedenken? Laat het me weten als je ideeën hebt die nog niet zijn opgenomen beneden, waar we een kijkje nemen op een hoop opties en zie welke het best geschikt is voor welke situatie.

Het veranderen van offsets

Dit is de methode die wordt gebruikt op CodePen en het werkt echt goed in deze specifieke situatie voor een heleboel redenen. Eerste off, het is een geweldige ondersteuning. Het werkt ook wanneer de uitbreiding van (pseudo-) element is responsief, met geen vaste afmetingen en, tegelijkertijd met het bedrag waarmee het uit is opgelost (een rem-waarde). Het werkt ook voor het uitbreiden van de in meer dan twee richtingen (boven, onder en links in dit specifieke geval).

Er zijn echter een paar valkuilen moeten we ons bewust van.

Ten eerste, onze groeiende element geen positie: statisch. Dit is niet een probleem in de context van de CodePen gebruiken geval sinds ::after pseudo-element moet worden absoluut gepositioneerd toch om te worden geplaatst onder de rest van deze ouders op de inhoud.

Ten tweede, overboord gaan met offset animaties (alsook, in het algemeen, het animeren van een pand dat van invloed is op de lay-met venster eigenschappen de manier offsets, marge, rand breedtes, stofferingen of dimensies niet) kan een negatief effect hebben op prestaties. Nogmaals, dit is niet iets van de zorg hier, we hebben alleen een beetje overgang op :hover, geen big deal.

Het wijzigen van de afmetingen

In plaats van het veranderen offsets, we kunnen veranderen afmetingen voor in de plaats. Echter, dit is een methode die werkt als we willen dat onze (pseudo-) element om uit te breiden in hooguit twee richtingen. Anders moeten we veranderen verschuift ook. Om beter te begrijpen, laten we eens kijken naar de CodePen situatie waar we willen onze ::after pseudo-elementen om uit te breiden in drie richtingen (boven, onder en links).

De relevante initiële sizing info is het volgende:

.single-item::after {
top: 1rem;
rechts: -1rem;
bodem: -1rem;
links: 1rem;
}

Sinds tegengestelde verschuivingen (de boven-onder en links-rechts paren) elkaar opheffen (1rem – 1rem = 0), het gevolg is dat de pseudo-element afmetingen zijn gelijk aan die van de ouder (of 100% van de bovenliggende dimensies).

We kunnen dus opnieuw schrijven van het bovenstaande:

.single-item::after {
top: 1rem;
rechts: -1rem;
breedte: 100%;
height: 100%;
}

Op :hover, vergroten we de breedte door 2rem aan de linker-en de hoogte 4rem, 2rem naar de top en 2rem naar de bodem. Echter, alleen het schrijven:

.single-item::after {
breedte: calc(100% + 2rem);
hoogte: calc(100% + 4rem);
}

…is niet genoeg, want dit maakt de hoogte toename van de neerwaartse richting door 4rem in plaats van het verhogen van het door 2rem tot en 2rem naar beneden. De volgende demo illustreert dit (zet :focus op of beweeg de muis over de items om te zien hoe de ::after pseudo-element vergroot):

Zie de Pen door thebabydino (@thebabydino) op CodePen.

We zouden nodig hebben om de update van de top woning zo goed in om het gewenste effect:

.single-item::after {
top: -1rem;
breedte: calc(100% + 2rem);
hoogte: calc(100% + 4rem);
}

Dat werkt, zoals hieronder te zien is:

Zie de Pen door thebabydino (@thebabydino) op CodePen.

Maar, om eerlijk te zijn, voelt dit minder wenselijk is dan het veranderen verschuift alleen.

Echter, het veranderen van de afmetingen is een goede oplossing in een ander soort situatie, zoals wanneer we willen een aantal bars met afgeronde hoeken die groter maken/kleiner maken in een enkele richting.

Zie de Pen door thebabydino (@thebabydino) op CodePen.

Merk op dat, als we niet hebben afgeronde hoeken behouden, de betere oplossing is gebruik te maken van gerichte schalen via de transform-eigenschap.

Het veranderen van padding/border-width

Vergelijkbaar met het veranderen van de afmetingen, we kunnen de padding of border-width (voor een grens die transparant is). Merk op dat, net als bij het wijzigen van de afmetingen, we moeten ook een update compenseert als het uitbreiden van het vak in meer dan twee dimensies:

Zie de Pen door thebabydino (@thebabydino) op CodePen.

In de demo hierboven, de roze vakje vertegenwoordigt de content-box van de ::after pseudo-element en je kunt zien blijft hetzelfde formaat, wat belangrijk is voor deze aanpak.

Om te begrijpen waarom het zo belangrijk is, overweeg dan deze andere beperking: we moeten ook het vak dimensies die zijn gedefinieerd door twee verschuivingen plus de breedte en de hoogte in plaats van het gebruik van alle vier de offsets. Dit is omdat de opvulling/ border-width zou groeien alleen naar binnen als we vier verschuivingen plaats twee plus de breedte en de hoogte.

Zie de Pen door thebabydino (@thebabydino) op CodePen.

Om dezelfde reden kunnen wij geen box-sizing: border-box op onze ::after pseudo-element.

Zie de Pen door thebabydino (@thebabydino) op CodePen.

Ondanks deze beperkingen, is deze methode kan handig zijn als onze uitbreiden van (pseudo -) – element tekst-inhoud we willen niet te zien bewegen op :hover zoals geïllustreerd wordt door het Pen onderaan, waar de eerste twee voorbeelden verander offsets/ afmetingen, terwijl de laatste twee wijziging stofferingen/ grens breedtes:

Zie de Pen door thebabydino (@thebabydino) op CodePen.

Het veranderen van marge

Met behulp van deze methode, hebben we eerst de verschuift naar de :hover state waarden en een marge te compenseren en geef ons de eerste staat sizing:

.single-item::after {
top: -1rem;
rechts: -1rem;
bodem: -3rem;
links: -1rem;
marge: 2rem 0 2rem 2rem;
}

Dan hebben we nul deze marge op :hover:

.single-item:hover::after { margin: 0 }

Zie de Pen door thebabydino (@thebabydino) op CodePen.

Dit is een andere aanpak die werkt geweldig voor de CodePen situatie, hoewel ik niet echt van andere use cases. Merk ook op dat, net als het veranderen van offsets of afmetingen, met deze methode is van invloed op de grootte van de content-box, dus de inhoud van de tekst, we hebben misschien wordt verplaatst en opnieuw worden gerangschikt.

Het wijzigen van de tekengrootte

Dit is waarschijnlijk de lastigste van allemaal en heeft veel beperkingen, waarvan de belangrijkste worden we niet hebben, de inhoud van de tekst op de werkelijke (pseudo-) element, dat groeit/krimpt — maar het is een andere methode die goed zou werken in de CodePen geval.

Ook de font-grootte op haar eigen niet echt alles doen om een vak uit te breiden of te verkleinen. We moeten om het te combineren met één van de eerder besproken eigenschappen.

Bijvoorbeeld, kunnen wij een set de font-size on ::na, gelijk is aan 1rem, stelt de compensatie voor de uitgebreide case en zet em marges die overeenkomt met het verschil tussen de uitgebreide en de oorspronkelijke staat.

.single-item::after {
top: -1rem;
rechts: -1rem;
bodem: -3rem;
links: -1rem;
marge: 2em 0 2em 2em;
font-size: 1rem;
}

Klik vervolgens op :hover, brengen wij de font-grootte 0:

.single-item:hover::after { font-size: 0 }

Zie de Pen door thebabydino (@thebabydino) op CodePen.

We kunnen ook gebruik maken font-size met offsets, maar het wordt een beetje ingewikkelder:

.single-item::after {
top: calc(2em – 1rem);
rechts: -1rem;
bodem: calc(2em – 3rem);
links: calc(2em – 1rem);
font-size: 1rem;
}

.single-item:hover::after { font-size: 0 }

Nog steeds, wat belangrijk is, is dat het werkt, als het kan worden hieronder te zien is:

Zie de Pen door thebabydino (@thebabydino) op CodePen.

Het combineren font-size met afmetingen is zelfs hairier, zoals we ook behoefte om de verticale offset-waarde op :beweeg met de muis op de top van alles:

.single-item::after {
top: 1rem;
rechts: -1rem;
breedte: calc(100% + 2em);
hoogte: calc(100% + 4em);
font-size: 0;
}

.single-item:hover::after {
top: -1rem;
font-size: 1rem
}

Oh, nou, in ieder geval werkt het:

Zie de Pen door thebabydino (@thebabydino) op CodePen.

Hetzelfde geldt voor het gebruik van font-size met vulling/border-width:

.single-item::after {
top: 1rem;
rechts: -1rem;
breedte: 100%;
height: 100%;
font-size: 0;
}

.single-item:nth-child(1)::after {
padding: 2em 0 2em 2em;
}

.single-item:nth-child(2)::after {
border: solid 0 transparant;
border-width: 2em 0 2em 2em;
}

.single-item:hover::after {
top: -1rem;
font-size: 1rem;
}

Zie de Pen door thebabydino (@thebabydino) op CodePen.

Het veranderen van schaal

Als je hebt gelezen stukken op animatie prestaties, dan heb je waarschijnlijk gelezen het is beter om te animeren transformeert in plaats van eigenschappen die van invloed zijn lay-out, zoals offsets, marges, randen, stofferingen, afmetingen — vrij veel wat wij tot nu toe heb gebruikt!

Het eerste probleem dat hier opvalt is dat de schalen van een element ook de schalen zijn afgeronde hoeken, zoals hieronder afgebeeld:

Zie de Pen door thebabydino (@thebabydino) op CodePen.

We kunnen dit probleem omzeilen door ook het schalen van de rand-straal de andere kant op.

Laten we zeggen dat we de schaal van een element met een factor $fx langs de x-as met factor $fy langs de y-as en we willen haar border-radius op een constante waarde $r.

Dit betekent dat we ook moeten verdelen $r door de overeenkomstige schalen factor op elke as.

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

Zie de Pen door thebabydino (@thebabydino) op CodePen.

Echter, er rekening mee dat met deze methode gebruiken we schaalfactoren, niet de bedragen die wij breiden onze (pseudo-) element in deze of die richting. Het verkrijgen van de schaalfactoren van de afmetingen en de uitbreiding bedragen is mogelijk, maar alleen als ze worden uitgedrukt in eenheden die een bepaalde vaste verhouding tussen hen. Terwijl preprocessors kan mengen eenheden, zoals in of px te wijten aan het feit dat 1in is altijd 96px, kunnen ze niet oplossen hoeveel 1em of 1% of 1vmin of 1ch is in px als zij een gebrek aan context. En calc() is niet een oplossing is, aangezien het niet toestaan ons te delen lengte waarde door een andere waarde voor de lengte van om een eenheidloze schaal factor.

Dit is de reden waarom schalen is niet een oplossing in de CodePen geval, waar de ::na dozen hebben afmetingen die afhankelijk zijn van de viewport en, tegelijkertijd, uit te breiden door middel van een vaste rem bedragen.

Maar als onze schaal bedrag wordt gegeven of kunnen we gemakkelijk berekenen, dit is een optie om te overwegen, vooral omdat het maken van de schaalfactoren aangepaste eigenschappen die we vervolgens animeren met een beetje Houdini magie sterk kunnen vereenvoudigen van onze code.

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

Merk op dat Houdini werkt alleen in Chroom browsers met de Experimentele Web-Platform functies vlag ingeschakeld.

Bijvoorbeeld, kunnen we deze tegel grid animatie:

Looping tegel grid animatie (Demo, Chroom met vlag alleen)

De vierkante tegels hebben een rand van lengte $l en met een hoek afronding van $k*$l:

.tegel {
breedte: $l;
hoogte: $l;
border-radius: calc(#{$r}/var(–fx))/ calc(#{$r}/var(–fy));
transformeren: schaal(var(–fx), var(–fy))
}

Wij registreren onze twee aangepaste eigenschappen:

CSS.registerProperty({
naam: ‘–fx’,
syntaxis: ‘<aantal>’,
initialValue: 1,
erft: false
});

CSS.registerProperty({
naam: ‘–fy’,
syntaxis: ‘<aantal>’,
initialValue: 1,
erft: false
});

En kunnen we daarna animeren ze:

.tegel {
/* hetzelfde als voorheen */
animatie: een $t oneindige gemak-in-plaatsvervanger;
animatie-naam: fx, fy;
}

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

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

Tot slot voegen we een vertraging, afhankelijk van de horizontale (–i) en verticale (–j) raster indices te maken van een gespreide animatie-effect:

animatie-vertraging:
calc((var(–i) + var(–m) – var(–j))*#{$t}/(2*var(–m)) – #{$t}),
calc((var(–i) + var(–m) – var(–j))*#{$t}/(2*var(–m)) – #{1.5*$t})

Een ander voorbeeld is de volgende, waar de stippen zijn gemaakt met behulp van pseudo-elementen:

Looping spikes animatie (Demo, Chroom met vlag alleen)

Sinds pseudo-elementen geschaald samen met hun ouders, moeten we ook omgekeerd de schalen transformatie op hen:

.spike {
/* andere spike stijlen */
transformeren: var(–positie) scalex(var(–fx));

&::voor, &::after {
/* andere pseudo-stijlen */
transformeren: scalex(calc(1/var(–fx)));
}
}

Het veranderen… clip-pad?!

Dit is een methode die ik echt leuk vind, ook al snijdt pre-Chroom Rand en Internet Explorer ondersteunen.

Vrijwel elke voorbeeld van gebruik van clip-pad heeft een veelhoek() waarde of een SVG-referentiewaarde. Echter, als je hebt gezien een aantal van mijn vorige artikelen, dan heb je waarschijnlijk weet zijn er andere vormen die we kunnen gebruiken, zoals inzet(), die werkt zoals hieronder afgebeeld:

Hoe de inzet() functie werkt. (Demo)

Dus, om te reproduceren CodePen effect met deze methode kunnen we het volgende instellen ::na verschuivingen op de uitgevouwen toestand waarden en snijd dan wat we niet willen zien, met de hulp van de clip-pad:

.single-item::after {
top: -1rem;
rechts: -1rem;
bodem: -3em;
links: -1em;
clip-pad: inzet(2rem 0 2rem 2rem)
}

En dan, in de :hover staat, we nul alle inzetstukken:

.single-item:hover::after {
clip-pad: inzet(0)
}

Dit kan worden gezien in actie hieronder:

Zie de Pen door thebabydino (@thebabydino) op CodePen.

Oke, dit werkt, maar we moeten ook een afgeronde hoeken. Gelukkig, inzet() kunnen we aangeven dat ook als wat border-radius waarde die we kunnen wensen.

Hier, een 10px een voor alle hoeken langs beide richtingen werkt het:

.single-item::after {
/* dezelfde stijlen als voorheen */
clip-pad: inzet(2rem 0 2rem 2rem ronde 10px)
}

.single-item:hover::after {
clip-pad: inzet(0 ronde 10px)
}

En dit geeft ons precies wat we van plan waren voor:

Zie de Pen door thebabydino (@thebabydino) op CodePen.

Bovendien gaat het niet echt om het even wat breken in niet-ondersteunende browsers, het is gewoon altijd blijft in uitgevouwen toestand.

Echter, terwijl deze methode is dat geweldig werkt voor veel situaties — met inbegrip van de CodePen gebruiken geval is — het werkt niet als onze uitbreiding/inkrimping elementen zijn afstammelingen, die buiten hun geknipt ouder border-box, zoals het geval is bij het laatste voorbeeld gegeven met de eerder besproken schaling methode.