CSS og nett

WebGL-gradienter og shadere, forklart for designere

Noen gradienter på nettet driver, gløder og skimrer på en måte ingen bilder eller CSS-regler kan. De er shadere. Slik fungerer de, med ord en designer kan bruke.

GradientlyVerifisert Gradiently-konto··7 min lesetid
Omslag: Thistle Mosaic · GR·2BAQ·CR

Kortversjonen

  • En WebGL-gradient tegnes av en shader: et lite program som kjører på grafikkbrikken og bestemmer fargen på hver piksel, ofte mange ganger i sekundet.
  • Fordi en shader regner ut farge fra matematikk i stedet for å lese et lagret bilde, kan den legge til bevegelse, støy, korn og lys i enhver størrelse uten at filen blir større.
  • Shadergradienter koster mer å kjøre enn CSS-gradienter, så en god en tar pause når den er utenfor skjermen, respekterer redusert bevegelse og har en enkel CSS-reserve.
  • Bruk CSS til statiske overganger og enkel bevegelse, og grip til en shader når teksturen, dybden eller bevegelsen er poenget med designet.
På denne siden

En WebGL-gradient er en gradient nettleseren din maler med en shader: et kort program som kjører på grafikkbrikken (GPU-en) og svarer på ett spørsmål for hver piksel på skjermen, «hvilken farge har du akkurat nå?» En CSS-gradient er en fast oppskrift av farger og posisjoner. En shader er en formel, så den kan bøye, gi korn, gløde og flytte fargen, og gjøre det igjen seksti ganger i sekundet, uten at noe bilde lastes ned.

Du trenger ikke å skrive shadere for å designe med dem, men når du vet hva de kan og ikke kan, er det lettere å gi en utvikler en brief, vurdere et verktøy og avgjøre når en vanlig CSS-gradient er det bedre valget.

Hva en shader er, med enkle ord

WebGL er nettleserens måte å snakke med GPU-en på, og hver WebGL-tegning bruker to typer shader. Vertex-shaderen plasserer former, og for en gradient i fullskjerm er det bare ett rektangel som dekker lerretet. Fragment-shaderen gjør det interessante arbeidet: den kjører én gang per piksel, mottar pikselens posisjon og gjeldende tid, og returnerer en farge.

Fordi GPU-en kjører tusenvis av disse små programmene parallelt, blir en formel som ville vært treg i vanlig kode, billig nok til å tegnes på nytt for hvert bilde. Her er en komplett fragment-shader for en gradient med tre farger der grensen svaier forsiktig over tid, med en linje korn på toppen.

text
#version 300 es
precision highp float;

uniform vec2 u_resolution;   // canvas size in pixels
uniform float u_time;        // seconds since start
out vec4 outColor;

void main() {
  vec2 uv = gl_FragCoord.xy / u_resolution;   // 0 to 1 across the canvas

  vec3 night  = vec3(0.07, 0.04, 0.18);  // #120a2e
  vec3 violet = vec3(0.49, 0.23, 0.93);  // #7c3aed
  vec3 coral  = vec3(0.98, 0.45, 0.45);  // #fa7373

  // A slow wave bends the blend so the colours drift.
  float wave = sin(u_time * 0.3 + uv.x * 3.0) * 0.08;
  float t = clamp(uv.y + wave, 0.0, 1.0);

  vec3 color = mix(night, violet, smoothstep(0.0, 0.6, t));
  color = mix(color, coral, smoothstep(0.55, 1.0, t));

  // Fine grain: a different random value per pixel, per frame.
  float n = fract(sin(dot(gl_FragCoord.xy + u_time, vec2(12.9898, 78.233))) * 43758.5453);
  color += (n - 0.5) * 0.04;

  outColor = vec4(color, 1.0);
}
En fragment-shader for WebGL2 i GLSL. smoothstep mykner hver overgang, sinusbølgen flytter grensen, og de siste linjene legger til korn som også skjuler striper.
De tre fargene i shaderen. GLSL skriver farge som 0 til 1 per kanal, så #7c3aed blir 124, 58 og 237 delt på 255.

Hvordan en shadergradient skiller seg fra en CSS-gradient

En CSS-gradient er deklarativ: du lister opp farger og posisjoner, og nettleseren maler dem. Det er det riktige verktøyet det meste av tiden. En shader er prosedyrisk: du beskriver hvordan fargen skal oppføre seg, og matematikken lager den. Den forskjellen viser seg i hva hver av dem kan, og hva hver av dem koster.

AspektCSS-gradientShadergradient
Defineres avFarger, stopp og en retningEn formel som kjøres per piksel
BevegelseFlytting av posisjon, størrelse eller animerte egendefinerte egenskaperAlt du kan uttrykke i matematikk, hvert bilde
Tekstur og kornTrenger et ekstra lag, som SVG-støyInnebygd, og det kan bevege seg
Kostnad ved kjøringSvært lav når den først er maltHolder GPU-en opptatt mens den animerer
Fungerer uten JavaScriptJaNei: et skript setter opp lerretet
Fungerer i e-postDelvis, avhengig av klientenNei
Ingen av dem er bedre generelt. Hver vinner på hver sin jobb.
CSS-reservenlinear-gradient(180deg, #120a2e 0%, #4c1d95 40%, #7c3aed 62%, #fa7373 100%)
Den samme paletten som en stillestående CSS-gradient. Hver shaderbakgrunn bør leveres med en slik reserve, vist før shaderen starter og hver gang den ikke kan kjøre.

Hvorfor shadergradienter føles levende

Tre teknikker gjør det meste av arbeidet, og du kommer til å høre utviklere nevne dem. Støy er jevn tilfeldighet: i stedet for en rett overgang følger fargen et landskap av myke åser, og derfor ser shadergradienter organiske ut og ikke geometriske. Domeneforvrengning mater støy tilbake i seg selv, så fargen folder seg og virvler som blekk i vann. Tid skyver hele landskapet av gårde, noe som gjør et stillestående felt til en drift.

  • Korn kan genereres per piksel og per bilde, så det skimrer som film i stedet for å ligge stille som en tekstur lagt på toppen. Se kornete gradienter.
  • Lys kan etterlignes med noen få linjer: et høylys som følger støyen, leses som glans på silke eller glass.
  • Oppløsning er gratis. Formelen kjører i den størrelsen skjermen har, så en shadergradient forblir skarp på en mobil og på en 4K-skjerm med samme kode.
  • Striper er lettere å slå, fordi shaderen kan legge til litt dither før fargen rundes av til 8 biter. Striper i gradienter forklarer hvorfor det betyr noe.

Bruk CSS når

  • Gradienten står stille, eller beveger seg på én enkel måte
  • Den ligger bak mye tekst på en lang side
  • Den må fungere med skript slått av, eller i e-post
  • Du trenger den på én kodelinje

Bruk en shader når

  • Bevegelsen eller teksturen er poenget med designet
  • Det er ett hero-område, ikke hver seksjon
  • Du vil ha korn, glans eller flyt som CSS ikke kan etterligne
  • Du kan levere en CSS-reserve og en pause

Kostnaden ved en WebGL-bakgrunn i bevegelse

En shader som animerer, holder GPU-en i arbeid så lenge den er på skjermen. På en stasjonær maskin merkes det knapt. På en eldre mobil kan det bety varme hender, et batteri som tappes, og en side som ruller mindre jevnt. Kostnadene skalerer med antall piksler og hvor kompleks formelen er, så en shader i fullskjerm på en skjerm med høy tetthet er det tyngste tilfellet. Gjør gradienter et nettsted tregere tar for seg hvordan du måler det.

  1. 1

    Vis CSS-reserven først

    Mal den stillestående gradienten umiddelbart, og ton så lerretet inn når shaderen har tegnet sitt første bilde. Ingen skal se en tom boks.

  2. 2

    Sjekk at WebGL er tilgjengelig

    Noen nettlesere, enheter og personverninnstillinger slår det av. Hvis konteksten ikke kan opprettes, beholder du reserven.

  3. 3

    Respekter redusert bevegelse

    Hvis den besøkende ber om mindre bevegelse, tegner du ett bilde og stopper. Redusert bevegelse forklarer innstillingen.

  4. 4

    Ta pause når den ikke kan ses

    Stopp animasjonsløkken når lerretet ruller ut av syne eller fanen er skjult.

  5. 5

    Tegn i en fornuftig oppløsning

    Myke gradienter trenger sjelden hver enhetspiksel. Å tegne i halv oppløsning og la nettleseren skalere opp kan kutte arbeidet mye, for en uskarphet du ikke kan se forskjell på.

js
const canvas = document.querySelector('#hero-canvas')
const gl = canvas.getContext('webgl2')
const still = matchMedia('(prefers-reduced-motion: reduce)').matches
let visible = true

if (!gl) {
  canvas.remove() // the CSS gradient behind it stays
} else {
  new IntersectionObserver(([entry]) => {
    visible = entry.isIntersecting
  }).observe(canvas)

  const frame = (ms) => {
    if (visible && !document.hidden) draw(gl, ms / 1000) // your draw call
    if (!still) requestAnimationFrame(frame)
  }
  requestAnimationFrame(frame)
}
Sikkerhetsnettene på noen få linjer: en reserve når WebGL mangler, bare ett bilde ved redusert bevegelse, og ingen tegning utenfor skjermen eller i en skjult fane.

Som referanse dokumenterer WebGL API på MDN hvert kall som brukes her, og caniuse følger støtten for WebGL2 på tvers av nettlesere.

Designe en shadergradient: hva du bør ha med i briefen

Du kan regissere en shader uten å lese GLSL. Gi en brief slik du ville gjort for et materiale, ikke en fargeprøve. Oppgi grunnfargen og de tre til fem fargene som lever på den, i hex. Beskriv strukturen: myke dammer, lange bånd, foldet silke. Oppgi farten i sekunder per syklus i stedet for «sakte», for sakte betyr ulike ting for ulike folk. Si hvor mye korn, og om det beveger seg. Si til slutt hvor teksten skal stå, så den mest urolige delen av feltet holder seg unna den.

Hvordan Gradiently tegner Marks med shadere

Marks i Gradiently er shadergradienter. Hver Mark er en oppskrift av farger, opptil tre stablede materialer, lys, korn og bevegelse, og studioet tegner den live med WebGL2 bak det du designer. Fordi den beregnes og ikke lagres, tegnes den samme Marken skarpt i alle plattformstørrelsene og beveger seg når du eksporterer en video i loop. Tegnemotoren vet også hvor ordene dine er, så den kan flytte den roligste delen av feltet bak dem. Hva er en Mark forklarer hele oppskriften.

Thistle Mosaic

GR·2BAQ·CR

Thistle Mosaic

Se denne Marken
En Mark er en shaderoppskrift med et navn, en kode og én eier. Siden dens viser den tegnet live.

Spørsmål folk stiller

Hva er en WebGL-gradient?

Det er en gradient tegnet av en shader, et lite program som kjører på grafikkbrikken og beregner fargen på hver piksel. Fordi den er en formel, kan den bevege seg, legge til korn og tegnes i enhver størrelse.

Er en shadergradient dårlig for ytelsen?

En stillestående eller pauset shader koster lite, men en som animerer, holder GPU-en opptatt mens den er på skjermen. Sett den på pause når den er ute av syne, tegn i en fornuftig oppløsning og behold en CSS-reserve.

Kan jeg lage en shadergradient uten å kode?

Ja. Flere designverktøy genererer shaderbakgrunner fra kontroller, og Forge i Gradiently bygger Marks, som er shadergradienter, fra en setning eller kontroll for kontroll.

Respekterer shadergradienter innstillinger for redusert bevegelse?

Bare hvis de er bygget for det. Sjekk mediespørringen prefers-reduced-motion i JavaScript, og tegn ett enkelt stillbilde når den er satt.

Hva er GLSL?

GLSL er shaderspråket WebGL bruker. Fragment-shadere skrevet i det bestemmer fargen på hver piksel, og nettleseren kompilerer dem for grafikkbrikken.

Del denne guiden

Skrevet av GradientlyVerifisert Gradiently-konto

Teamet bak Gradiently, et designverktøy bygget rundt Marks: levende gradienter som gjør at alt du designer ser ut som ditt.

Se profilen vår