Att rita Bilder med CSS Gradienter

0
23

Vad jag menar med “CSS-bilder” är bilder som är skapade för att bara använda HTML-element och CSS. De ser ut som om de var SVGs ritas i Adobe Illustrator, men de var gjorda direkt i webbläsaren. Några tekniker som jag har sett användas mixtra med gränsen radier, box skuggor, och ibland klipp-väg. Du kan hitta en hel del bra exempel om du söker dagligen css-bilder” på CodePen. Jag drog några själv, inklusive denna Infinity Gauntlet, men i en del med endast bakgrunder och minimal användning av andra egenskaper.

Låt oss ta en titt på hur du kan skapa CSS-bilder på det sättet själv.

Metoden

Förståelse stenografi bakgrund syntax samt hur CSS gradienter arbete är praktiskt taget allt du behöver för att rita något i ett element. En recension, argumenten är följande:

bakgrund: <‘background-color’> || <bild> || <position> [ / <storlek> ]? || <upprepa> || <bifogad fil> || <ursprunget> || <klipp>;

De kan förekomma i vilken ordning med undantag av att det måste finnas ett / mellan position och storlek. Vi måste behålla dessa två argument i den ordningen också, annars kommer vi att få oväntade resultat. Inte alla av dessa måste inkluderas, och för detta ändamål har vi inte använder färg, upprepa, kvarstad, ursprung, eller klipp argument. Detta lämnar oss med bild, storlek och position. Eftersom bakgrunder upprepa som standard, dock, måste vi sätta background-repeat: no-repeat; rätt enligt allt som står i bakgrunden (om vissa bakgrunder borde vara återkommande, som vi kan använda för att upprepa-linear-gradient() och upprepa-radial gradient()). I så fall, skelettet CSS kommer att vara denna:

.bild {
bakgrund: <bild> <position> / <storlek>;
background-repeat: no-repeat;
}

Vi kan även använda flera uppsättningar av bakgrunden argument! Därför kan vi stack och separera dem med kommatecken så här:

.bild {
bakgrund:
<image> <position> / <storlek>,
<image> <position> / <storlek>,
<image> <position> / <storlek>;
background-repeat: no-repeat;
}

Strukturen ovan är grunden för hur vi ska rita bilder—en rad per form. Tänk på att de som gör så är motsatsen av hur absolut – eller fast position delar är beställda. Det första man kommer att visa upp på toppen istället för botten. Med andra ord, i cirklar (radiell lutningar) nedan återges från botten till toppen (blå på undersidan, red på toppen).

.cirklar {
bakgrund:
radial gradient(7em 7em på 35% 35%, röd 50%, transparent 50%),
radial gradient(7em 7em på 50% 50% guld och 50%, transparent 50%),
radial gradient(7em 7em på 65% 65%, blå 50%, transparent 50 procent).
background-repeat: no-repeat;
bredd: 240px;
höjd: 240px;
}

Ritning

Vi kommer att använda Sass (SCSS) för att dra dessa bilder så vi kan använda variabler för en färgpalett. Som kommer att göra koden kortare, lättare att läsa och ändra mörkare eller ljusare varianter av färger. Vi skulle kunna använda variabler i normala CSS istället och glömmer Sass, men på grund av Internet Explorer saknar stöd för, låt oss hålla oss med Sass. För att förklara hur det fungerar, vi kommer att experimentera med former med hjälp av både linjär och radiella gradienter.

Att sätta Upp en Färgpalett

Vår färgpalett består av RGB eller HSL färger. Jag ska förklara senare varför hålla färgerna i något av dessa format. För detta exempel kommer vi att använda RGB.

$r: rgb(255,0,0); // hsl(0,100%,50%)
sek o: rgb(255,128,0); // hsl(32,100%,50%)

Vad jag gillar att göra för att hålla koden kort och lätt att läsa är att använda minst en bokstav för att representera varje färg (till exempel $r för rött). Om du använder mörkare eller ljusare nyanser av en färg, jag lägger till en d innan basen eller flera bokstäver för mörkt eller har en l för ljus. Jag skulle använda $dr för mörkt röda och $lr för ljus röd. Om det finns ett behov av mer än två andra nyanser, då ska jag lägga till ett nummer i slutet för att ange skuggan nivå. Till exempel, $dr1 för mörkt röd, $dr2 för en mörkare röd, och $lr1 för ljus röd, $lr2 efter ett lättare rött. En sådan palett skulle se ut så här (med mörk första, normal nästa, och sista ljus):

$dr1: rgb(224,0,0);
$dr2: rgb(192,0,0);
$r: rgb(255,0,0);
$lr1: rgb(255,48,48);
$lr2: rgb(255,92,92);
Inställning av Skala och Canvas

Vi kommer att använda em enheter för bildens mått så att bilden kan enkelt ändra storlek proportionellt. Eftersom 1em är lika med elementet font storlek, har varje enhet av bilden kommer att justeras i enlighet med detta om de ändras. Låt oss ställa en teckenstorlek på 10px och ange både bredd och höjd till 24em. Enheter av 10px är det enklaste att tänka på eftersom om du mentalt göra matte, du får omedelbart 240 × 240px. Sedan är det bara att se om kanterna på duken är, vi kommer att använda en 1px grå kontur.

$r: rgb(255,0,0); // hsl(0,100%,50%)
sek o: rgb(255,128,0); // hsl(32,100%,50%)

.bild {
background-repeat: no-repeat;
font-size: 10px;
utkast: 1px solid #aaa;
bredd: 24em;
höjd: 24em;
}

Vara medveten om att använda mindre textstorlek, men, webbläsare har en minsta teckenstorlek (för tillgänglighet skäl). Om du ställer in en teckenstorlek 4px och den minsta är 6px, det ska tvingas på 6px.

Dessutom kan du aktivera lyhördhet bara genom att använda calc() och virtuella enheter. Vi kanske kan använda något som calc(10px + 2vmin) om så önskas, men låt oss hålla oss med 10px för nu.

Rita Former

Det roliga börjar här. För att rita en kvadrat som är 8 × 8em i centrum, vi använder en linjär gradient() med två personer av samma färgade stannar.

.bild {
bakgrund:
linear-gradient($r, $r) 50% 50% / 8em 8em;

}

För att forma det till något som mer liknar en trapets, ange en vinkel på 60deg. Samtidigt, låt oss lägga $T för transparent för våra paletten och sedan placera båda stannar för $r $T 63% (rätt innan det nedre högra hörnet blir avskurna).

$T: transparent;

.bild {
bakgrund:
linear-gradient(60deg,$r 63%, $T 63%) 50% 50% / 8em 8em;

}

Inställning båda stannar på samma värde gör den snedställda så skarp som de andra. Om du tittar på det närmare men det verkar vara pixlad ut:

För att korrigera detta, vi något justera en av de hållplatser (av 1% eller ungefär så) så att kanten är slät räcker. Så, låt oss ändra på $r s 63% till 62%.

Detta kommer att vara ett problem med runda kanter som när du arbetar med radiell gradienter, som vi ska se senare. Om du ser detta i en webbläsare annan än Safari, allt ser bra ut även om övergång till ett icke-transparent färg istället (säger orange). Problemet med övergången till öppna i Safari är att du kommer att märka lite av svart foder på den sneda sidan.

Detta beror på att den genomskinliga sökord i Safari är alltid svart öppenhet, och vi ser något svart som följd. Jag önskar verkligen att Apple skulle fixa detta, men de kommer aldrig. För närvarande, låt oss lägga till en ny $redT variabel för röda insyn under $r. Skrot $T som vi använde oss av öppna som vi kommer inte längre att använda den.

$rT: rgba(255,0,0,0); // hsla(0,100%,50%,0)

Så låt oss byta ut öppet med $redT. Detta tar hand om vår Safari problem!

.bild {
bakgrund:
linear-gradient(60deg,$r 62%, $rT 63%) 50% 50% / 8em 8em;

}

Om du har undrat varför vi inte använder hexadecimala färger, Internet Explorer och Edge inte stödja #rgba och #rrggbbaa beteckningarna (japp, hex har haft en alfa-kanal sedan slutet av 2016 om du visste aldrig), och vi vill att detta ska fungera som en cross-browser som möjligt. Vi vill också stanna i överensstämmelse med vårt val av färg format.

Låt oss nu flytta form vertikalt till 20% och rita en orange cirkel som har samma dimensioner. Lägg också till en annan variabel för dess transparenta versionen. För slät kant, lägg i en 1% skillnad mellan den fasta och öppna apelsiner.

$oT: rgba(255,128,0,0); // hsla(32,100%,50%,0)

.bild {
bakgrund:
linear-gradient(60deg,$r 62%, $rT 63%) 50% 20% / 8em 8em,
radial gradient(8em 8em på 50% 80%, $o 49%, $oT 50 procent).

}

För att upprätthålla konsekvens med vår dimensionering, den andra färgen stopp ska vara på 50% istället för 100%.

Positionering Former

Vägen gradienter är placerad är baserat på om enheten är fasta eller som en procentsats. Antag att vi vänder oss både av gradienter i fyrkanter och försök att placera dem hela vägen över div horisontellt.

.bild {
bakgrund:
linear-gradient($r, $r) 24em 20% / 8em 8em,
linear-gradient($o $o) 100% 80% / 8em 8em;

}

Röda torget hamnar helt utanför arbetsytan (se), och den högra sidan av den orange fyrkanten vidrör den andra sidan. Med hjälp av fasta enheter är som att placera helt placerade element eller rita former i HTML5 canvas. Det är sant i den meningen att den utgångspunkt som är längst upp till vänster. När du använder procent och en uppsättning bakgrund storlek, div blir “falska utfyllnad” av halva bakgrund storlek. Samtidigt bakgrunden startpunkt är centrerad (inte att förväxla med bakgrund, ursprung, som det gäller box hörn).

Nu, om vi vände dessa gradienter i radiell gradienter som cirklar och tillämpas samma x-position 24em och 100%, båda hamnar på andra sidan skär den i halvor. Detta beror på att den utgångspunkt är alltid i centrum om vi skriver den bakgrunden så här:

.bild {
bakgrund:
radial gradient(8em 8em på 24em 20%, $r 49%, $rT 50%),
radial gradient(8em 8em på 100% 80%, $o 49%, $oT 50 procent).

}

Om vi skrev om i bakgrunden så att position och storlek efter lutning och används 100% 100% i centrum, kommer de att placeras som den linjära gradienter. Den röda som hamnar utanför, och orange inslag i den högra kanten. Den “falska utfyllnad” uppstår återigen med orange.

.bild {
bakgrund:
radial gradient(100% 100% vid center, $r 49%, $rT 50%) 24em 20% / 8em 8em,
radial gradient(100% 100% vid center, $o 49%, $oT 50%) 100% 80% / 8em 8em;

}

Det finns inget enda korrekt sätt att placera former, men att placera den som en helt eller fast placerad HTML-element, använda fasta enheter. Om du är i behov av ett snabbt sätt att placera en form (med hjälp av position / storlek parametrar) i dead center, 50% är det bästa alternativet i form ursprung kommer att vara dess centrum. Använda 100% om det ska röra mycket på höger sida.

Dimensionering Former

Dimensionering i CSS bakgrunder fungerar som vi förväntar oss, men det är fortfarande påverkad av den typ av enhet som används för position—fast eller procent. Om vi tar vår torg igen och ändra sin bredd och 10em, den röda expanderar till höger, och orange expanderar i sidled.

.bild {
bakgrund:
linear-gradient($r, $r) 12em 20% / 10em 8em,
linear-gradient($o $o) 50% 80% / 10em 8em;

}

Om vi använde em enheter för y-position, formen kommer att växa nedåt eller krympa uppåt efter att byta höjd. Om vi använder en procentsats, så kommer det att expandera både vertikal riktning.

För en stund sedan, vi tittade på två sätt för att rita cirklar med radiell gradienter. Det första sättet är att ange bredd och höjd mellan ( och på och sedan ställning efter att:

.bild {
bakgrund:
radial gradient(8em 8em minst 50%, 50%, $r 49%, $rT 50 procent).

}

Det andra sättet är att använda 100% 100% i mitten och sedan ge den position och storlek:

.bild {
bakgrund:
radial gradient(100% 100% 50% 50%, $r 49%, $rT 50%) 50% 50% / 8em 8em;

}

Dessa metoder både rita cirklar, men kommer att resultera i olika utgångar eftersom:

  1. Det första sättet upptar hela div eftersom det inte fanns någon verklig bakgrund position eller storlek.
  2. Ge en verklig position och storlek för att den andra sätter det en bounding box. Följaktligen, kommer det beter sig precis som en linjär gradient form.

Antag att vi ersatt $rT med $o. Du kommer att se att den orange kommer att täcka vad som var vit eller former under den (om vi lagt till några) för det första sättet. Genom att använda andra sätt, du kommer lätt att märka om den omgivande rutan framgår av den orange.

Dessutom syftet med 100% 100% istället för att använda cirkel eller ellips är att låta cirkeln för att ockupera hela bounding box. Det ger även oss fullständig kontroll över dess dimensioner. På det sättet så kommer det att förbli den samma om du ändrar 50% 50% position till något annat. Om du använder en av de två sökord, kanten av cirkeln stannar endast ca 71% av vägen när centrerad och blir mer påverkade om dess position justeras. Till exempel, här är vad som händer när vi ändrar x-position till 0 för cirkel och ellips:

I det långa loppet, du kan reimagine syntax som radial gradient(bredd höjd på x-y) eller radial gradient(100% 100% på x-i-omgivande rutan y-i-bounding box) x-y / bredd höjd. Om du ritar bara en cirkel eller oval, kan du förenkla koden med det första sättet. Om att rita en del av en cirkel eller en del av en ring, sedan det andra sättet kommer in i bilden. Det kommer att bli många ansökningar som i de exempel som vi kommer att skapa nästa.

Exempel

Redo att dra något på riktigt nu? Vi kommer att gå igenom tre exempel, steg för steg. De två första kommer att vara statiska—en med massor av halv-cirklar och andra som arbetar med vissa rundade rektanglar. Det sista exemplet kommer att bli mindre, men fokuserade på animation.

Statisk Bild

Detta parasoll kommer att bli vårt första statisk bild:

Vi kommer att använda en palett med röd ($r $rT), vit ($w $wT), orange ($o $oT), och mörkt orange ($att göra och $doT).

$r: rgb(255,40,40);
$rT: rgba(255,40,40,0);

$w: rgb(240,240,240);
$wT: rgba(240,240,240,0);

sek o: rgb(255,180,70);
$oT: rgba(255,180,70,0);

$att göra: rgb(232,144,0);
$doT: rgba(232,144,0,0);

Låt oss ställa upp vår ritning område av 30 × 29em.

.parasoll {
// bakgrunden för att gå här
background-repeat: no-repeat;
font-size: 10px;
utkast: 1px solid #aaa;
bredd: 30em;
höjd: 29em;
}

Ovanför background-repeat, vi kommer att börja med att rita delar av parasoll. Lägg först till gradienter att göra upp stången (eftersom varken överlappar varandra, botten-till-topp ordning spelar ingen roll på denna punkt):

.parasoll {
bakgrund:
// 1
radial gradient(200% 200% 100% 100%, $do 49%, $prick 50%) 14em 0 / 1em 1em,
radial gradient(200% 200% 0% 100%, $o 49%, $oT 50%) 15em 0 / 1em 1em,
// 2
linear-gradient(90deg, $att göra 50%, $o 50%) 14em 1em / 2em 25em,
// 3
radial gradient(100% 200% 50% 0, $oT 0.95 em, $o 1em, $1.95 o em, $att göra 2em, $att göra 2.95 em, $doT 3em) 14em 26em / 6em 3em,
// 4
radial gradient(200% 200% 100% 100%, $o 49%, $oT 50%) 18em 25em / 1em 1em,
radial gradient(200% 200% 0% 100%, $do 49%, $prick 50%) 19em 25em / 1em 1em;

}

  1. Att rita upp varje sida av toppen av stången, vi använde fjärdedelar av en cirkel som är 1 × 1em. Att få dem att ockupera deras bounding boxes, vi använde cirklar som är dubbelt så stor (200% 200%) placerad längst ned till höger och längst ner till vänster. Vi kan också använda sökord par som rätt eller botten vänster botten, men det är kortare att använda procent medel. Märker 1% skillnader mellan de stannar för att säkerställa jämnhet.
  2. För lång del, använde vi en lång rektangel med ett abrupt mörk orange-orange. Det finns ingen anledning för en relativ liten lucka eftersom vi inte jobbar med en kurva eller vinkling.
  3. Denna del av polen är lite svårare att dra än den andra, eftersom vi måste underhålla 2em diameter. Att dra denna båge, använder vi en låda med 6 × 3em så att det är en 2em utrymme mellan ändarna som också 2em. Sedan använder vi en radiell övertoning på mitten där varje stopp uppstår 1em varje (och sprids med 0,05 em för jämnhet).
  4. De två sista är precis som den första förutom att de är placerade vid den högra änden av bågen så att de smidigt passform. Även färgerna swap platser.

Sedan över den tidigare gradienter, lägg till följande från botten till toppen för att dra den övre delen av paraply utan spetsiga ändar:

.parasoll {
bakgrund:
radial gradient(100% 200% 50% 100%, $r 50%, $rT 50.25%) 50% 1.5 em / 9em 12em,
radial gradient(100% 200% 50% 100%, $w 50%, $wT 50.25%) 50% 1.5 em / 21em 12em,
radial gradient(100% 200% 50% 100%, $r 50%, $rT 50.25%) 50% 1.5 em / 30em 12em,

}

För att rita en halv cirklar som gör upp denna del, använde vi en gradient storlek av 100% 200%, vilket innebär att varje diameter passar in i dess bakgrund bredd men har dubbelt så hög höjd och centrerad i botten. Genom att beställa dem nerifrån och upp så att den största är på botten och den lägsta på toppen, vi få de kurvor vi vill.

Som vår stack gradienter växer längre, det kommer att bli svårt efter ett tag för att identifiera vilken bakgrund eller grupp av bakgrunder motsvarar vad en del av bilden. Så för att göra det lättare att pin ner dem, kan vi dela upp dem i grupper leds av en kommentar som beskriver vad varje grupp är till för. Just nu, vi har delat stack till grupper för toppen av parasoll och stolpen.

.parasoll {
bakgrund:
/* toppen */
radial gradient(100% 200% 50% 100%, $r 50%, $rT 50.25%) 50% 1.5 em / 9em 12em,
radial gradient(100% 200% 50% 100%, $w 50%, $wT 50.25%) 50% 1.5 em / 21em 12em,
radial gradient(100% 200% 50% 100%, $r 50%, $rT 50.25%) 50% 1.5 em / 30em 12em,

/* pol */
radial gradient(200% 200% 100% 100%, $do 49%, $prick 50%) 14em 0 / 1em 1em,
radial gradient(200% 200% 0% 100%, $o 49%, $oT 50%) 15em 0 / 1em 1em,
linear-gradient(90deg, $att göra 50%, $o 50%) 14em 1em / 2em 25em,
radial gradient(100% 200% 50% 0, $oT 0.95 em, $o 1em, $1.95 o em, $att göra 2em, $att göra 2.95 em, $doT 3em) 14em 26em / 6em 3em,
radial gradient(200% 200% 100% 100%, $o 49%, $oT 50%) 18em 25em / 1em 1em,
radial gradient(200% 200% 0% 100%, $do 49%, $prick 50%) 19em 25em / 1em 1em;

}

Då, i mellan toppen och pole, vi ska lägga upp nästa bit av bakgrund att göra spetsiga ändar. För att bestämma bredden på varje segment, vi måste få avståndet mellan varje punkt där röda och vita möts. De måste alla lägga till upp till 30em.

Börjar med den vita och smalaste röda halvan cirklar, vi subtraherar den röda bredd av 9em från vit bredd av 21em och dividera resultatet med 2 för att få den bredd av två vita segment (punkt “b” i figur). Så, skulle resultatet bli 6em b = (21 – 9) / 2 = 6 ). Sedan mitten röda segment skulle vara 9em (21 – (6 + 6) = 9). Vad vi har kvar nu är den yttre röda segment (punkt “a” i figur). Subtrahera summan av vad vi har nu är från bredd av större red en halv cirkel och dela resultatet med 2. Det skulle vara att göra värdet av punkt ett: (30em – (6 + 6 + 9)) / 2 = 4.5 em.

.parasoll {
bakgrund:

/* spetsiga ändar */
radial gradient() 0 13.5 em / 4.5 em 3em,
radial gradient() 4.5 em 13.5 em / 6em 3em,
radial gradient() 50% 13.5 em / 9em 3em,
radial gradient() 19.5 em 13.5 em / 6em 3em,
radial gradient() 25.5 em 13.5 em / 4.5 em 3em,

}

För att rita en halv kretsar som liknar hur vi ritade upp en del, börjar vi med öppen motsvarighet i färg för varje form så att de liknar arc broar. Vi kommer även att lägga till en extra 5% för varje lutning bredd (inte bakgrunden rutan bredd), så att varje punkt som bildas av intilliggande bakgrund inte alltför vass och tunn.

.parasoll {
bakgrund:

/* spetsiga ändar */
radial gradient(105% 200% 50% 100%, $rT 49%, $r 50%) 0 13.5 em / 4.5 em 3em,
radial gradient(105% 200% 50% 100%, $wT 49%, $w 50%) 4.5 em 13.5 em / 6em 3em,
radial gradient(105% 200% 50% 100%, $rT 49%, $r 50%) 50% 13.5 em / 9em 3em,
radial gradient(105% 200% 50% 100%, $wT 49%, $w 50%) 19.5 em 13.5 em / 6em 3em,
radial gradient(105% 200% 50% 100%, $rT 49%, $r 50%) 25.5 em 13.5 em / 4.5 em 3em,

}

Slutligen, kommer du inte längre behöver det 1px solid #aaa kontur. Vårt parasoll är klar!

Se Pennan Parasoll av Jon Kantner (@jkantner) på CodePen.

Något Med Rundade Rektanglar

Nästa exempel kommer att vara en gammal iPhone-modell, där det finns mer information än nyare modeller. Den sak om detta är de två rundade rektanglar, som är utanför och mitten av hem-knappen.

Paletten kommer att bestå av svarta ($bk och $bkT) för home-knappen kanten, mörkgrå ($dg och$dgT) för kroppen, grå ($g $gT) för kamera och högtalare, ljus grå ($lg och $lgT) för utanför gränsen, blå ($bl och $blT) för kameralinsen, och en mycket mörk lila ($p $pT) för skärmen.

$bk: rgb(10,10,10);
$bkT: rgba(10,10,10,0);

$gd: rgb(50,50,50);
$dgT: rgba(50,50,50,0);

$g: rgb(70,70,70);
$gT: rgba(70,70,70,0);

$lg: rgb(120,120,120);
$lgT: rgba(120,120,120,0);

$bl: rgb(20,20,120);
$blT: rgba(20,20,120,0);

$p: rgb(25,20,25);
$pT: rgba(25,20,25,0);

Låt oss ställa upp vår canvas på 20 × 40em och använda samma teckenstorlek som vi använde för parasoll, 10px:

.iphone {
// går här bakgrunden
background-repeat: no-repeat;
font-size: 10px;
utkast: 1px solid #aaa;
bredd: 20em;
höjd: 40em;
}

Innan vi börjar dra vår första rundad rektangel, vi måste tänka på vårt border radie, som kommer att vara 2em. Också, vi vill lämna lite utrymme till vänster för att låsa strömbrytaren och volymknapparna, som kommer att vara med 0,25 em. Av denna anledning, rektangeln kommer att 19.75 × 40em. Med tanke på den 2em border radie, vi kommer att behöva två linjära gradienter korsande varandra. Man måste ha en bredd 15,75 em (19.75 em – 2 × 2), och den andra måste ha en höjd av 36em (40em – 2 × 2). Position den första 2.25 em från vänster och sedan den andra 0.25 em från vänster och 2em från toppen.

.iphone {
bakgrund:
/* kropp */
linear-gradient() 2.25 em 0 / 15.75 em 40em,
linear-gradient() 0.25 em 2em / 19.75 em 36em;

}

Eftersom den ljusgrå gränsen kommer att vara 0,5 em tjock, låt oss göra varje lutning sluta omedelbart växla från ljusgrå ($lg) till mörkt grå ($dg) och vice versa vid 0,5 em och 0,5 em innan slutet (40em – 0.5 = 39.5 em för första gradient, 19.75 em – 0.5 = 19.25 em för andra). Ange en vinkel på 90deg för det andra för att få det att gå horisontellt.

.iphone {
bakgrund:
/* kropp */
linear-gradient($lg 0.5 em, $dg 0.5 em, $dg 39.5 em, $lg 39.5 em) 2.25 em 0 / 15.75 em 40em,
linear-gradient(90deg, $lg 0.5 em, $dg 0.5 em, $dg 19.25 em, $lg 19.25 em) 0.25 em 2em / 19.75 em 36em;

}

I varje ruta hörnet, vilket framgår av den orange rutan i figur, vi ska placera de rundade kanterna. För att skapa dessa former, vi använder radiell lutningar som är två gånger storleken av deras bounding boxes och ligger i varje hörn. Sätt dem framför kroppen bakgrunder.

.iphone {
bakgrund:
/* hörn */
radial gradient(200% 200% 100% 100%, $dg 1.45 em, $lg 1.5 em, $lg 50%, $lgT 51%) 0.25 em 0 / 2em 2em,
radial gradient(200% 200% 0% 100%, $dg 1.45 em, $lg 1.5 em, $lg 50%, $lgT 51%) 18em 0 / 2em 2em,
radial gradient(200% 200% 100% 0%, $dg 1.45 em, $lg 1.5 em, $lg 50%, $lgT 51%) 0.25 em 38em / 2em 2em,
radial gradient(200% 200%, 0%, 0%, $dg 1.45 em, $lg 1.5 em, $lg 50%, $lgT 51%) 18em 38em / 2em 2em,

}

För att få 0,5 em-tjocka ljus grå slutar tänka på där lutningen börjar och sedan göra matten. Eftersom det är ljust grått, som är i slutet, vi subtrahera 0.5 em från 2em att korrekt placera första stopp. För jämnhet, som vi tar ut en liten bit från de första 1,5 em och tillsätt 1% till de andra 50%, så att de runda kanter smälter in med platta kanter.

Om vi nu förstoras bilden genom att ändra teckenstorleken till 40 bildpunkter eller mer, vi märker sömmar mellan runda och platta kanter (inringat i orange):

Eftersom de verkar vara så små, vi kan enkelt uppdatera dem genom att gå tillbaka till kroppen bakgrunder och något att ändra lutning stannar så länge allt ser fortfarande rätt när du ändrar teckenstorlek tillbaka till 10px.

.iphone {
bakgrund:
/* kropp */
linear-gradient($lg 0.5 em, $dg 0.55 em, $dg 39.5 em, $lg 39.55 em) 2.25 em 0 / 15.75 em 40em,
linear-gradient(90deg, $lg 0.5 em, $dg 0.55 em, $dg 19.175 em, $lg 19.25 em) 0.25 em 2em / 19.75 em 36em;

}

Sedan i en linjär gradient, vi kommer att lägga till lås strömbrytaren och volymknapparna för att fylla 0,25 em utrymme på vänster. Om en 1px utrymme kommer att hända mellan knapparna och kropp, kan vi lägga till en liten blöda på 0,05 em i bakgrunden bredd (gör det med 0,3 em) så att den inte sticker ut i den mörka grå.

.iphone {
bakgrund:
/* volymknappar */
linear-gradient($lgT 5em, $lg 5em, $lg 7.5 em, $lgT 7.5 em, $lgT 9.5 em, $lg 9.5 em, $lg 11em, $lgT 11em, $lgT 13em, $lg 13em, $lg 14.5 em, $lgT 14.5 em) 0 0 / 0.3 em 100%,

}

Det ser ut som vi kunde ha använt tre ljus grå-till-ljus grå gradienter, men eftersom det var möjligt, endast en behövdes. Det är bara massor av plötsliga övergångar mellan transparenta och opaka ljus grå kör nedåt.

Nästa, låt oss lägga till kanten på home-knappen samt platt kanterna på torget inne i det. Nu torget inne hem-knappen kommer att vara 1,5 × 1.5 em och följer i princip samma förfarande som kroppen: två korsande linjära gradienter och radialer att fylla i hörnen. Att placera dem horisontellt i centrum, calc() kommer väl till pass. 50% + 0.125 em kommer att vara uttryck; om vi centrerad endast telefonen kroppen, det kommer att bli 0.125 em utrymmen på varje sida. Därför flyttar vi det 0.125 em mer till höger. Samma x-positionering kommer att gälla för de övre två bakgrunder.

.iphone {
bakgrund:
/* hem-knappen */
linear-gradient() calc(50% + 0.125 em) 36.5 em / 0.5 em 1.5 em,
linear-gradient() calc(50% + 0.125 em) 37em / 1.5 em 0.5 em,
radial gradient(3em 3em på calc(50% + 0.125 em) 37.25 em, $bkT 1.25 em, $bk 1.3 em, $bk 49%, $bkT 50%),

}

Liknar hur vi skuggade linjär gradient delar av telefonen kroppen, den stannar ska börja och sluta med ljus grå men med transparent i mitten. Meddelande vi lämnade 0.05 em luckor mellan var och en grå-till-öppen övergång (och vice versa). Precis som hörnen av kroppen, detta för att säkerställa en blandning mellan en runda hörn och platta änden inne.

.iphone {
bakgrund:
/* hem-knappen */
linear-gradient($lg 0.15 em, $lgT 0.2 em, $lgT 1.35 em, $lg 1.35 em) calc(50% + 0.125 em) 36.5 em / 0.5 em 1.5 em,
linear-gradient(90deg, $lg 0.15 em, $lgT 0.2 em, $lgT 1.3 em, $lg 1.35 em) calc(50% + 0.125 em) 37em / 1.5 em 0.5 em,
radial gradient(3em 3em på calc(50% + 0.125 em) 37.25 em, $bkT 1.25 em, $bk 1.3 em, $bk 49%, $bkT 50%),

}

Förresten, eftersom den anger kommer att vara så liten som du har sett tidigare, kan vi bättre se vad vi gör genom att öka teckenstorleken till minst 20px. Det är som med hjälp av zoom-verktyget i ett bildbehandlingsprogram.

Nu för att få hörnen av grå ruta för att exakt där de ska vara, låt oss fokusera på x-position först. Vi börjar med calc(50% + 0.125 em), då kan vi lägga till eller dra ifrån bredden på varje bit, eller ska jag säga torget border radie. Dessa bakgrunder kommer att gå över de tre sista.

.iphone {
bakgrund:
/* hem-knappen */
radial gradient(200% 200% 100% 100%, $lgT 0.3 em, $lg 0.35 em, $lg 0.48 em, $lgT 0.5 em) calc(50% + 0.125 em – 0.5 em) 36.5 em / 0.5 em 0.5 em,
radial gradient(200% 200% 0% 100%, $lgT 0.3 em, $lg 0.35 em, $lg 0.48 em, $lgT 0.5 em) calc(50% + 0.125 em + 0.5 em) 36.5 em / 0.5 em 0.5 em,
radial gradient(200% 200% 100% 0%, $lgT 0.3 em, $lg 0.35 em, $lg 0.48 em, $lgT 0.5 em) calc(50% + 0.125 em – 0.5 em) 37.5 em / 0.5 em 0.5 em,
radial gradient(200% 200%, 0%, 0%, $lgT 0.3 em, $lg 0.35 em, $lg 0.48 em, $lgT 0.5 em) calc(50% + 0.125 em + 0.5 em) 37.5 em / 0.5 em 0.5 em,

}

Då skärmen kommer att vara en 17.25 × 30em rektangel. Precis som delar av hem-knappen, kommer vi horisontellt center den med calc(50% + 0.125 em). Från toppen, det ska vara 5em.

.iphone {
bakgrund:
/* skärmen */
linear-gradient($p $s) calc(50% + 0.125 em) – 5em / 17.25 em 30em,

}

Slutligen, vi kommer att lägga kameran och speaker. Kameran är en enkel 1 × 1 blå-till-grå radial med ingen lust beräkningar. Ren-grå högtalare men kommer att vara lite mer delaktiga. Det kommer att vara ett 5 × 1em rektangel och har en 0,5 em border radie. Att rita, vi först rita en rektangel med den första 4ems av bredd och centrera den med calc(50% + 0.125 em). Då vi använder 0.5 × 1em halvcirklar i vilken lutning positioner är 100% 50% 0% 50%. Det bästa sättet att placera dessa vänster och höger om rektangeln är att använda några nya calc() uttryck. Till vänster, vi kommer att dra ifrån hälften av rektangelns bredd och hälften av en halv cirkel bredd från kroppen center (50% + 0.125 em – 2em – 0.25 em). Rätten kommer att följa samma mönster men med tillägg, så 50% + 0.125 em + 2em + 0.25 em.

.iphone {
bakgrund:
/* kamera */
radial gradient(1em 1em på 6,25 em 2.5 em, $bl 0.2 em, $g 0.21 em, $g 49%, $gT 50%),
/* högtalare */
radial gradient(200% 100% 100% 50%, $g 49%, $gT 50%) calc(50% + 0.125 em – 2em – 0.25 em) 2em / 0.5 em 1em,
radial gradient(200% 100% 0%, 50%, $g 49%, $gT 50%) calc(50% + 0.125 em + 2em + 0.25 em) 2em / 0.5 em 1em,
linear-gradient($g $g) calc(50% + 0.125 em) 2em / 4em 1em,

}

Ta bort den grå kontur runt div, och iPhone är klar!

Se Pennan iPhone av Jon Kantner (@jkantner) på CodePen.

Animerade Bilder

Du kanske tänker att du skulle kunna använda background-position för att animera dessa typer av bilder, men du kan bara göra så mycket. Till exempel, det är omöjligt att animera rotation av en individuell bakgrund av sig själv. I själva verket, background-position animationer brukar inte utföra samt omvandla animationer, så jag rekommenderar det inte.

Att animera en del av en bild på något sätt vi vill, vi kan låta :före eller efter pseudo-element vara ansvarig för den delen. Om vi behöver fler val, då kan vi återgå till flera barn divs, men som inte behöver en för varje liten detalj. För våra animerad bild exemplet kommer vi att skapa denna animerad radar:

Vi drar den statiska delen först, som är allt utom den grå ramen och roterande hand. Innan dess, låt oss leverera våra paletten (observera: Vi behöver inte en $dgnT för $dgn) och bas-kod.

$gn: rgb(0,192,0);
$gnT: rgba(0,192,0,0);
$dgn: rgb(0,48,0);
$gy: rgb(128,128,128);
$gyT: rgba(128,128,128,0);
$bk: rgb(0,0,0);
$bkT: rgba(0,0,0,0);

.radar {
background-repeat: no-repeat;
font-size: 10px;
utkast: 1px solid #aaa;
bredd: 20em;
höjd: 20em;
}

Eftersom den här bilden kommer att vara helt runda, vi kan säkert lägga till en kantlinje radie av 50%. Sedan kan vi använda ett upprepande radiell övertoning för att rita ringar—ca 1/3 sätt från varandra.

.radar {
bakgrund:
/* ringar */
upprepa-radial gradient($dgn, $dgn 2.96 em, $gn 3em, $gn 3.26 em, $dgn 3.3 em);
background-repeat: no-repeat;
border-radius: 50%;

}

Observera också den extra $dgn i början. För att upprepa gradienter till start, slut och slinga som förväntat, måste vi ange start färg vid 0 (eller utan 0).

Till skillnad från föregående exempel, vi använder inte calc() för att centrera rader eftersom Internet Explorer kommer att göra det hela tafatt när vi använder en pseudo-element senare. För att rita fyra 0.4 em linjer som korsar varandra i mitten, vet att hälften av linjen bör vara hälften av div i 10em. Så, vi dra ifrån och lägg till hälften av 0.4 (0.4 / 2 = 0.2) på varje sida. Med andra ord, vänster om green bör vara 9.8 em, och den rätten bör vara 10.2 em. För 45deg diagonaler men, vi måste multiplicera 10em med roten ur 2 för att få sina centrum (10 × √2 ≈ 14.14). Det är längden på den längsta sidan av en 10em rätvinklig triangel. Som ett resultat, de sidor av varje diagonal skulle vara ungefär på 13.94 och 14.34 em.

.radar {
bakgrund:
/* linjer */
linear-gradient($gnT 9.8 em, $gn 9.8 em, $gn 10.2 em, $gnT 10.2 em),
linear-gradient(45deg,$gnT 13.94 em, $gn 13.98 em, $gn 14.3 em, $gnT 14.34 em),
linear-gradient(90deg,$gnT 9.8 em, $gn 9.8 em, $gn 10.2 em, $gnT 10.2 em),
linear-gradient(-45deg,$gnT 13.94 em, $gn 13.98 em, $gn 14.3 em, $gnT 14.34 em),

}

För att förhindra pixelering av diagonaler, vi lämnade en liten 0.04 em klyftan mellan grön och transparent grön. Sedan, för att skapa lite ljus, lägga till detta öppet-till-svart radiell övertoning:

.radar {
bakgrund:
/* belysning */
radial gradient(100% 100%, $var, $bk 9.9 em,$bkT 10em),

}

Som fullbordar den statiska delen av radar. Nu ska vi dra den grå ramen och hand i en annan bakgrund stack under :före och lägger till animation. Det finns en anledning till att vi inte inkluderar ram här. Eftersom handen behållare ska passa hela div, vi vill inte att det ska överlappa ram.

Denna pseudo-element skall fylla utrymmet, och för att säkerställa att den stannar kvar i det, låt oss helt position. Vi använder samma border radie så att det stannar runt medan animerade i Safari.

.radar {

position: relative;
&innan {
background-repeat: no-repeat;
border-radius: 50%;
innehåll: “”;
position: absolute;
width: 100%;
höjd: 100%;
}
}

Sedan, för att dra handen, vi gör det en halv storlek av sin behållare och förvara det i det övre vänstra hörnet. Slutligen, på toppen av det, vi drar ram.

.radar {

&innan {
animation: skanna 5s linjär oändlig;
bakgrund:
/* ram */
radial gradient($gyT 9.20 em, $gy 9.25 em, $gy 10em, $gyT 10.05 em),
/* hand */
linear-gradient(45deg, $gnT 6em, $gn) 0 0 / 50% 50%;

}
}

@keyframes scan {
från {
förändra: rotera(0);
}
till {
förändra: rotera(1turn);
}
}

Nu har vår lilla pryl är klar!

Se Pennan Radar av Jon Kantner (@jkantner) på CodePen.

Fördelar (Plus en Nackdel)

Den här metoden för att rita CSS-bilder har flera fördelar. För det första, HTML-kommer att vara mycket lätt jämfört med en rastrerade bildfil. För det andra, det är bra för att ta itu med bilder som är omöjligt att dra sig bra utan hjälp av experimentella egenskaper och Api: er som inte kan få ett brett stöd.

Det är inte att säga att denna metod är bättre än att använda ett överordnat element kapslade med barn för de former. Det finns en nackdel dock. Har du ge upp att kunna markera enskilda figurer med hjälp av webbläsaren dev verktyg. Du måste kommentera och avkommentera en bakgrund till att identifiera vilka det är. Så länge du gruppen och etikett varje bit av bakgrund, kan du hitta att viss bakgrund snabbare.

Slutsats

I ett nötskal, metoden för teckning av CSS-bilder som vi har i det här inlägget ger oss möjlighet att:

  1. Ställ upp en palett bestående av variabler för färger.
  2. Inaktivera bakgrunden upprepa, ställa in en skala med font-size, och en duk bredd och höjd i em-enheter för målet element.
  3. Använd en temporär beskriva att visa kanter som vi arbetar.
  4. Dra varje form från botten till toppen, eftersom bakgrunder återges i den ordningen. Bakgrunden syntax för varje form följer bildens position / storlek (med eller utan position och storlek).

Det finns en hel del att tänka utanför boxen kommer på, liksom experiment för att få önskat resultat. Tre exempel, vi skapade var precis tillräckligt för att demonstrera konceptet. Vi har tittat på hur vi för varje bakgrunden, ritning delar av cirklar, rundade rektanglar, och något att justera lutning stannar för att jämna till kanter. För att lära dig mer, är du välkommen att analysera och studera andra exempel som jag har gjort i detta CodePen samling!

Jetpack WordPress plugin som körs på denna webbplats, driver inte bara relaterade inlägg nedan, men säkerhet och backup, Wiki-stöd, sök på sajten, kommentera form, sociala nätverk, och mycket mer!