CSS och webb

Brustextur i CSS: lägg korn på gradienter med SVG

Ett svagt lager brus döljer banding och får platt skärmfärg att kännas som tryck eller film. Här är SVG-filtret bakom det, finjusterat och redo att klistra in.

GradientlyVerifierat Gradiently-konto··5 minuters läsning
Omslag: Muslin Anvil · GR·W4AX·4M

Kortversionen

  • En brustextur i CSS görs oftast med ett SVG-filter med feTurbulence, inbäddat som en liten data-URI-bild och kaklat över en gradient.
  • baseFrequency i feTurbulence anger kornstorleken: högre värden ger finare korn, lägre värden ger grovt, molnigt brus.
  • Brus fungerar bäst lagt över gradienten på ett pseudoelement med ett blandläge som soft-light eller overlay och låg opacitet.
  • Korn döljer gradientbanding eftersom det bryter de synliga kanterna mellan närliggande toner till fin, slumpmässig variation.
  • En kaklad brusbild är billig att rendera, medan ett levande SVG-filter på ett stort element, eller att animera det, kostar mycket mer.
På den här sidan

En brustextur i CSS är ett fint, slumpmässigt stänk som läggs över en färg eller gradient för att ge den korn. CSS har ingen brusfunktion, så den vanliga källan är SVG: filtret feTurbulence genererar brus, du lägger det i en liten SVG, bäddar in den som en data-URI och kaklar den över din gradient med låg styrka. Resultatet ser ut som filmkorn eller tryckt papper, och det åtgärdar i det tysta banding, de synliga trappstegen som uppstår i stora, mjuka gradienter.

Varför korn får färg att se dyrare ut tas upp i kornig gradient. Den här guiden är genomförandet.

SVG-filtret för brus

html
<svg xmlns="http://www.w3.org/2000/svg" width="240" height="240">
  <filter id="n">
    <feTurbulence type="fractalNoise" baseFrequency="0.8" numOctaves="3" stitchTiles="stitch" />
    <feColorMatrix type="saturate" values="0" />
  </filter>
  <rect width="100%" height="100%" filter="url(#n)" />
</svg>
En bricka på 240 pixlar med grått brus. Spara den som noise.svg eller bädda in den som visas nedan.
AttributVärde härVad det styr
typefractalNoiseMjukt, jämnt korn. turbulence ger mer strimmigt, krusigt brus.
baseFrequency0.8Kornstorlek. Runt 0,6 till 0,9 är fint korn, 0,1 till 0,3 är molnigt.
numOctaves3Lager av detaljer. Över ungefär 4 är skillnaden svår att se.
stitchTilesstitchFår brickans kanter att matcha, så upprepningar saknar sömmar.
feColorMatrix saturate 00Tar bort den slumpmässiga färgen och lämnar grått korn.
Inställningarna som spelar roll. MDN:s referens för feTurbulence dokumenterar resten.

Att bädda in brus som en data-URI

En separat fil fungerar, men inbäddning sparar en förfrågan och håller effekten på ett ställe. I en data-URI måste tecken som betyder något i URL:er kodas: < blir %3C, > blir %3E, # blir %23 och % blir %25. Använd enkla citattecken inuti SVG så att de inte krockar med de dubbla runt URL:en.

css
:root {
  --noise: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
Samma bricka som en egen egenskap du kan återanvända var som helst. Att glömma koda # som %23 är den vanliga orsaken till att inget syns i Firefox.

Att lägga brus i lager över en gradient

Lägg bruset på ett pseudoelement ovanför gradienten och styr det sedan med två rattar: ett blandläge, som avgör hur det grå kornet blandas med färgen under, och opacitet, som avgör hur starkt det är. soft-light håller färgerna rena och är det mildaste, overlay ger mer kontrast. pointer-events: none hindrar lagret från att blockera klick.

css
.grain {
  position: relative;
  isolation: isolate;
  background: linear-gradient(135deg, #1e1b4b, #7c3aed 55%, #f472b6);
}

.grain::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: var(--noise);
  mix-blend-mode: soft-light;
  opacity: 0.45;
  pointer-events: none;
}
Korn mellan gradienten och innehållet: texten inuti .grain förblir skarp.
Tre gradienter som vinner mest på korn. Mörka toningar med låg kontrast som den i mitten är där banding syns först.

Om du föredrar ett enda element utan pseudoelement listar du bruset först i background-image och sätter background-blend-mode: soft-light, normal. Då förlorar du den separata opacitetsratten, så baka in styrkan i SVG i stället, till exempel med opacity='0.5' på rect.

Hur mycket korn räcker

  1. 1

    Börja svagt

    Börja på opacity: 0.3 med soft-light. Du bör knappt märka det på armlängds avstånd.

  2. 2

    Kontrollera det mörkaste området

    Banding lever i mörka, långsamma toningar. Höj opaciteten tills stegen där löses upp och sluta sedan.

  3. 3

    Anpassa kornet till storleken

    Hero-ytor i helskärm tål något grövre korn, runt 0,6. Kort och knappar vill ha fint korn, runt 0,9.

  4. 4

    Kontrollera på en telefon och en stor skärm

    Korn som ser rätt ut på en skärm kan se ut som damm på en annan. Sikta på en textur som du känner snarare än ser.

  5. 5

    Kontrollera texten ovanpå

    Korn får inte försämra läsbarheten. Om liten text ligger på texturen sänker du styrkan eller håller texten på en lugnare yta.

För mycket

  • Korn som syns från andra sidan rummet
  • Färgerna blir grå och smutsiga
  • Grovt, molnigt brus på små komponenter
  • Textkanter ser suddiga ut mot stänket

Ungefär rätt

  • Korn som märks bara på nära håll
  • Färgerna förblir rena med soft-light
  • Fint korn anpassat till elementets storlek
  • Banding borta, text skarp

Prestanda för brus i CSS

En kaklad data-URI är billig: webbläsaren renderar den lilla brickan en gång och upprepar den, och ett statiskt lager målas en gång. Den dyra versionen är att tillämpa filtret live på ett stort element med filter: url(#noise), vilket kör filtret över varje pixel varje gång ytan ritas om. Om du animerar korn, för ett flimrande filmutseende, flyttar du det kaklade lagret med transform i några ryckiga steg i stället för att generera om brus, och stänger av det för reducerad rörelse.

css
.grain {
  overflow: hidden;
}

.grain::after {
  inset: -50%;
  animation: flicker 0.6s steps(3) infinite;
}

@keyframes flicker {
  0%   { transform: translate(0, 0); }
  33%  { transform: translate(-3%, 2%); }
  66%  { transform: translate(2%, -3%); }
}

@media (prefers-reduced-motion: reduce) {
  .grain::after { animation: none; }
}
Animerat korn genom att flytta en överdimensionerad bricka. Den negativa inset-marginalen håller kanterna täckta medan den skiftar.

En förrenderad brusbricka i PNG eller WebP på ungefär 128 till 256 pixlar är en lika bra källa om du redan har en. Korn är också en ingrediens i en bredare familj av ytor, från papper till glas, som tas upp i bakgrundstextur. Det är också det avslutande lagret på en mesh-gradient i CSS.

Korn är inbyggt i varje Gradiently Mark som en materialinställning, vid sidan av ljus och rörelse, så designer gjorda med en bär textur utan någon kod.

Muslin Anvil

GR·W4AX·4M

Muslin Anvil

Se den här Marken
En Mark med korn som en del av sitt material, renderad live i stället för lagd på efteråt.

Vanliga frågor

Hur lägger jag till en brustextur i CSS?

Bädda in en SVG med ett feTurbulence-filter som en data-URI, kakla den på ett pseudoelement över din gradient och sätt ett blandläge som soft-light med låg opacitet.

Varför syns inte min SVG-brus-data-URI?

Oftast ett okodat tecken. Koda # som %23, % som %25 och vinkelparenteserna som %3C och %3E i data-URI:n, och använd enkla citattecken inuti SVG.

Åtgärdar korn gradientbanding?

Ja, i de flesta fall. Slumpmässig fin variation bryter upp de hårda kanterna mellan närliggande toner, så ögat ser inte längre trappsteg.

Vilken baseFrequency ska jag använda för korn?

Runt 0,6 till 0,9 ger fint, filmlikt korn. Lägre värden som 0,2 ger stort, molnigt brus.

Är brus i CSS dåligt för prestandan?

En liten kaklad brusbild är billig. Levande SVG-filter på stora element och ständigt omgenererat brus är det som kostar mest.

Dela den här guiden

Skriven av GradientlyVerifierat Gradiently-konto

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