Xlera8

Hieno leijuva tehoste avatarillesi

Tiedätkö sellaisen vaikutuksen, jossa jonkun pää työntyy ympyrän tai reiän läpi? Kuuluisa Porky Pig -animaatio, jossa hän vilkuttaa hyvästit punaisten sormusten sarjasta, on täydellinen esimerkki. Kilian Valkhof itse asiassa loi sen uudelleen täällä CSS-Tricksissä jokin aika sitten.

Minulla on samanlainen ajatus, mutta käsitin eri tavalla ja animaatiolla. Mielestäni se on melko käytännöllinen ja saa aikaan siistin hover-efektin, jota voit käyttää esimerkiksi omassa avatarissasi.

Näetkö tuon? Aiomme tehdä skaalaavan animaation, jossa avatar näyttää ponnahtavan suoraan ulos ympyrästä, jossa se on. Hienoa, eikö? Älä katso koodia, vaan rakennetaan tämä animaatio yhdessä askel askeleelta.

HTML: Vain yksi elementti

Jos et ole tarkistanut demon koodia ja mietit kuinka monta divs tämä kestää ja lopeta sitten tähän, koska merkintämme on vain yksi kuvaelementti:

<img src="" alt="">

Kyllä, yksi elementti! Tämän harjoituksen haastavin osa on käyttää mahdollisimman vähän koodia. Jos olet ollut seuraa minua jonkin aikaa, sinun pitäisi tottua tähän. Yritän kovasti löytää CSS-ratkaisuja, jotka voidaan saavuttaa pienimmällä ja ylläpidettävällä koodilla.

Kirjoitin artikkelisarja täällä CSS-Tricksissä, jossa tutkin erilaisia ​​hover-tehosteita käyttämällä samaa HTML-merkintää, joka sisältää yhden elementin. Menen yksityiskohtiin kaltevuudesta, peittämisestä, leikkaamisesta, ääriviivoista ja jopa asettelutekniikoista. Suosittelen tarkistamaan ne, koska aion käyttää monia tämän postauksen temppuja uudelleen.

Neliön muotoinen kuvatiedosto läpinäkyvällä taustalla sopii parhaiten toimintaamme. Tässä on yksi, jota käytän, jos haluat aloittaa siitä.

Suunnitellut cang

Toivon näkeväni tästä paljon esimerkkejä oikeiden kuvien avulla – joten jaa lopputuloksesi kommentteihin, kun olet valmis, jotta voimme rakentaa kokoelman!

Ennen kuin siirryt CSS:ään, tarkastellaan ensin tehostetta. Kuva kasvaa leijuttaessa, joten tulemme varmasti käyttämään transform: scale() siellä. Avatarin takana on ympyrä, ja säteittäisen gradientin pitäisi tehdä temppu. Lopuksi tarvitsemme tavan luoda ympyrän alaosaan reunus, joka luo avatarin ulkonäön ympyrän taakse.

Mennään töihin!

Mittakaavaefekti

Aloitetaan lisäämällä muunnos:

img { width: 280px; aspect-ratio: 1; cursor: pointer; transition: .5s;
}
img:hover { transform: scale(1.35);
}

Ei mitään monimutkaista vielä, eihän? Siirrytään eteenpäin.

Ympyrä

Sanoimme, että tausta olisi säteittäinen gradientti. Se on täydellinen, koska voimme luoda kovia pysähdyksiä säteittäisen gradientin värien väliin, mikä saa sen näyttämään siltä, ​​että piirremme ympyrän kiinteillä viivoilla.

img { --b: 5px; /* border width */ width: 280px; aspect-ratio: 1; background: radial-gradient( circle closest-side, #ECD078 calc(99% - var(--b)), #C02942 calc(100% - var(--b)) 99%, #0000 ); cursor: pointer; transition: .5s;
}
img:hover { transform: scale(1.35);
}

Huomaa CSS-muuttuja, --b, käytän siellä. Se edustaa "reunan" paksuutta, jota käytetään oikeastaan ​​vain määrittämään kovia väripysähdyksiä säteittäisen gradientin punaiselle osalle.

Seuraava askel on pelata liukuvärin koolla hover-tilassa. Ympyrän on säilytettävä kokonsa kuvan kasvaessa. Koska haemme a scale() muodonmuutos, meidän on todella tehtävä vähentää ympyrän koko, koska se muuten skaalautuu avatarin mukana. Joten, kun kuva skaalautuu, tarvitsemme gradientin skaalautumaan.

Aloitetaan määrittelemällä CSS-muuttuja, --f, joka määrittää "skaalaustekijän" ja käyttää sitä ympyrän koon asettamiseen. Käytän 1 oletusarvona, koska se on kuvan ja ympyrän, josta muunnetaan, alkuperäinen asteikko.

Tässä on demo tempun havainnollistamiseksi. Vie hiiri nähdäksesi mitä kulissien takana tapahtuu:

Lisäsin siihen kolmannen värin radial-gradient tunnistaaksesi liukuvärin alueen paremmin hiiri:

radial-gradient( circle closest-side, #ECD078 calc(99% - var(--b)), #C02942 calc(100% - var(--b)) 99%, lightblue
);

Nyt meidän on asetettava taustamme ympyrän keskelle ja varmistettava, että se vie koko korkeuden. Haluan ilmoittaa kaiken suoraan background shorthand-ominaisuus, jotta voimme lisätä taustasijaintimme ja varmistaa, ettei se toistu, kiinnittämällä näihin arvoihin heti radial-gradient():

background: radial-gradient() 50% / calc(100% / var(--f)) 100% no-repeat;

Tausta on sijoitettu keskelle (50%), jonka leveys on yhtä suuri kuin calc(100%/var(--f)), ja sen korkeus on yhtä suuri kuin 100%.

Mikään ei skaalaudu milloin --f on yhtä suuri kuin 1 – jälleen alkuperäinen mittakaavamme. Samaan aikaan gradientti vie säiliön koko leveyden. Kun lisäämme --f, elementin koko kasvaa - kiitos scale() muunnos — ja gradientin koko pienenee.

Tässä on mitä saamme, kun käytämme tätä kaikkea demossamme:

Olemme tulossa lähemmäksi! Meillä on ylivuotoefekti ylhäällä, mutta meidän on silti piilotettava kuvan alaosa, joten näyttää siltä, ​​​​että se ponnahtaa ulos ympyrästä eikä istuisi sen edessä. Se on hankala osa tätä koko asiaa, ja sen aiomme tehdä seuraavaksi.

Alareuna

Yritin ensin käsitellä tätä asiaa border-bottom omaisuutta, mutta en löytänyt tapaa sovittaa reunuksen koko ympyrän kokoon. Tässä on parasta mitä voin saada, ja näet heti, että se on väärin:

Varsinainen ratkaisu on käyttää outline omaisuutta. Joo, outline, Ei border. sisään edellinen artikkeli, näytän miten outline on tehokas ja antaa meille mahdollisuuden luoda viileitä hover-efektejä. Yhdistettynä outline-offset, meillä on juuri se, mitä tarvitsemme vaikutukseemme.

Ajatuksena on asettaa an outline kuvassa ja säädä sen siirtymää luodaksesi alareunuksen. Poikkeama riippuu skaalauskertoimesta samalla tavalla kuin gradientin koko.

Nyt meillä on alarajamme (itse asiassa an outline) yhdistettynä gradientin luomaan "reunukseen" täyden ympyrän luomiseksi. Meidän on silti piilotettava osia outline (ylhäältä ja sivuilta), johon pääsemme hetken kuluttua.

Tässä on tähän mennessä koodimme, mukaan lukien pari muuta CSS-muuttujaa, joilla voit määrittää kuvan koon (--s) ja "reunuksen" väri (--c):

img { --s: 280px; /* image size */ --b: 5px; /* border thickness */ --c: #C02942; /* border color */ --f: 1; /* initial scale */ width: var(--s); aspect-ratio: 1; cursor: pointer; border-radius: 0 0 999px 999px; outline: var(--b) solid var(--c); outline-offset: calc((1 / var(--f) - 1) * var(--s) / 2 - var(--b)); background: radial-gradient( circle closest-side, #ECD078 calc(99% - var(--b)), var(--c) calc(100% - var(--b)) 99%, #0000 ) 50% / calc(100% / var(--f)) 100% no-repeat; transform: scale(var(--f)); transition: .5s;
}
img:hover { --f: 1.35; /* hover scale */
}

Koska tarvitsemme pyöreän alareunuksen, lisäsimme a border-radius alapuolella, jolloin outline vastaamaan gradientin kaarevuutta.

Käytössä oleva laskelma outline-offset on paljon suoraviivaisempi kuin miltä se näyttää. Oletuksena, outline on piirretty ulkopuolella elementin laatikosta. Ja meidän tapauksessamme tarvitsemme sitä päällekkäisyys elementti. Tarkemmin sanottuna tarvitsemme sen seuraamaan gradientin luomaa ympyrää.

Taustan siirtymän kaavio.

Kun skaalaamme elementin, näemme ympyrän ja reunan välisen tilan. Älkäämme unohtako, että ideana on pitää ympyrä samassa koossa mittakaavamuunnoksen jälkeen, jolloin meille jää tilaa, jota käytämme ääriviivan siirtymän määrittelemiseen yllä olevan kuvan mukaisesti.

Älkäämme unohtako, että toinen elementti on skaalattu, joten myös tuloksemme skaalataan… mikä tarkoittaa, että meidän on jaettava tulos f saadaksesi todellisen offset-arvon:

Offset = ((f - 1) * S/2) / f = (1 - 1/f) * S/2

Lisäämme negatiivisen merkin, koska tarvitsemme ääriviivat ulkopuolelta sisäänpäin:

Offset = (1/f - 1) * S/2

Tässä on nopea esittely, joka näyttää, kuinka ääriviivat noudattavat gradienttia:

Saatat jo nähdä sen, mutta tarvitsemme silti alaääriviivat peittämään ympyrän sen sijaan, että annamme sen vuotaa sen läpi. Voimme tehdä sen poistamalla reunuksen koon siirtymästä:

outline-offset: calc((1 / var(--f) - 1) * var(--s) / 2) - var(--b));

Nyt meidän on löydettävä kuinka poistaa yläosa ääriviivasta. Toisin sanoen haluamme vain kuvan alaosan outline.

Ensin lisätään tilaa yläosaan pehmusteella, jotta vältetään päällekkäisyys yläosassa:

img { --s: 280px; /* image size */ --b: 5px; /* border thickness */ --c: #C02942; /* border color */ --f: 1; /* initial scale */ width: var(--s); aspect-ratio: 1; padding-block-start: calc(var(--s)/5); /* etc. */
}
img:hover { --f: 1.35; /* hover scale */
}

Tuossa yläpehmusteessa ei ole mitään erityistä logiikkaa. Ajatuksena on varmistaa, että ääriviivat eivät kosketa avatarin päätä. Käytin elementin kokoa määrittämään, että tila on aina sama.

Huomaa, että olen lisännyt content-box arvoa background:

background: radial-gradient( circle closest-side, #ECD078 calc(99% - var(--b)), var(--c) calc(100% - var(--b)) 99%, #0000 ) 50%/calc(100%/var(--f)) 100% no-repeat content-box;

Tarvitsemme tämän, koska lisäsimme täytteen ja haluamme vain taustan olevan sisältölaatikossa, joten meidän on nimenomaisesti kerrottava taustalle, että se pysähtyy.

CSS-maskin lisääminen sekoitukseen

Pääsimme viimeiseen osaan! Meidän tarvitsee vain piilottaa joitakin palasia, ja olemme valmiita. Tässä luotamme siihen mask omaisuus ja tietysti kaltevuudet.

Tässä on kuva havainnollistamaan, mitä meidän on piilotettava tai mitä meidän on näytettävä ollaksemme tarkempia

Näyttää, kuinka maski koskee ympyrän alaosaa.

Vasen kuva on se, mitä meillä on tällä hetkellä, ja oikea on se, mitä haluamme. Vihreä osa havainnollistaa maskia, joka meidän on kiinnitettävä alkuperäiseen kuvaan saadaksemme lopputuloksen.

Voimme tunnistaa kaksi osaa maskistamme:

  • Pyöreä osa alareunassa, jolla on samat mitat ja kaarevuus kuin säteittäinen gradientti, jota käytimme luomaan ympyrän avatarin taakse
  • Yläosassa oleva suorakulmio, joka peittää ääriviivan sisällä olevan alueen. Huomaa, kuinka ääriviivat ovat yläosan vihreän alueen ulkopuolella – se on tärkein osa, koska sen avulla ääriviivat voidaan leikata niin, että vain alaosa on näkyvissä.

Tässä on lopullinen CSS:mme:

img { --s: 280px; /* image size */ --b: 5px; /* border thickness */ --c: #C02942; /* border color */ --f: 1; /* initial scale */ --_g: 50% / calc(100% / var(--f)) 100% no-repeat content-box; --_o: calc((1 / var(--f) - 1) * var(--s) / 2 - var(--b)); width: var(--s); aspect-ratio: 1; padding-top: calc(var(--s)/5); cursor: pointer; border-radius: 0 0 999px 999px; outline: var(--b) solid var(--c); outline-offset: var(--_o); background: radial-gradient( circle closest-side, #ECD078 calc(99% - var(--b)), var(--c) calc(100% - var(--b)) 99%, #0000) var(--_g); mask: linear-gradient(#000 0 0) no-repeat 50% calc(-1 * var(--_o)) / calc(100% / var(--f) - 2 * var(--b)) 50%, radial-gradient( circle closest-side, #000 99%, #0000) var(--_g); transform: scale(var(--f)); transition: .5s;
}
img:hover { --f: 1.35; /* hover scale */
}

Puretaan se mask omaisuutta. Ensinnäkin huomaa, että samanlainen radial-gradient() mistä background omaisuus on siellä. loin uuden muuttujan, --_g, jotta yhteiset osat tekevät asioista vähemmän sotkuisia.

--_g: 50% / calc(100% / var(--f)) 100% no-repeat content-box; mask: radial-gradient( circle closest-side, #000 99%, #0000) var(--_g);

Seuraavaksi on a linear-gradient() siellä myös:

--_g: 50% / calc(100% / var(--f)) 100% no-repeat content-box; mask: linear-gradient(#000 0 0) no-repeat 50% calc(-1 * var(--_o)) / calc(100% / var(--f) - 2 * var(--b)) 50%, radial-gradient( circle closest-side, #000 99%, #0000) var(--_g);

Tämä luo maskin suorakaideosan. Sen leveys on yhtä suuri kuin säteittäisen gradientin leveys miinus kaksinkertainen reunan paksuus:

calc(100% / var(--f) - 2 * var(--b))

Suorakulmion korkeus on puolet, 50%, elementin koosta.

Tarvitsemme myös lineaarisen gradientin, joka on sijoitettu vaakasuoraan keskelle (50%) ja siirtyy ylhäältä samalla arvolla kuin ääriviivan siirtymä. Loin toisen CSS-muuttujan, --_o, aiemmin määrittämällemme siirrolle:

--_o: calc((1 / var(--f) - 1) * var(--s) / 2 - var(--b));

Yksi hämmentävä asia tässä on, että tarvitsemme a negatiivinen ääriviivan siirtymä (siirtääksesi sen ulkopuolelta sisälle), mutta a positiivinen gradientin siirtymä (siirtyä ylhäältä alas). Joten jos mietit, miksi kerromme offsetin, --_o, jonka -1, no nyt tiedät!

Tässä on demo maskin gradienttikokoonpanon havainnollistamiseksi:

Vie hiiri yllä ja katso, kuinka kaikki liikkuu yhdessä. Keskimmäinen laatikko havainnollistaa maskikerroksen, joka koostuu kahdesta gradientista. Kuvittele se vasemman kuvan näkyvänä osana, ja saat lopputuloksen oikealla!

Käärimistä

Oho, ollaan valmis! Emme vain päätyneet liukkaaseen leijuusanimaatioon, vaan teimme sen kaiken yhdellä HTML-koodilla <img> elementti. Juuri tämä ja alle 20 riviä CSS-temppuja!

Toki luotimme joihinkin pieniin temppuihin ja matemaattisiin kaavoihin saavuttaaksemme näin monimutkaisen vaikutuksen. Mutta tiesimme tarkalleen, mitä tehdä, koska tunnistimme tarvittavat osat etukäteen.

Olisimmeko voineet yksinkertaistaa CSS:ää, jos olisimme sallineet itsellemme enemmän HTML:ää? Ehdottomasti. Mutta olemme täällä oppimassa uusia CSS-temppuja! Tämä oli hyvä harjoitus tutkia CSS-gradientteja, peittämistä ja outline kiinteistön käyttäytyminen, muutokset ja paljon muuta. Jos tunnet olosi eksyksissä jossain vaiheessa, tarkista ehdottomasti minun sarjani joka käyttää samoja yleiskäsitteitä. Joskus on hyödyllistä nähdä enemmän esimerkkejä ja käyttää tapauksia ajaaksesi pisteen kotiin.

Jätän sinulle viimeisen demon, joka käyttää suosittujen CSS-kehittäjien valokuvia. Älä unohda näyttää minulle demoa omalla kuvallasi, jotta voin lisätä sen kokoelmaan!

Keskustele kanssamme

Hei siellä! Kuinka voin olla avuksi?