Animeren Grens

0
10

De overgang van de grens voor een hover-state. Eenvoudig, juist? Je zou onaangenaam verrast.

De Uitdaging

De uitdaging is simpel: bouw een knop met een uitbreiding op de grens van de muisaanwijzer.

Dit artikel zal zich richten op de echte CSS trucs die gemakkelijk zou zijn om te vallen in een project, zonder contact met de DOM of gebruik van JavaScript. De methoden die hier besproken zullen deze regels te volgen

  • Enkel element (geen helper divs, maar psuedo-elementen zijn toegestaan)
  • CSS (geen JavaScript)
  • Werkt voor elke maat (niet beperkt tot een bepaalde breedte, hoogte of breedte-lengteverhouding)
  • Ondersteunt een transparante achtergrond
  • Glad en performant overgang

Ik stelde voor deze uitdaging in de Animatie op het Werk Slap en weer op . Al was er geen consensus over de beste aanpak, kreeg ik enorm slimme ideeën door een aantal fenomenale ontwikkelaars.

Methode 1: het Animeren van de grens

De meest eenvoudige manier om te animeren een grens is… nou, het animeren van een grens.

.grens-knop {
border: 5px solid #FC5185;
overgang: border-width 0.6 lineair;
}

.grens-knop:hover { border-width: 10px; }

Zie de Pen CSS schrijven-modus experimenteer door Shaw (@shshaw) op CodePen.

Leuk en simpel, maar er zijn een aantal grote problemen met de prestaties.

Sinds grens neemt de ruimte in van het document lay-out, het veranderen van de border-width zal leiden tot lay-out. In de buurt elementen niet verschuiven als gevolg van de nieuwe grens grootte, waardoor browser verplaatsen de elementen van elk frame van de animatie tenzij u hebt ingesteld dat een expliciete grootte op de knop.

Als triggering lay-out was niet slecht genoeg is, wordt de overgang zelf voelt “getrapt”. Ik zal je laten zien waarom in het volgende voorbeeld.

Methode 2: een Betere grens met overzicht

Hoe veranderen we de grens over zonder dat een lay-out? Door het gebruik van outline in plaats daarvan! U bent waarschijnlijk het meest vertrouwd met de hoofdlijnen van het te verwijderen op :focus stijlen (al moet je het niet), maar het overzicht is een buitenste lijn die niet verandert in een element van de grootte of de positie in de lay-out.

.grens-knop {
overzicht: 5px solid #FC5185;
overgang: overzicht van 0.6 lineair;
marge: 0.5 em; /* Verhoogde marge sinds de omtrek breidt buiten het element */
}

.grens-knop:hover { outline-width: 10px; }

Een snelle check in de Dev Tools’ Prestaties tabblad toont het overzicht overgang leidt niet tot lay-out. Ongeacht de beweging lijkt nog steeds stapte omdat browsers zijn afronding van de border-width en outline-width waarden, zodat je het niet sub-pixel rendering tussen de 5 en 6 of vloeiende overgangen van 5,4 tot 5,5.

Vreemd, Safari vaak niet renderen van de omtrek van de overgang en af en toe laat gek artefacten.

Methode 3: het Snijden met clip-pad

Voor het eerst geïmplementeerd door Steve Gardner, deze methode maakt gebruik van clip-pad met calc-trim de grens naar beneden, dus op beweeg kunnen we de overgang naar het onthullen van de volledige grens.

.grens-knop {
/* De volle breedte van de rand en een clip-pad visueel te snijden naar beneden naar de start formaat */
grens: 10px solid #FC5185;
clip-pad: polygoon(
calc(0% + 5px) calc(0% + 5px), /* top links */
calc(100% – 5px) calc(0% + 5px), /* rechtsboven */
calc(100% – 5px) calc(100% – 5px), /* onderaan rechts */
calc(0% + 5px) calc(100% – 5px) /* linksonder */
);
overgang: clip-pad 0.6 lineair;
}

.grens-knop:hover {
/* Clip-pad die de hele doos, zodat het niet langer verbergen van de volledige breedte van de grens. */
clip-pad: polygoon(0 0, 100% 0, 100% 100%, 0 100%);
}

clip-pad techniek is de meest soepele en meest performante methode dan zo ver, maar komt met een paar kanttekeningen. Afrondingsfouten kan leiden tot een kleine oneffenheden, afhankelijk van de exacte grootte. De grens heeft ook zijn volledige omvang van de start, waardoor de exacte positionering lastig.

Er zijn helaas geen IE/Edge-ondersteuning nog niet, maar het lijkt te zijn in ontwikkeling. U kunt en moet stimuleren van Microsoft team op te zetten om deze functies door te stemmen op maskers/clip-pad te worden toegevoegd.

Methode 4: linear-gradient achtergrond

Simuleren We een rand met behulp van een slimme combinatie van meerdere linear-gradient achtergrond het juiste formaat. In totaal hebben we vier aparte verlopen, één voor elke zijde. De background-position en achtergrond-formaat eigenschappen voor elk van de gradiënt op de juiste plek en de juiste maat, die vervolgens kan worden overgestapt naar de grens uit te breiden.

.grens-knop {
background-repeat: no-repeat;

/* background-size-waarden zal herhalen zodat we hoeven alleen maar te verklaren hen eens */
background-size:
calc(100% – 10px) 5px, /* boven en onder */
5px calc(100% – 10px); /* rechts & links */

background-position:
5px 5px, /* top */
calc(100% – 5px) 5px, /* rechts */
5px calc(100% – 5px), /* onder */
5px 5px; /* links */

/* Aangezien we de dimensionering en positionering met de bovenstaande eigenschappen, we hoeven alleen maar een eenvoudige effen opvullingen voor elke zijde */
background-image:
linear-gradient(0deg, #FC5185, #FC5185),
linear-gradient(0deg, #FC5185, #FC5185),
linear-gradient(0deg, #FC5185, #FC5185),
linear-gradient(0deg, #FC5185, #FC5185);

overgang: alle 0.6 lineair;
overgang-eigendom: achtergrond-grootte, achtergrond-positie;
}

.grens-knop:hover {
background-position: 0 0, 100% 0, 0 100%, 0 0;
background-size: 100% 10px, 10px 100%, 100% 10px, 10px 100%;
}

Deze methode is zeer moeilijk in te stellen zijn en heeft heel wat cross-browser verschillen. Firefox en Safari animeren van de faux-grens soepel, precies het effect dat we naar op zoek bent. Chrome animatie is schokkerig en nog meer stapte dan de omtrek en de grens overgangen. IE en Rand weigeren te animeren op de achtergrond, maar ze geven wel de juiste grens uitbreiding effect.

Methode 5: de Valse met box-shadow

Verborgen in box-shadow spec is een vierde waarde voor verspreiden-radius. Alle andere lengte waarden 0px en het gebruik van de spread-radius om te bouwen uw grens alternatief dat, zoals de omtrek, is niet van invloed op de indeling.

.grens-knop {
box-shadow: 0px 0px 0px 5px #FC5185;
overgang: box-shadow 0.6 lineair;
marge: 0.5 em; /* Verhoogde marge sinds de vak-hd breidt buiten het element, zoals contour */
}

.grens-knop:hover { box-shadow: 0px 0px 0px 10px #FC5185; }

De overgang met box-shadow is voldoende performant en voelt veel soepeler, behalve in Safari waar het uitlijnen van de hele-waarden tijdens de overgang als grens en overzicht.

Pseudo-Elementen

Een aantal van deze technieken kan worden aangepast voor het gebruik van een pseudo-element in plaats, maar pseudo-elementen uiteindelijk tot een aantal extra problemen met de prestaties in mijn tests.

Voor de box-shadow-methode, de overgang af en toe geactiveerd verf in een veel groter gebied dan nodig is. Reinier Kaper op gewezen dat een pseudo-element kan helpen bij het opsporen van de verf om een meer specifieke gebied. Als ik liep verder testen, box-shadow was niet meer waardoor de verf in grote delen van het document en de complicatie van de pseudo-element uiteindelijk minder performant. De verandering in de verf en prestatie kan het gevolg zijn geweest van een Chrome-update, dus voel je vrij om te testen voor jezelf.

Ik kon het ook niet vinden van een manier om gebruik te maken van de pseudo-elementen op een manier die het mogelijk maken voor transformatie gebaseerd animatie.

Waarom niet transformeren: schaal?

U kan opstoken om behulpzaam te stellen voor het gebruik van transform: schaal voor. Sinds transformatie en transparantie zijn de beste stijl eigenschappen om animatie toe te passen voor prestaties, waarom niet gebruik maken van een pseudo-element en de rand-schaal up & down?

.grens-knop {
position: relative;
marge: 0.5 em;
border: 5px solid transparant;
achtergrond: #3E4377;
}

.grens-knop:na {
inhoud: “;
display: block;
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
grens: 10px solid #FC5185;
marge: -15px;
z-index: -1;
overgang: de transformatie van 0.6 lineair;
transformeren: schaal(0.97, 0.93);
}

.grens-knop:hover::after { transform: schaal(1,1); }

Er zijn een paar problemen:

  1. De grens zal laten zien door middel van een transparante toets. Ik gedwongen een achtergrond op de knop om te laten zien hoe de grens ligt verstopt achter de knop. Als uw ontwerp oproepen voor knoppen met een volledige achtergrond, dan is dit zou kunnen werken.
  2. Je kunt niet de schaal van de grens om specifieke maten. Sinds de knop van de afmetingen variëren met de tekst, er is geen manier om het animeren van de grens van precies 5px te 10px met alleen CSS. In dit voorbeeld heb ik gedaan wat magie-getallen op de weegschaal te krijgen om te verschijnen, maar dat is niet universeel.
  3. De grens bezielt ongelijk want op de knop de aspect ratio is niet 1:1. Dit betekent meestal dat de links/rechts worden groter dan de bovenste/onderste tot de animatie is voltooid. Dit kan geen probleem zijn, afhankelijk van hoe snel uw overgang is de knop aspect ratio, en hoe groot uw grens ligt.

Als de knop is ingesteld, heeft afmetingen, Cher gewezen op een slimme manier voor het berekenen van de exacte schalen nodig is, al kan zij worden onderworpen aan bepaalde afrondingsfouten.

Dan CSS

Als we los van onze regels een beetje, er zijn veel interessante manieren kunt u een animatie van grenzen. Codrops consequent doet uitstekend werk verricht op dit gebied, meestal gebruik makend van SVGs en JavaScript. De resultaten zijn zeer bevredigend, maar ze kunnen een beetje complex om te implementeren. Hier zijn een paar de moeite waard:

  • Creatieve Knoppen
  • Knop Stijlen Inspiratie
  • Geanimeerde Selectievakjes
  • Vervormd Knop Effecten
  • Vooruitgang Knop Stijlen

Conclusie

Er is meer aan de randen dan gewoon grens, maar als u animatie wilt voorzien van een rand die u mogelijk een aantal problemen. De methoden die hier behandeld zal helpen, maar geen van hen zijn een perfecte oplossing. Wat u kiest zal afhangen van de eisen van uw project, dus ik heb legde uit een vergelijking van tabel om u te helpen beslissen.

Mijn aanbeveling zou zijn om te gebruiken box-shadow, die het best op de algehele balans van het gemak van implementatie, animatie-effect, de prestaties en de steun van de browser.

Heb je een andere manier van het creëren van een geanimeerde grens? Misschien een slimme manier om gebruik te maken van transformaties voor het verplaatsen van een grens? Reageer hieronder of mij bereiken op om uw oplossing voor de uitdaging.

Speciale dank aan Martin Pitt, Steve Gardner, Cher, Reinier Kaper, Joseph Rex, David Khourshid, en de Animatie op het Werk van de gemeenschap.