# WebGL-gradientshaders förklarade för designers

[Canonical HTML page](https://gradiently.design/sv/guide/shader-gradients)

Vissa gradienter på webben driver, glöder och skimrar på ett sätt ingen bild eller CSS-regel kan. De är shaders. Så fungerar de, med ord en designer kan använda.

## The short version

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

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](https://gradiently.design/sv/guide/css-linear-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å.

```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 WebGL2-fragmentshader i GLSL. `smoothstep` mjukar upp varje övergång, sinusvågen flyttar gränsen och de sista raderna lägger till korn som också döljer bandning.

- Nattbotten: #120a2e
- Violett: #7c3aed
- Korall: #fa7373

De tre färgerna i shadern. GLSL skriver färg som 0 till 1 per kanal, så #7c3aed blir 124, 58 och 237 delat med 255.

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

Ingen är bättre i allmänhet. Var och en vinner på ett annat jobb.

CSS-reserven: `linear-gradient(180deg, #120a2e 0%, #4c1d95 40%, #7c3aed 62%, #fa7373 100%)`

Samma palett som en stillastående CSS-gradient. Varje shaderbakgrund bör levereras med en reserv som den här, som visas innan shadern startar och närhelst den inte kan köras.

## 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](https://gradiently.design/sv/guide/grainy-gradients).
- **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](https://gradiently.design/sv/guide/gradient-banding) 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](https://gradiently.design/sv/guide/css-gradient-performance) 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](https://gradiently.design/sv/guide/reduced-motion) 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.

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

Skyddsräckena på några rader: en reserv när WebGL saknas, bara en bildruta vid minskad rörelse och ingen ritning utanför skärmen eller i en dold flik.

Som referens dokumenterar [WebGL API på MDN](https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API) varje anrop som används här, och [caniuse](https://caniuse.com/webgl2) 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.

> **Bedöm den stilla först** Pausa shadern på en slumpmässig bildruta och titta på den som en stillbild. Om en stillbild inte ser bra ut räddar inte rörelsen den. Rörelse ska tillföra något till en design som redan fungerar.

## 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](https://gradiently.design/sv/guide/what-is-a-mark) förklarar receptet i sin helhet.

En Mark är ett shaderrecept med ett namn, en kod och en ägare. Dess sida visar den renderas live.

## FAQ

### 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.
