Fancy billeddekorationer: Single Element Magic PlatoBlockchain Data Intelligence. Lodret søgning. Ai.

Fancy billeddekorationer: Single Element Magic

Som titlen siger, skal vi dekorere billeder! Der er en masse andre artikler derude, der taler om dette, men det, vi dækker her, er en hel del anderledes, fordi det er mere en udfordring. Udfordringen? Dekorer et billede ved kun at bruge tag og intet mere.

Det rigtige, ingen ekstra markup, ingen divs og ingen pseudo-elementer. Bare det ene mærke.

Det lyder svært, ikke? Men i slutningen af ​​denne artikel - og de andre, der udgør denne lille serie - vil jeg bevise, at CSS er kraftfuld nok til at give os fantastiske og fantastiske resultater på trods af begrænsningen af ​​at arbejde med et enkelt element.

Fancy billeddekorationsserie

  • Single Element Magic — du er her
  • Masker og avancerede svæveeffekter (kommer den 21. oktober )
  • Konturer og komplekse animationer (kommer den 28. oktober )

Lad os starte med vores første eksempel

Inden vi graver i koden, lad os opregne mulighederne for at style en uden ekstra elementer eller pseudo-elementer. Vi kan bruge border, box-shadow, outlineOg, selvfølgelig, background. Det kan se mærkeligt ud at tilføje en baggrund til et billede, fordi vi ikke kan se det, da det vil være bag billedet - men tricket er at skabe rum omkring billedet ved hjælp af padding og / eller border og tegn derefter vores baggrund inde i det rum.

Jeg tror, ​​du ved, hvad der kommer næste gang, siden jeg talte om background, ret? Ja, gradienter! Alle de dekorationer, vi skal lave, er afhængige af en masse gradienter. Hvis du har fulgte mig i et stykke tid, tror jeg, at det nok ikke kommer som nogen overraskelse for dig overhovedet. 😁

Lad os vende tilbage til vores første eksempel:

img {
  --s: 10px; /* control the size */
  padding: var(--s);
  border: calc(2 * var(--s)) solid #0000;
  outline: 1px solid #000;
  outline-offset: calc(-1 * var(--s));
  background: conic-gradient(from 90deg at 1px 1px, #0000 25%, #000 0);
}

Vi definerer padding og en gennemsigtig border ved hjælp af variablen --s at skabe et rum omkring vores billede svarende til tre gange den variable.

Hvorfor bruger vi begge dele padding , border i stedet for det ene eller det andet? Vi kan få ved at bruge kun én af dem, men jeg har brug for denne kombination til min gradient, fordi den oprindelige værdi af background-clip is border-box , background-origin er lig med padding-box.

Her er en trin-for-trin illustration for at forstå logikken:

I første omgang har vi ingen grænser på billedet, så vores gradient vil skabe to segmenter med 1px af tykkelse. (Jeg bruger 3px i denne specifikke demo, så det er lettere at se.) Vi tilføjer en farvet kant, og gradienten giver os stadig det samme resultat inde i polstringsområdet (pga. background-origin), men det gentager sig bag grænsen. Hvis vi gør farven på kanten gennemsigtig, kan vi bruge gentagelsen, og vi får den ramme, vi ønsker.

outline i demoen har en negativ offset. Det skaber en firkantet form i toppen af ​​gradienten. Det er det! Vi tilføjede en flot dekoration til vores billede ved hjælp af en gradient og en outline. Vi kunne have brugt flere gradienter! Men jeg forsøger altid at holde min kode så enkel som muligt, og jeg fandt ud af, at tilføjelse af en outline er bedre på den måde.

Her er en gradient-only-løsning, hvor jeg kun bruger padding at definere rummet. Stadig det samme resultat, men med en mere kompleks syntaks.

Lad os prøve en anden idé:

For denne tog jeg det forrige eksempel fjernet outline, og anvendte en clip-path at skære gradienten på hver side. Det clip-path værdien er lidt ordrig og forvirrende, men her er en illustration for bedre at se dens pointer:

Fancy billeddekorationer: Single Element Magic

Jeg tror, ​​du forstår hovedideen. Vi kommer til at kombinere baggrunde, konturer, klipning og lidt maskering for at opnå forskellige slags dekorationer. Vi vil også overveje nogle fede svæveanimationer som en ekstra bonus! Det, vi har set på indtil videre, er blot et lille overblik over, hvad der kommer!

Den eneste hjørneramme

Denne tager fire gradienter. Hver gradient dækker et hjørne, og når vi svæver, udvider vi dem for at skabe en fuld ramme omkring billedet. Lad os dissekere koden for en af ​​gradienterne:

--b: 5px; /* border thickness */
background: conic-gradient(from 90deg at top var(--b) left var(--b), #0000 90deg, darkblue 0) 0 0;
background-size: 50px 50px; 
background-repeat: no-repeat;

Vi skal tegne en gradient med en størrelse lig med 50px 50px og placer den i øverste venstre hjørne (0 0). For gradientens konfiguration er her en trin-for-trin illustration, der viser, hvordan jeg nåede det resultat.

Vi har en tendens til at tro, at gradienter kun er gode til at skifte mellem to farver. Men i virkeligheden kan vi gøre så meget mere med dem! De er især nyttige, når det kommer til at skabe forskellige former. Tricket er at sikre, at vi har hårde stop mellem farver - som i eksemplet ovenfor - snarere end jævne overgange:

#0000 25%, darkblue 0

Dette er dybest set at sige: "fyld gradienten med en gennemsigtig farve indtil 25% af området, og fyld derefter det resterende område med darkblue.

Du klør dig måske i hovedet over 0 værdi. Det er et lille hack for at forenkle syntaksen. I virkeligheden burde vi bruge dette til at gøre et hårdt stop mellem farverne:

#0000 25%, darkblue 25%

Det er mere logisk! Den transparente farve slutter kl 25% , darkblue starter præcis, hvor gennemsigtigheden slutter, hvilket gør et hårdt stop. Hvis vi erstatter den anden med 0, vil browseren klare opgaven for os, så det er en lidt mere effektiv måde at gøre det på.

Et eller andet sted i specifikationen, det siger:

hvis en farvestop or overgangstip har en position, der er mindre end den angivne position for et farvestop eller overgangstip før den på listen, skal du indstille dens position til at være lig med den største specificerede position af et farvestop eller overgangstip før den.

0 er altid mindre end nogen anden værdi, så browseren vil altid konvertere den til den største værdi, der kommer før den i erklæringen. I vores tilfælde er det tal 25%.

Nu anvender vi den samme logik på alle hjørnerne, og vi slutter med følgende kode:

img {
  --b: 5px; /* border thickness */
  --c: #0000 90deg, darkblue 0; /* define the color here */
  padding: 10px;
  background:
    conic-gradient(from 90deg  at top    var(--b) left  var(--b), var(--c)) 0 0,
    conic-gradient(from 180deg at top    var(--b) right var(--b), var(--c)) 100% 0,
    conic-gradient(from 0deg   at bottom var(--b) left  var(--b), var(--c)) 0 100%,
    conic-gradient(from -90deg at bottom var(--b) right var(--b), var(--c)) 100% 100%;
  background-size: 50px 50px; /* adjust border length here */
  background-repeat: no-repeat;
}

Jeg har introduceret CSS-variabler for at undgå en vis redundans, da alle gradienter bruger den samme farvekonfiguration.

For svæveeffekten er alt, hvad jeg gør, at øge størrelsen af ​​gradienterne for at skabe den fulde ramme:

img:hover {
  background-size: 51% 51%;
}

Ja det er 51% i stedet for 50% — der skaber et lille overlap og undgår mulige huller.

Lad os prøve en anden idé med samme teknik:

Denne gang bruger vi kun to gradienter, men med en mere kompleks animation. Først opdaterer vi placeringen af ​​hver gradient, og øger derefter deres størrelser for at skabe den fulde ramme. Jeg introducerede også flere variabler for bedre kontrol over farven, størrelsen, tykkelsen og endda afstanden mellem billedet og rammen.

img {
  --b: 8px;  /* border thickness*/
  --s: 60px; /* size of the corner*/
  --g: 14px; /* the gap*/
  --c: #EDC951; 

  padding: calc(var(--b) + var(--g));
  background-image:
    conic-gradient(from  90deg at top    var(--b) left  var(--b), #0000 25%, var(--c) 0),
    conic-gradient(from -90deg at bottom var(--b) right var(--b), #0000 25%, var(--c) 0);
  background-position:
    var(--_p, 0%) var(--_p, 0%),
    calc(100% - var(--_p, 0%)) calc(100% - var(--_p, 0%));
  background-size: var(--s) var(--s);
  background-repeat: no-repeat;
  transition: 
    background-position .3s var(--_i,.3s), 
    background-size .3s calc(.3s - var(--_i, .3s));
}
img:hover {
  background-size: calc(100% - var(--g)) calc(100% - var(--g));
  --_p: calc(var(--g) / 2);
  --_i: 0s;
}

Hvorfor gør --_i , --_p variable har en understregning i deres navn? Understregningerne er en del af en navnekonvention, jeg bruger til at overveje "interne" variabler, der bruges til at optimere koden. De er ikke noget særligt, men jeg vil gerne gøre en forskel mellem de variabler, vi justerer for at styre rammen (som --b, --cosv.) og dem jeg bruger til at gøre koden kortere.

Koden kan se forvirrende ud og ikke let at forstå, men jeg skrev en serie i tre dele hvor jeg detaljerer sådan teknik. Jeg anbefaler stærkt at læse i det mindste den første artikel for at forstå, hvordan jeg nåede ovenstående kode.

Her er en illustration til bedre at forstå de forskellige værdier:

Viser det samme billede af to klassiske biler tre gange for at illustrere de CSS-variabler, der bruges i koden.
Fancy billeddekorationer: Single Element Magic

The Frame Reveal

Lad os prøve en anden type animation, hvor vi afslører hele billedet, når vi svæver:

Fedt, ikke? Og hvis du ser godt efter, vil du bemærke, at stregerne forsvinder i den modsatte retning på musen ud, hvilket gør effekten endnu mere fancy! Jeg brugte en lignende effekt i en tidligere artikel.

Men denne gang, i stedet for at dække hele elementet, dækker jeg kun en lille del ved at definere en height for at få noget som dette:

Dette er den øverste kant af vores ramme. Vi gentager den samme proces på hver side af billedet, og vi har vores hover-effekt:

img {
  --b: 10px; /* the border thickness*/
  --g: 5px; /* the gap on hover */
  --c: #8A9B0F; 

  padding: calc(var(--g) + var(--b));
  --_g: no-repeat linear-gradient(var(--c) 0 0);
  background: 
    var(--_g) var(--_i, 0%) 0,
    var(--_g) 100% var(--_i, 0%),
    var(--_g) calc(100% - var(--_i, 0%)) 100%,
    var(--_g) 0 calc(100% - var(--_i, 0%));
  background-size: var(--_i, 0%) var(--b),var(--b) var(--_i, 0%);
  transition: .4s, background-position 0s;
  cursor: pointer;
}
img:hover {
  --_i: 100%;
}

Som du kan se, anvender jeg den samme gradient fire gange, og hver af dem har en anden position til kun at dække én side ad gangen.

Endnu en? Lad os gå!

Denne ser en smule vanskelig ud, og det kræver faktisk lidt fantasi at forstå, hvordan to kegleformede gradienter udløser denne form for magi. Her er en demo for at illustrere en af ​​gradienterne:

Pseudo-elementet simulerer gradienten. Den er i første omgang ude af syne, og når vi svæver, ændrer vi først dens position for at få den øverste kant af rammen. Så øger vi højden for at få den rigtige kant. Gradientformen ligner dem, vi brugte i sidste afsnit: to segmenter til at dække to sider.

Men hvorfor lavede jeg gradientens bredde 200%? Man skulle tro 100% ville være nok, ikke?

100% burde være nok, men jeg vil ikke være i stand til at flytte gradienten, som jeg vil, hvis jeg holder dens bredde lig med 100%. Det er en anden lille særhed relateret til hvordan background-position arbejder. Jeg dækker dette ind en tidligere artikel. Også mig postede et svar på Stack Overflow beskæftiger sig med dette. Jeg ved, det er meget læsning, men det er virkelig din tid værd.

Nu hvor vi har forklaret logikken for en gradient, er den anden nem, fordi den gør nøjagtig det samme, men dækker i stedet venstre og nederste kanter. Alt vi skal gøre er at bytte nogle få værdier, og vi er færdige:

img {
  --c: #8A9B0F; /* the border color */
  --b: 10px; /* the border thickness*/
  --g: 5px;  /* the gap */

  padding: calc(var(--g) + var(--b));
  --_g: #0000 25%, var(--c) 0;
  background: 
    conic-gradient(from 180deg at top    var(--b) right var(--b), var(--_g))
     var(--_i, 200%) 0 / 200% var(--_i, var(--b))  no-repeat,
    conic-gradient(            at bottom var(--b) left  var(--b), var(--_g))
     0 var(--_i, 200%) / var(--_i, var(--b)) 200%  no-repeat;
  transition: .3s, background-position .3s .3s;
  cursor: pointer;
}
img:hover {
  --_i: 100%;
  transition: .3s, background-size .3s .3s;
}

Som du kan se, er begge gradienter næsten identiske. Jeg bytter simpelthen værdierne for størrelse og position.

Rammerotationen

Denne gang skal vi ikke tegne en ramme omkring vores billede, men snarere justere udseendet af et eksisterende.

Du spørger sikkert, hvordan pokker jeg er i stand til at transformere en lige linje til en vinklet linje. Nej, magien er anderledes end det. Det er bare den illusion, vi får efter at have kombineret simple animationer til fire gradienter.

Lad os se, hvordan animationen til den øverste gradient er lavet:

Jeg opdaterer simpelthen positionen for en gentagende gradient. Ikke noget fancy endnu! Lad os gøre det samme for højre side:

Er du begyndt at se tricket? Begge gradienter skærer hinanden i hjørnet for at skabe en illusion, hvor den lige linje ændres til en vinklet. Lad os fjerne omridset og skjule overløbet for bedre at se det:

Nu tilføjer vi yderligere to gradienter for at dække de resterende kanter, og vi er færdige:

img {
  --g: 4px; /* the gap */
  --b: 12px; /* border thickness*/
  --c: #669706; /* the color */

  padding: calc(var(--g) + var(--b));
  --_c: #0000 0 25%, var(--c) 0 50%;
  --_g1: repeating-linear-gradient(90deg ,var(--_c)) repeat-x;
  --_g2: repeating-linear-gradient(180deg,var(--_c)) repeat-y;
  background:
    var(--_g1) var(--_p, 25%) 0, 
    var(--_g2) 0 var(--_p, 125%),
    var(--_g1) var(--_p, 125%) 100%, 
    var(--_g2) 100% var(--_p, 25%);
  background-size: 200% var(--b), var(--b) 200%;
  transition: .3s;
}
img:hover {
  --_p: 75%;
}

Hvis vi tager denne kode og justerer den lidt, kan vi få endnu en fed animation:

Kan du finde ud af logikken i dette eksempel? Det er dine lektier! Koden ser måske skræmmende ud, men den bruger den samme logik som de tidligere eksempler, vi så på. Prøv at isolere hver gradient og forestil dig, hvordan den animerer.

Indpakning op

Det er mange gradienter i én artikel!

Det er det bestemt, og jeg advarede dig! Men hvis udfordringen er at dekorere et billede uden ekstra elementer og pseudo-elementer, står vi tilbage med kun få muligheder, og gradienter er den mest kraftfulde mulighed.

Bare rolig, hvis du er lidt fortabt i nogle af forklaringerne. Jeg anbefaler altid nogle af mine gamle artikler, hvor jeg går mere i detaljer med nogle af de koncepter, vi genbrugte til denne udfordring.

Jeg går afsted med en sidste demo for at holde dig tilbage indtil næste artikel i denne serie. Denne gang bruger jeg radial-gradient() for at skabe endnu en sjov svæveeffekt. Jeg vil lade dig dissekere koden for at finde ud af, hvordan den virker. Stil mig spørgsmål i kommentarerne, hvis du går i stå!

Fancy billeddekorationsserie

  • Single Element Magic — du er her
  • Masker og avancerede svæveeffekter (kommer den 21. oktober )
  • Konturer og komplekse animationer (kommer den 28. oktober )

Tidsstempel:

Mere fra CSS-tricks