Animera Gränsen

0
12

Övergår gränsen för ett svävande tillstånd. Enkel, rätt? Du kan vara obehagligt överraskad.

Utmaningen

Utmaningen är enkel: att bygga en knapp med en växande gränsen på hover.

Denna artikel kommer att fokusera på äkta CSS-tricks som skulle vara lätt att släppa in i ett projekt utan att behöva röra DOM eller använda JavaScript. De metoder som här kommer att följa dessa regler

  • Enda element (ingen hjälpare divs, men pseudo-element som är tillåtna)
  • Enbart CSS (nr JavaScript)
  • Fungerar för varje storlek (inte bundet till en viss bredd, höjd, eller bildförhållande)
  • Stöder transparent bakgrund
  • Jämn och hög prestanda övergång

Jag föreslog denna utmaning i Animation på Jobbet Slack och om igen . Men det var ingen konsensus om att det bästa sättet, jag fick en del riktigt smarta idéer av några fenomenala utvecklare.

Metod 1: Animera gränsen

Det enklaste sättet att animera en gräns är… tja, av animera gränsen.

.border-knappen {
border: solid 5px #FC5185;
övergång: border-width 0.6 s linjär;
}

.border-knappen:hover { border-width: 10px; }

Se Pennan skriva CSS-läge experiment av Shaw (@shshaw) på CodePen.

Fina och enkla, men det finns några stora problem med prestanda.

Sedan border tar upp utrymme i dokumentets layout, byta border-width kommer att utlösa layout. I närheten delar kommer att flytta runt på grund av den nya gränsen, storlek, vilket gör webbläsaren flytta dessa delar varje bildruta i animationen om du inte anger en explicit storlek på knappen.

Som om det är påkallat av layouten var inte illa nog, övergången själv känner sig “trampade”. Jag ska visa varför i nästa exempel.

Metod 2: Bättre border beskriva med

Hur kan vi ändra på gränsen utan att utlösa en layout? Med hjälp av kontur istället! Du är förmodligen mest bekant med konturerna från att ta bort det på :fokusera stilar (men du bör inte), men konturerna är en yttre linje att inte ändra ett elements storlek eller position i layouten.

.border-knappen {
utkast: solid 5px #FC5185;
övergången skiss 0.6 s linjär;
marginalen: 0.5 em; /* Ökad marginal eftersom konturerna expanderar utanför elementet */
}

.border-knappen:hover { outline-width: 10px; }

En snabb kontroll i-Dev-Tools fliken Prestanda visar konturerna övergången inte att utlösa layout. Oavsett, den rörelse som fortfarande verkar klev eftersom webbläsare är avrundning border-width och outline-width värden så att du inte blir sub-pixel rendering mellan 5 och 6 eller mjuka övergångar från 5.4 5.5.

Konstigt, Safari ofta inte gör konturerna övergången och ibland lämnar crazy artefakter.

Metod 3: Klipp med klipp-väg

För första gången genomförs av Steve Gardner, denna metod använder clip-väg med calc för att trimma border ner så på hover vi kan övergången till att avslöja hela gränsen.

.border-knappen {
/* Full bredd gränsen och ett clip-väg visuellt skära ner det till start storlek */
border: solid 10px #FC5185;
clip-path: polygon(
calc(0% + 5px) calc(0% + 5px), /* överst till vänster */
calc(100% – 5px) calc(0% + 5px), /* upp till höger */
calc(100% – 5px) calc(100% – 5px), /* botten höger */
calc(0% + 5px) calc(100% – 5px) /* längst ned till vänster */
);
övergång: clip-väg 0.6 s linjär;
}

.border-knappen:hover {
/* Clip-väg som spänner över hela rutan så att det inte längre att dölja full bredd gränsen. */
clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
}

clip-vägen teknik är den smidigaste och mest presterande metod så långt, men inte kommit med några invändningar. Avrundningsfel kan orsaka lite ojämnheter, beroende på den exakta storleken. Gränsen har också att vara full storlek från början, vilket kan göra en exakt positionering knepigt.

Tyvärr finns det ingen IE/Edge-stöd ännu, men det verkar vara i utveckling. Du kan och bör uppmuntra Microsofts team för att genomföra dessa funktioner genom att rösta för masker/clip-väg som ska läggas till.

Metod 4: linear-gradient bakgrund

Vi kan simulera en gräns med hjälp av en smart kombination av multipel linjär gradient bakgrund av rätt storlek. Totalt har vi fyra olika gradienter, en för varje sida. Background-position och bakgrund-storlek egenskaper får var och en lutning på rätt plats och i rätt storlek, som sedan kan användas för övergått till att göra gränsen expandera.

.border-knappen {
background-repeat: no-repeat;

/* bakgrund-storlek värden kommer att upprepa så vi behöver bara deklarera dem en gång */
bakgrund-storlek:
calc(100% – 10px) 5px /* topp och botten */
5px calc(100% – 10px); /* höger & vänster */

background-position:
5px 5px /* toppen */
calc(100% – 5px) 5px / * * /
5px calc(100% – 5px), /* botten */
5px 5px; /* vänster */

/* Eftersom vi är för dimensionering och placering med ovanstående egenskaper, vi behöver bara ställa upp en enkel enfärgade gradienter för varje sida */
background-image:
linear-gradient(0deg, #FC5185, #FC5185),
linear-gradient(0deg, #FC5185, #FC5185),
linear-gradient(0deg, #FC5185, #FC5185),
linear-gradient(0deg, #FC5185, #FC5185);

övergång: alla 0.6 s linjär;
övergången fastighet: bakgrund-storlek, background-position.
}

.border-knappen:hover {
background-position: 0 0, 100% 0, 0 100%, 0 0;
bakgrund-storlek: 100% 10px, 10px 100%, 100% 10px, 10px 100%;
}

Denna metod är ganska svårt att ställa upp och har en hel del cross-browser skillnader. Firefox och Safari animera faux-gränsen smidigt, precis den effekt vi är ute efter. Chrome animation är ryckig och ännu mer klivit än konturerna och gränserna övergångar. IE och Kanten vägra att animera bakgrunden på alla, men de ger rätt border expansion effekt.

Metod 5: Fejka det med box-shadow

Gömda i box-shadow: s spec är en fjärde värdet för spridning-radie. Som alla andra längd värden till 0px och använda spridning-radie för att bygga ditt border alternativ som gillar skisser, kommer inte att påverka layouten.

.border-knappen {
box-shadow: 0px 0px 0px 5px #FC5185;
övergång: box-shadow 0.6 s linjär;
marginalen: 0.5 em; /* Ökad marginal eftersom box-shado expanderar utanför element, som disposition */
}

.border-knappen:hover { box-shadow: 0px 0px 0px 10px #FC5185; }

Övergången med box-shadow är tillräckligt hög prestanda och känns mycket mjukare, utom i Safari där det knäppa till hela värden under övergången som gränsen och kontur.

Pseudo-Element

Flera av dessa tekniker kan modifieras för att använda en pseudo-element i stället, men pseudo-element hamnade orsakar ytterligare några prestandaproblem i mina tester.

För box-shadow metod, övergången ibland utlöses färg i ett mycket större område än nödvändigt. Reinier Kaper påpekade att en pseudo-element kan hjälpa till att isolera färg till ett mer specifikt område. När jag sprang ytterligare tester, box-shadow var inte längre orsakar måla i stora delar av handlingen och den komplikation av pseudo-element slutade mindre prestanda. Förändringen i färg och prestanda kan ha varit på grund av en Chrome-uppdateringen, så känn dig fri att testa själv.

Jag kunde inte hitta ett sätt att använda pseudo-element på ett sätt som gör det möjligt att omvandla animationer.

Varför inte transform: skala?

Du kan skjuta upp till hjälpsamt föreslår att du använder transform: skala för detta. Sedan omvandla och opacitet är den bästa stilen egenskaper för att animera för prestation, varför inte använda en pseudo-element och har gränsen skala upp & ner?

.border-knappen {
position: relative;
marginalen: 0.5 em;
border: solid 5px transparent.
bakgrund: #3E4377;
}

.border-knapp:efter {
innehåll: “;
display: block;
position: absolute;
top: 0; till höger: 0; bottom: 0; left: 0;
border: solid 10px #FC5185;
marginal: -15px;
z-index: -1;
övergången till: omvandla 0.6 s linjär;
transform: skala(0.97, 0.93);
}

.border-knappen:för muspekaren::efter { transform: skala(1,1); }

Det finns ett par frågor:

  1. Gränsen kommer att visa, genom ett öppet knappen. Jag tvingade en bakgrund på knappen för att visa hur gränsen gömmer sig bakom knappen. Om din design kräver knappar med en fullständig bakgrund, då detta skulle kunna fungera.
  2. Du kan inte skala gränsen till specifika storlekar. Sedan knappen mått varierar med text, det finns inget sätt att animera gränsen från exakt 5px att 10px med bara CSS. I detta exempel har jag gjort lite magi-siffrorna på vågen för att få det att synas rätt, men det kommer inte att vara universell.
  3. Gränsen besjälar ojämnt eftersom knappen aspect ratio är inte 1:1. Detta innebär vanligtvis vänster/höger visas större än den övre/nedre tills animeringen är klar. Detta kan inte vara ett problem beroende på hur snabbt din övergång är knapp för bildförhållande, och hur stor din gräns.

Om din knappen har satt dimensioner, Cher pekade ut ett smart sätt att beräkna den exakta skalor som behövs, även om det kan vara föremål för vissa avrundningsfel.

Utöver CSS

Om vi lossa våra regler lite, det finns många intressanta sätt kan du animera gränser. Codrops konsekvent gör ett enastående arbete på detta område, vanligtvis använder SVGs och JavaScript. Resultatet är mycket tillfredsställande, även om de kan vara lite svåra att genomföra. Här är några värda att kolla in:

  • Kreativa Knappar
  • Knappen Stilar Inspiration
  • Animerade Kryssrutor
  • Förvrängd Knappen Effekter
  • Framsteg Knappen Stilar

Slutsats

Det finns mer att gränserna än att bara gränsen, men om du vill animera en gräns du kan ha vissa problem. De metoder som här kommer att hjälpa, men ingen av dem är en perfekt lösning. Vilken du väljer beror på din projektets krav, så jag har lagt ut en jämförande tabell för att hjälpa dig att avgöra.

Min rekommendation skulle vara att använda box-shadow, som har den bästa övergripande balansen av lätthet-av-genomförande, animation effekt, prestanda och webbläsare stöd.

Har du ett annat sätt att skapa en animerad gränsen? Kanske ett smart sätt att använda transformer för att flytta en gräns? Kommentera nedan eller nå mig på att dela din lösning på utmaningen.

Ett särskilt tack till Martin Pitt, Steve Gardner, Cher, Reinier Kaper, Joseph Rex, David Khourshid, och Animeringen i Arbetet gemenskapen.