Animerade bakgrundsränder som övergår på Hover PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Animerade bakgrundsränder som övergår när du svävar

Hur ofta sträcker du dig efter CSS background-size fast egendom? Om du är som jag – och förmodligen många andra frontend-människor – så är det oftast när du background-size: cover en bild för att fylla utrymmet för ett helt element.

Tja, jag fick en intressant utmaning som krävde mer avancerad bakgrundsstorlek: bakgrundsränder som övergår när man svävar. Kolla in det här och håll det med muspekaren:

Det händer mycket mer där än storleken på bakgrunden, men det var tricket jag behövde för att få ränderna att övergå. Jag tänkte visa dig hur jag kom dit, inte bara för att jag tycker att det är en riktigt snygg visuell effekt, utan för att det krävde att jag blev kreativ med gradienter och blandningslägen som jag tror att du skulle kunna uppskatta.

Låt oss börja med en mycket grundläggande inställning för att göra det enkelt. Jag pratar om en singel

i HTML-koden som är utformad som en grön fyrkant:

div {
  width: 500px;
  height: 500px;
  background: palegreen;
}
Animerade bakgrundsränder som övergår när du svävar

Sätta upp bakgrundsränderna

Om ditt sinne gick direkt till en linjär CSS-gradient när du såg dessa ränder, då är vi redan på samma sida. Vi kan inte exakt göra en upprepad gradient i det här fallet eftersom vi vill att ränderna ska uppta ojämna mängder utrymme och flytta över dem, men vi kan skapa fem ränder genom att kedja fem bakgrunder ovanpå vår befintliga bakgrundsfärg och placera dem överst - höger om behållaren:

div {
  width: 500px;
  height: 500px;
  background: 
    linear-gradient(black, black) top right,
    linear-gradient(black, black) top 100px right,
    linear-gradient(black, black) top 200px right,
    linear-gradient(black, black) top 300px right,
    linear-gradient(black, black) top 400px right, 
    palegreen;
}

Jag gjorde horisontella ränder, men vi kunde också gå vertikalt med det tillvägagångssätt som vi tar upp här. Och vi kan förenkla detta ganska mycket med anpassade egenskaper:

div {
  --gt: linear-gradient(black, black);
  --n: 100px;

  width: 500px;
  height: 500px;
  background: 
    var(--gt) top right,
    var(--gt) top var(--n) right,
    var(--gt) top calc(var(--n) * 2) right,
    var(--gt) top calc(var(--n) * 3) right,
    var(--gt) top calc(var(--n) * 4) right, 
    palegreen;
}

Så, den --gt värde är gradienten och --n är en konstant som vi använder för att knuffa ränderna nedåt så att de förskjuts vertikalt. Och du kanske har märkt att jag inte har angett en riktig gradient, utan snarare solida svarta ränder i linear-gradient() funktion — det är avsiktligt och vi kommer till varför jag gjorde det om en stund.

En sak till som vi borde göra innan vi går vidare är att förhindra att vår bakgrund upprepas; annars lägger de till och fyller hela utrymmet:

div {
  --gt: linear-gradient(black, black);
  --n: 100px;

  width: 500px;
  height: 500px;
  background: 
    var(--gt) top right,
    var(--gt) top var(--n) right,
    var(--gt) top calc(var(--n) * 2) right,
    var(--gt) top calc(var(--n) * 3) right,
    var(--gt) top calc(var(--n) * 4) right, 
    palegreen;
  background-repeat: no-repeat;
}

Vi kunde ha satt background-repeat i background stenografi, men jag bestämde mig för att dela ut det här för att göra saker lättlästa.

Förskjutning av ränderna

Vi har tekniskt sett ränder, men det är ganska svårt att säga eftersom det inte finns något mellanrum mellan dem och de täcker hela behållaren. Det är mer som att vi har en hel svart fyrkant.

Det är här vi får använda background-size fast egendom. Vi vill ställa in både höjden och bredden på ränderna och egenskapen stöder en syntax med två värden som gör att vi kan göra exakt det. Och vi kan kedja dessa storlekar genom att kommaseparera dem på samma sätt som vi gjorde på background.

Låt oss börja enkelt med att ställa in bredderna först. Att använda envärdessyntaxen för background-size ställer in bredden och ställer in höjden som standard auto. Jag använder helt godtyckliga värden här, så ställ in värdena på det som fungerar bäst för din design:

div {
  --gt: linear-gradient(black, black);
  --n: 100px;

  width: 500px;
  height: 500px;
  background: 
    var(--gt) top right,
    var(--gt) top var(--n) right,
    var(--gt) top calc(var(--n) * 2) right,
    var(--gt) top calc(var(--n) * 3) right,
    var(--gt) top calc(var(--n) * 4) right, 
    palegreen;
  background-repeat: no-repeat;
  background-size: 60%, 90%, 70%, 40%, 10%;
}

Om du använder samma värden som jag får du detta:

Det ser inte precis ut som att vi ställer in bredden för alla ränder, eller hur? Det är på grund av auto höjdbeteende för enkelvärdessyntaxen. Den andra randen är bredare än de andra under den, och den täcker dem. Vi borde ställa in höjderna så att vi kan se vårt arbete. De ska alla ha samma höjd och vi kan faktiskt återanvända våra --n variabel, återigen, för att göra saker enkelt:

div {
  --gt: linear-gradient(black, black);
  --n: 100px;

  width: 500px;
  height: 500px;
  background: 
    var(--gt) top right,
    var(--gt) top var(--n) right,
    var(--gt) top calc(var(--n) * 2) right,
    var(--gt) top calc(var(--n) * 3) right,
    var(--gt) top calc(var(--n) * 4) right, 
    palegreen;
    background-repeat: no-repeat;
    background-size: 60% var(--n), 90% var(--n), 70% var(--n), 40% var(--n), 10% var(--n); // HIGHLIGHT 15
}

Ah, mycket bättre!

Lägga till mellanrum mellan ränderna

Detta är ett helt valfritt steg om din design inte kräver mellanrum mellan ränderna, men min gjorde det och det är inte alltför komplicerat. Vi ändrar höjden på varje ränder background-size en smula, vilket minskar värdet så att de inte fyller hela det vertikala utrymmet.

Vi kan fortsätta använda vår --n variabel, men subtrahera en liten mängd, säg 5px, Med användning av calc() för att få det vi vill ha.

background-size: 60% calc(var(--n) - 5px), 90% calc(var(--n) - 5px), 70% calc(var(--n) - 5px), 40% calc(var(--n) - 5px), 10% calc(var(--n) - 5px);

Det är många upprepningar vi kan eliminera med en annan variabel:

div {
  --h: calc(var(--n) - 5px);
  /* etc. */
  background-size: 60% var(--h), 90% var(--h), 70% var(--h), 40% var(--h), 10% var(--h);
}

Maskering och blandning

Låt oss nu byta palegreen bakgrundsfärg som vi har använt för visuella ändamål fram till denna punkt för vit.

div {
  /* etc. */
  background: 
    var(--gt) top right,
    var(--gt) top var(--n) right,
    var(--gt) top calc(var(--n) * 2) right,
    var(--gt) top calc(var(--n) * 3) right,
    var(--gt) top calc(var(--n) * 4) right, 
    #fff;
  /* etc. */
}

Ett svartvitt mönster som detta är perfekt för maskering och blandning. För att göra det ska vi först slå in vår

i en ny föräldrabehållare och introducera en andra

under den:

Vi kommer att göra en liten CSS-omfaktor här. Nu när vi har en ny föräldrabehållare kan vi klara det fasta width och height egenskaper vi använde på våra

där borta:

section {
  width: 500px;
  height: 500px;
} 

Jag kommer också att använda CSS Grid för att placera de två

element ovanpå varandra. Det här är samma knep som Temani Afif använder för att skapa sitt superhäftiga bildgallerier. Tanken är att vi placerar båda diverna över hela behållaren med hjälp av grid-area egendom och rikta allt mot mitten:

section {
  display: grid;
  align-items: center;
  justify-items: center;
  width: 500px;
  height: 500px;
} 

section > div {
  width: inherit;
  height: inherit;
  grid-area: 1 / 1;
}

Kolla in det här nu. Anledningen till att jag använde en solid gradient som går från svart till svart tidigare är att ställa in oss för att maskera och blanda de två

skikten. Detta är inte sant maskering i den meningen att vi kallar det mask egenskap, men kontrasten mellan lagren styr vilka färger som är synliga. Området som täcks av vitt kommer att förbli vitt, och området som täcks av svart läcker igenom. MDN:s dokumentation om blandningslägen har en bra förklaring på hur detta fungerar.

För att få det att fungera kommer jag att tillämpa den verkliga gradienten vi vill se på den första

samtidigt som du tillämpar stilreglerna från vår initial

på den nya, med hjälp av :nth-child() pseudoväljare:

div:nth-child(1) { 
  background: linear-gradient(to right, red, orange); 
}

div:nth-child(2)  {
  --gt: linear-gradient(black, black);
  --n: 100px;
  --h: calc(var(--n) - 5px);
  background: 
    var(--gt) top right,
    var(--gt) top var(--n) right,
    var(--gt) top calc(var(--n) * 2) right,
    var(--gt) top calc(var(--n) * 3) right,
    var(--gt) top calc(var(--n) * 4) right, 
    white;
  background-repeat: no-repeat;
  background-size: 60% var(--h), 90% var(--h), 70% var(--h), 40% var(--h), 10% var(--h);
}

Om vi ​​stannar här kommer vi faktiskt inte se någon visuell skillnad från vad vi hade tidigare. Det beror på att vi inte har gjort själva blandningen ännu. Så låt oss göra det nu med hjälp av screen blandningsläge:

div:nth-child(2)  {
  /* etc. */
  mix-blend-mode: screen;
}

Jag använde en beige bakgrundsfärg i demon som jag visade i början av den här artikeln. Den lite mörkare sortens benvita färgen gör att lite färg kan blöda genom resten av bakgrunden:

Svävningseffekten

Den sista biten i detta pussel är svävningseffekten som vidgar ränderna till full bredd. Låt oss först skriva ut vår väljare för det. Vi vill att detta ska ske när den överordnade behållaren (

i vårt fall) är svävad. När den har svävat, ändrar vi bakgrundsstorleken på ränderna i den andra

:

/* When 
is hovered, change the second div's styles */ section:hover > div:nth-child(2){ /* styles go here */ }

Vi vill ändra background-size av ränderna till behållarens fulla bredd samtidigt som man bibehåller samma höjd:

section:hover > div:nth-child(2){
  background-size: 100% var(--h);
}

Det "snäpper" bakgrunden till full bredd. Om vi ​​lägger till lite transition till detta ser vi ränderna expandera vid svävning:

section:hover > div:nth-child(2){
  background-size: 100% var(--h);
  transition: background-size 1s;
}

Här är den sista demon igen:

Jag lade bara till text där för att visa hur det kan se ut att använda detta i ett annat sammanhang. Om du gör detsamma är det värt att se till att det finns tillräckligt med kontrast mellan textfärgen och färgerna som används i övertoningen för att överensstämma med WCAG -riktlinjer. Och medan vi kort berör tillgänglighet, är det värt det med tanke på användarpreferenser för minskad rörelse när det gäller svävningseffekten.

Vi är klara!

Ganska snyggt, eller hur? Det tycker jag verkligen. Det jag gillar med det här också är att det är ganska underhållbart och anpassningsbart. Till exempel kan vi ändra höjden, färgerna och riktningen på ränderna genom att ändra några värden. Du kan till och med ändra några fler saker där - som färger och bredder - för att göra det ännu mer konfigurerbart.

Jag är verkligen intresserad om du skulle ha tagit det här på ett annat sätt. Om så är fallet, vänligen dela i kommentarerna! Det skulle vara kul att se hur många varianter vi kan samla in.

Tidsstämpel:

Mer från CSS-tricks