Fancy Image Decorations: Single Element Magic PlatoBlockchain Data Intelligence. Verticaal zoeken. Ai.

Fancy Image Decorations: Magie met één element

Zoals de titel al zegt, gaan we afbeeldingen versieren! Er zijn een heleboel andere artikelen die hierover praten, maar wat we hier behandelen is heel wat anders omdat het meer een uitdaging is. De uitdaging? Versier een afbeelding met alleen de tag en niets meer.

Dat klopt, geen extra opmaak, geen divs en geen pseudo-elementen. Alleen dat ene label.

Klinkt moeilijk, toch? Maar aan het einde van dit artikel — en de anderen die deel uitmaken van deze kleine serie — zal ik bewijzen dat CSS krachtig genoeg is om ons geweldige en verbluffende resultaten te geven, ondanks de beperking van het werken met een enkel element.

Fancy Image Decorations-serie

  • Magie met één element — je bevindt je hier
  • Maskers en geavanceerde zweefeffecten (komt 21 oktober )
  • Contouren en complexe animaties (komt 28 oktober )

Laten we beginnen met ons eerste voorbeeld

Laten we, voordat we in de code gaan graven, de mogelijkheden opsommen voor het stylen en zonder extra elementen of pseudo-elementen. We kunnen gebruiken border, box-shadow, outlineEn, natuurlijk, background. Het lijkt misschien vreemd om een ​​achtergrond aan een afbeelding toe te voegen, omdat we deze niet kunnen zien omdat deze zich achter de afbeelding bevindt - maar de truc is om ruimte te creëren rond de afbeelding met behulp van padding en / of border en teken dan onze achtergrond in die ruimte.

Ik denk dat je weet wat er daarna komt sinds ik het erover had background, Rechtsaf? Ja, gradiënten! Alle decoraties die we gaan maken, zijn afhankelijk van veel gradiënten. Als je volgde mij voor een tijdje, ik denk dat dit waarschijnlijk helemaal geen verrassing voor je is.

Laten we terugkeren naar ons eerste voorbeeld:

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);
}

We zijn aan het definiëren padding en een transparante border met behulp van de variabele --s om een ​​ruimte rond ons beeld te creëren die gelijk is aan drie keer die variabele.

Waarom gebruiken we beide? padding en border in plaats van het een of het ander? We kunnen krijgen door er slechts één te gebruiken, maar ik heb deze combinatie nodig voor mijn verloop omdat standaard de beginwaarde van background-clip is border-box en background-origin is gelijk aan padding-box.

Hier is een stapsgewijze illustratie om de logica te begrijpen:

In eerste instantie hebben we geen randen op de afbeelding, dus ons verloop zal twee segmenten maken met 1px van dikte. (Ik gebruik 3px in deze specifieke demo, zodat het gemakkelijker te zien is.) We voegen een gekleurde rand toe en het verloop geeft ons nog steeds hetzelfde resultaat binnen het opvulgebied (vanwege background-origin) maar het herhaalt zich achter de grens. Als we de kleur van de rand transparant maken, kunnen we de herhaling gebruiken en krijgen we het frame dat we willen.

De outline in de demo heeft een negatieve offset. Dat creëert een vierkante vorm aan de bovenkant van het verloop. Dat is het! We hebben een mooie decoratie aan onze afbeelding toegevoegd met één verloop en een outline. We hadden meer hellingen kunnen gebruiken! Maar ik probeer mijn code altijd zo eenvoudig mogelijk te houden en ik merkte dat het toevoegen van een outline is beter zo.

Hier is een oplossing met alleen gradiënten waar ik alleen gebruik padding om de ruimte te definiëren. Nog steeds hetzelfde resultaat, maar met een complexere syntaxis.

Laten we een ander idee proberen:

Voor deze nam ik het vorige voorbeeld verwijderde de outline, en toegepast a clip-path om het verloop aan elke kant te snijden. De clip-path waarde is een beetje uitgebreid en verwarrend, maar hier is een illustratie om de punten beter te zien:

Fancy Image Decorations: Magie met één element

Ik denk dat je de hoofdgedachte begrijpt. We gaan achtergronden, contouren, knippen en wat maskeren combineren om verschillende soorten decoraties te krijgen. We gaan ook enkele coole hover-animaties beschouwen als een toegevoegde bonus! Wat we tot nu toe hebben bekeken, is slechts een klein overzicht van wat er gaat komen!

Het alleen hoekframe

Deze duurt vier hellingen. Elke gradiënt bedekt een hoek en bij de muisaanwijzer breiden we ze uit om een ​​volledig frame rond de afbeelding te creëren. Laten we de code voor een van de verlopen ontleden:

--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;

We gaan een verloop tekenen met een grootte gelijk aan 50px 50px en plaats deze in de linkerbovenhoek (0 0). Voor de configuratie van het verloop is hier een stapsgewijze illustratie die laat zien hoe ik dat resultaat heb bereikt.

We hebben de neiging om te denken dat gradiënten alleen goed zijn voor de overgang tussen twee kleuren. Maar in werkelijkheid kunnen we er zoveel meer mee doen! Ze zijn vooral handig als het gaat om het maken van verschillende vormen. De truc is om ervoor te zorgen dat we harde stops tussen kleuren hebben - zoals in het bovenstaande voorbeeld - in plaats van vloeiende overgangen:

#0000 25%, darkblue 0

Dit zegt eigenlijk: "vul het verloop met een transparante kleur tot 25% van het gebied, vul dan het resterende gebied met darkblue.

Misschien krab je je hoofd over de 0 waarde. Het is een kleine hack om de syntaxis te vereenvoudigen. In werkelijkheid zouden we dit moeten gebruiken om een ​​harde stop tussen kleuren te maken:

#0000 25%, darkblue 25%

Dat is logischer! De transparante kleur eindigt bij 25% en darkblue begint precies waar de transparantie eindigt en maakt een harde stop. Als we de tweede vervangen door 0, zal de browser het werk voor ons doen, dus het is een iets efficiëntere manier om dit te doen.

Ergens in de specificatie, het zegt:

indien kleur stop or overgang hint een positie heeft die kleiner is dan de gespecificeerde positie van een kleurstop of overgangshint ervoor in de lijst, stel de positie dan in op de grootste gespecificeerde positie van een kleurstop of overgangshint ervoor.

0 is altijd kleiner dan elke andere waarde, dus de browser converteert deze altijd naar de grootste waarde die ervoor staat in de declaratie. In ons geval is dat nummer 25%.

Nu passen we dezelfde logica toe op alle hoeken en eindigen we met de volgende code:

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;
}

Ik heb CSS-variabelen geïntroduceerd om enige redundantie te voorkomen, aangezien alle verlopen dezelfde kleurconfiguratie gebruiken.

Voor het hover-effect vergroot ik alleen de grootte van de verlopen om het volledige frame te maken:

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

Ja het is 51% in plaats van 50% — dat zorgt voor een kleine overlap en vermijdt mogelijke hiaten.

Laten we een ander idee proberen met dezelfde techniek:

Deze keer gebruiken we slechts twee verlopen, maar met een complexere animatie. Eerst werken we de positie van elk verloop bij en vergroten vervolgens de afmetingen om het volledige frame te maken. Ik heb ook meer variabelen geïntroduceerd voor een betere controle over de kleur, grootte, dikte en zelfs de opening tussen de afbeelding en het frame.

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;
}

Waarom doen de --_i en --_p variabelen een onderstrepingsteken in hun naam hebben? De onderstrepingstekens maken deel uit van een naamgevingsconventie die ik gebruik om rekening te houden met "interne" variabelen die worden gebruikt om de code te optimaliseren. Ze zijn niets bijzonders, maar ik wil een verschil maken tussen de variabelen die we aanpassen om het frame te regelen (zoals --b, --c, etc.) en degene die ik gebruik om de code korter te maken.

De code ziet er misschien verwarrend uit en is niet gemakkelijk te begrijpen, maar ik schreef een driedelige serie waar ik een dergelijke techniek detailleer. Ik raad ten zeerste aan om ten minste het eerste artikel te lezen om te begrijpen hoe ik de bovenstaande code heb bereikt.

Hier is een illustratie om de verschillende waarden beter te begrijpen:

Drie keer dezelfde afbeelding van twee klassieke auto's weergeven om de CSS-variabelen te illustreren die in de code worden gebruikt.
Fancy Image Decorations: Magie met één element

Het frame onthullen

Laten we een ander type animatie proberen, waarbij we het volledige frame bij de muisaanwijzer onthullen:

Cool toch? En als je goed kijkt, zul je merken dat de lijnen in de tegenovergestelde richting verdwijnen als je met de muis naar buiten gaat, wat het effect nog mooier maakt! Ik gebruikte een soortgelijk effect in een vorig artikel.

Maar deze keer, in plaats van het hele element te bedekken, bedek ik slechts een klein deel door a . te definiëren height om zoiets te krijgen:

Dit is de bovenrand van ons frame. We herhalen hetzelfde proces aan elke kant van de afbeelding en we hebben ons zweefeffect:

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%;
}

Zoals je kunt zien, pas ik vier keer hetzelfde verloop toe en elk heeft een andere positie om slechts één kant tegelijk te bedekken.

Nog een? Laten we gaan!

Deze ziet er een beetje lastig uit en het vereist inderdaad wat verbeeldingskracht om te begrijpen hoe twee kegelvormige gradiënten dit soort magie teweegbrengen. Hier is een demo om een ​​van de gradiënten te illustreren:

Het pseudo-element simuleert het verloop. Het is aanvankelijk uit het zicht en bij het zweven veranderen we eerst zijn positie om de bovenrand van het frame te krijgen. Vervolgens vergroten we de hoogte om de rechterrand te krijgen. De verloopvorm is vergelijkbaar met degene die we in het laatste gedeelte hebben gebruikt: twee segmenten om twee zijden te bedekken.

Maar waarom heb ik de breedte van het verloop gemaakt? 200%? Je zou denken 100% zou genoeg zijn, toch?

100% zou genoeg moeten zijn, maar ik zal het verloop niet kunnen verplaatsen zoals ik wil als ik de breedte gelijk houd aan 100%. Dat is nog een kleine eigenaardigheid met betrekking tot hoe background-position werken. Ik bedek dit in een vorig artikel. ik ook heeft een antwoord gepost op Stack Overflow hiermee omgaan. Ik weet dat het veel lezen is, maar het is echt de moeite waard.

Nu we de logica voor één verloop hebben uitgelegd, is de tweede eenvoudig omdat deze precies hetzelfde doet, maar in plaats daarvan de linker- en onderrand bedekt. Het enige wat we hoeven te doen is een paar waarden omwisselen en we zijn klaar:

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;
}

Zoals je kunt zien, zijn beide gradiënten bijna identiek. Ik verwissel gewoon de waarden van de grootte en positie.

De framerotatie

Deze keer gaan we geen kader rond onze afbeelding tekenen, maar eerder het uiterlijk van een bestaande aanpassen.

Je vraagt ​​je waarschijnlijk af hoe ik in godsnaam in staat ben om een ​​rechte lijn om te zetten in een schuine lijn. Nee, de magie is anders dan dat. Dat is gewoon de illusie die we krijgen na het combineren van eenvoudige animaties voor vier verlopen.

Laten we eens kijken hoe de animatie voor het bovenste verloop wordt gemaakt:

Ik werk gewoon de positie van een herhalend verloop bij. Nog niets bijzonders! Laten we hetzelfde doen voor de rechterkant:

Begin je de truc te zien? Beide verlopen kruisen elkaar in de hoek om de illusie te creëren dat de rechte lijn wordt veranderd in een schuine lijn. Laten we de omtrek verwijderen en de overloop verbergen om deze beter te kunnen zien:

Nu voegen we nog twee verlopen toe om de resterende randen te bedekken en we zijn klaar:

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%;
}

Als we deze code nemen en iets aanpassen, kunnen we nog een coole animatie krijgen:

Kun je de logica in dit voorbeeld achterhalen? Dat is je huiswerk! De code ziet er misschien eng uit, maar gebruikt dezelfde logica als de vorige voorbeelden die we hebben bekeken. Probeer elk verloop te isoleren en stel je voor hoe het animeert.

Afsluiten

Dat zijn veel hellingen in één artikel!

Dat is het zeker en ik heb je gewaarschuwd! Maar als de uitdaging is om een ​​afbeelding te decoreren zonder extra elementen en pseudo-elementen, blijven er maar een paar mogelijkheden over en zijn hellingen de krachtigste optie.

Maak je geen zorgen als je een beetje verdwaald bent in sommige verklaringen. Ik raad altijd enkele van mijn oude artikelen aan, waarin ik dieper inga op enkele van de concepten die we voor deze uitdaging hebben hergebruikt.

Ik ga weg met nog een laatste demo om je uit te houden tot het volgende artikel in deze serie. Deze keer gebruik ik radial-gradient() om nog een grappig zweefeffect te creëren. Ik laat je de code ontleden om te zien hoe het werkt. Stel me vragen in de comments als je vastloopt!

Fancy Image Decorations-serie

  • Magie met één element — je bevindt je hier
  • Maskers en geavanceerde zweefeffecten (komt 21 oktober )
  • Contouren en complexe animaties (komt 28 oktober )

Tijdstempel:

Meer van CSS-trucs