Kortversionen
- En WebGL-gradient ritas av en shader: ett litet program som körs på grafikchippet och avgör färgen på varje pixel, ofta många gånger i sekunden.
- Eftersom en shader räknar ut färg ur matematik i stället för att läsa en lagrad bild kan den lägga till rörelse, brus, korn och ljus i vilken storlek som helst utan att filen blir större.
- Shadergradienter kostar mer att köra än CSS-gradienter, så en bra sådan pausar när den är utanför skärmen, respekterar minskad rörelse och har en enkel CSS-reserv.
- Använd CSS för statiska övergångar och enkel rörelse, och ta till en shader när texturen, djupet eller rörelsen är poängen med designen.
På den här sidan
En WebGL-gradient är en gradient som din webbläsare målar med en shader: ett kort program som körs på grafikchippet (GPU:n) och svarar på en fråga för varje pixel på skärmen, ”vilken färg har du just nu?” En CSS-gradient är ett fast recept av färger och positioner. En shader är en formel, så den kan böja, ge korn åt, låta glöda och flytta färgen, och göra om det sextio gånger i sekunden, utan att någon bild laddas ner.
Du behöver inte skriva shaders för att designa med dem, men att veta vad de kan och inte kan hjälper dig att instruera en utvecklare, bedöma ett verktyg och avgöra när en vanlig CSS-gradient är det bättre valet.
Vad en shader är, med enkla ord
WebGL är webbläsarens sätt att tala med GPU:n, och varje WebGL-ritning använder två sorters shader. Vertexshadern placerar former; för en gradient i helskärm är det bara en rektangel som täcker duken. Fragmentshadern gör det intressanta jobbet: den körs en gång per pixel, tar emot pixelns position och den aktuella tiden och returnerar en färg.
Eftersom GPU:n kör tusentals av de här små programmen parallellt blir en formel som skulle vara långsam i vanlig kod billig nog att rita om varje bildruta. Här är en komplett fragmentshader för en trefärgsgradient vars gräns svajar mjukt över tid, med en rad korn ovanpå.
#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);
}smoothstep mjukar upp varje övergång, sinusvågen flyttar gränsen och de sista raderna lägger till korn som också döljer bandning.Hur en shadergradient skiljer sig från en CSS-gradient
En CSS-gradient är deklarativ: du listar färger och positioner, och webbläsaren målar dem. Det är rätt verktyg för det mesta. En shader är procedurell: du beskriver hur färg ska bete sig, och matematiken producerar den. Den skillnaden syns i vad var och en kan göra och vad var och en kostar.
| Aspekt | CSS-gradient | Shadergradient |
|---|---|---|
| Definieras av | Färger, stopp och en riktning | En formel som körs per pixel |
| Rörelse | Flyttad position, storlek eller animerade egna egenskaper | Allt du kan uttrycka i matematik, varje bildruta |
| Textur och korn | Behöver ett extra lager, som SVG-brus | Inbyggt, och det kan röra sig |
| Kostnad att köra | Mycket låg när den väl är målad | Håller GPU:n sysselsatt medan den animeras |
| Fungerar utan JavaScript | Ja | Nej: ett skript ställer in duken |
| Fungerar i mejl | Delvis, beroende på klienten | Nej |
linear-gradient(180deg, #120a2e 0%, #4c1d95 40%, #7c3aed 62%, #fa7373 100%)Därför känns shadergradienter levande
Tre tekniker gör det mesta av jobbet, och du kommer att höra utvecklare nämna dem. Brus är mjuk slumpmässighet: i stället för en rak övergång följer färgen ett landskap av mjuka kullar, vilket är varför shadergradienter ser organiska ut snarare än geometriska. Domain warping matar tillbaka brus i sig självt, så att färgen viks och virvlar som bläck i vatten. Tid glider hela landskapet framåt, vilket förvandlar ett stilla fält till en drift.
- Korn kan genereras per pixel och per bildruta, så att det skimrar som film i stället för att sitta stilla som en textur lagd ovanpå. Se korniga gradienter.
- Ljus kan fejkas med några rader: en högdager som följer bruset läses som glans på siden eller glas.
- Upplösning är gratis. Formeln körs i den storlek skärmen har, så en shadergradient förblir skarp på en telefon och på en 4K-skärm med samma kod.
- Bandning är lättare att slå, eftersom shadern kan lägga till lite dither innan färgen avrundas till 8 bitar. Gradientbandning förklarar varför det spelar roll.
Använd CSS när
- Gradienten är stilla, eller rör sig på ett enkelt sätt
- Den ligger bakom mycket text på en lång sida
- Den måste fungera med skript avstängda, eller i mejl
- Du behöver den på en rad kod
Använd en shader när
- Rörelsen eller texturen är poängen med designen
- Det är ett hero-område, inte varje sektion
- Du vill ha korn, glans eller flöde som CSS inte kan fejka
- Du kan ge en CSS-reserv och en paus
Kostnaden för en rörlig WebGL-bakgrund
En shader som animeras håller GPU:n igång så länge den syns på skärmen. På en dator märks det knappt. På en äldre telefon kan det betyda varma händer, ett batteri som töms och en sida som scrollar mindre mjukt. Kostnaderna växer med antalet pixlar och formelns komplexitet, så en shader i helskärm på en skärm med hög täthet är det tyngsta fallet. Gör gradienter en webbplats långsammare tar upp hur du mäter det.
- 1
Visa CSS-reserven först
Måla den stillastående gradienten direkt och tona sedan in duken när shadern har ritat sin första bildruta. Ingen ska se en tom ruta.
- 2
Kontrollera att WebGL finns
Vissa webbläsare, enheter och integritetsinställningar stänger av det. Om kontexten inte kan skapas, behåll reserven.
- 3
Respektera minskad rörelse
Om besökaren ber om mindre rörelse, rita en bildruta och stanna. Minskad rörelse förklarar inställningen.
- 4
Pausa när den inte syns
Stoppa animationsloopen när duken scrollar ut ur bild eller fliken är dold.
- 5
Rendera i en rimlig upplösning
Mjuka gradienter behöver sällan varje enhetspixel. Att rita i halv upplösning och låta webbläsaren skala upp kan minska arbetet mycket för en suddighet du inte kan skilja från originalet.
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)
}Som referens dokumenterar WebGL API på MDN varje anrop som används här, och caniuse följer stödet för WebGL2 i olika webbläsare.
Designa en shadergradient: vad du ska ange
Du kan styra en shader utan att läsa GLSL. Instruera den som du skulle instruera ett material, inte ett färgprov. Ange bottenfärgen och de tre till fem färger som lever på den, i hex. Beskriv strukturen: mjuka pooler, långa band, veckat siden. Ange farten i sekunder per cykel i stället för ”långsam”, eftersom långsam betyder olika saker för olika människor. Säg hur mycket korn, och om det rör sig. Säg till sist var texten ska sitta, så att fältets livligaste del hålls borta från den.
Så ritar Gradiently Marks med shaders
Marks i Gradiently är shadergradienter. Varje Mark är ett recept av färger, upp till tre staplade material, ljus, korn och rörelse, och Studion ritar den live med WebGL2 bakom allt du designar. Eftersom den räknas ut i stället för att lagras renderas samma Mark skarpt i vilken plattformsstorlek som helst och rör sig när du exporterar en loopvideo. Renderaren vet också var dina ord finns, så den kan flytta fältets lugnaste del bakom dem. Vad är en Mark förklarar receptet i sin helhet.

GR·2BAQ·CR
Thistle Mosaic
Se den här MarkenVanliga frågor
Vad är en WebGL-gradient?
Det är en gradient ritad av en shader, ett litet program som körs på grafikchippet och räknar ut färgen på varje pixel. Eftersom den är en formel kan den röra sig, lägga till korn och renderas i vilken storlek som helst.
Är en shadergradient dålig för prestandan?
En stillastående eller pausad shader kostar lite, men en som animeras håller GPU:n sysselsatt medan den syns på skärmen. Pausa den när den är utanför bild, rita i en rimlig upplösning och behåll en CSS-reserv.
Kan jag göra en shadergradient utan att koda?
Ja. Flera designverktyg genererar shaderbakgrunder från reglage, och Gradiently Forge bygger Marks, som är shadergradienter, av en mening eller reglage för reglage.
Respekterar shadergradienter inställningar för minskad rörelse?
Bara om de är byggda för det. Kontrollera mediefrågan prefers-reduced-motion i JavaScript och rita en enda stillbildsruta när den är satt.
Vad är GLSL?
GLSL är det shaderspråk WebGL använder. Fragmentshaders skrivna i det avgör färgen på varje pixel, och webbläsaren kompilerar dem för grafikchippet.
Skriven av Gradiently
Teamet bakom Gradiently, ett designverktyg byggt kring Marks: levande gradienter som får allt du gör att kännas som ditt.
Se vår profil


