PerfectVector
By Irene Kim10 min read

SVG Grain Texture: Keep Noise Inside Your Artwork

Add SVG grain with feTurbulence, keep monochrome noise inside SourceAlpha, tune it at two sizes, and preserve a clean path master for other destinations.

On this page

To add grain to an SVG illustration, generate noise with feTurbulence, turn it into a faint monochrome overlay, and composite that overlay inside SourceAlpha. Merge it over SourceGraphic so the original fill stays visible. This adds a rendered texture while leaving the artwork's path geometry intact.

A bare noise primitive gives a different result: it fills its filter primitive subregion, rather than following the shape's outline. That is why a leaf can become a rectangular noise patch. MDN's feTurbulence reference documents that behavior.

For a web illustration, the useful deliverables are a textured display version and a clean master. Grain produced by this filter is not a collection of editable dots or cutting contours.

Separate the shape from the surface treatment

Start with a simple filled path that already looks right without grain. Fix its outline, gaps, and color before adding the effect. A filter will not repair that geometry.

The three states below explain the boundary problem:

VersionWhat the filter outputsWhen to use it
Plain shapeThe original filled pathEditing and a clean master
Bare noiseA rectangular generated image in the filter regionInspecting the noise source, rather than delivering the motif
Contained grainOriginal artwork plus monochrome noise limited by its alphaA textured browser display version
The boundary matters
Illustration of a clean coral leaf, grain spilling outside a leaf, and grain contained inside a crisp leaf silhouette
Illustration: the shape stays clean while the noise is confined to its silhouette. This conceptual diagram is not an SVG renderer screenshot or a vectorization result.

SourceGraphic supplies the element being filtered. SourceAlpha supplies its alpha channel. The filter operates on an image of the artwork; it does not rewrite the path commands. These inputs and the filter graph are defined in the W3C Filter Effects specification.

If your starting artwork already has transparent areas, those areas affect the containment too. SourceAlpha follows the actual rendered opacity, not a guessed outer bounding box.

Copy a complete SVG grain example

Save this as an .svg file and open it in a browser. It contains one original leaf path, a deterministic noise seed, a dark overlay, and the explicit containment step. The diagonal opening is part of the path, so it remains transparent in the textured version.

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" width="200" height="200">
  <defs>
    <filter id="grain" x="-10%" y="-10%" width="120%" height="120%"
            color-interpolation-filters="sRGB">
      <feTurbulence type="fractalNoise" baseFrequency="0.65"
                    numOctaves="2" seed="8" result="noise"/>
      <feColorMatrix in="noise" type="matrix" values="0 0 0 0 0
        0 0 0 0 0
        0 0 0 0 0
        0 0 0 0.28 0" result="ink"/>
      <feComposite in="ink" in2="SourceAlpha" operator="in" result="inside"/>
      <feMerge>
        <feMergeNode in="SourceGraphic"/>
        <feMergeNode in="inside"/>
      </feMerge>
    </filter>
  </defs>
  <path d="M36 142C40 70 104 26 164 30C164 100 120 150 60 156L38 180L28 170L52 146C80 112 112 78 146 46C104 78 74 110 54 140Z" fill="#e76b50" filter="url(#grain)"/>
</svg>

The filter has four jobs:

  1. feTurbulence creates the noise and names it noise.
  2. The matrix sets red, green, and blue to zero. Its last row multiplies the noise's alpha by 0.28, creating a faint black overlay called ink.
  3. feComposite with operator="in" keeps that overlay where SourceAlpha exists.
  4. feMerge draws the original artwork first and the contained overlay above it.

The MDN feColorMatrix reference explains how the five-column matrix transforms color and alpha. Here it changes the noise image, not the leaf's fill. The MDN feComposite reference explains the in operation used to restrict the overlay to the second input.

The value 0.28 is a starting point for this coral leaf, not a universal grain setting. Lower it if the texture dulls the artwork; raise it if the grain disappears at the intended display size. Black overlay grain darkens the fill. It will not create visible pale speckles on a black motif.

For the color and alpha operations used to recolor existing artwork, see the separate feColorMatrix guide. For hardening an existing transparent edge, see SVG alpha thresholds. Neither operation supplies the generated noise source used here.

Check the result at the size people will see

We made three versions of this original path: no filter, a filter containing only the noise primitive, and the complete contained-grain graph above. We inspected the rendered versions in Chrome at 120 × 120 and 360 × 360 CSS pixels, with the same 0 0 200 200 viewBox.

Check120-pixel version360-pixel version
Plain masterSmooth coral leaf, transparent openingSame outline and opening
Bare noiseRectangular noise replaces the visible motifRectangular noise remains visible beyond the leaf silhouette
Contained grainFaint texture inside the leafMore visible texture, with opening and surrounding area clear

The browser DOM contained one path in every specimen. All six d attributes were identical. That establishes the limit of this example: the rendered surface changed, and no speck paths were added. It is an authored browser fixture, not output from PerfectVector or a native vector editor.

A larger preview helps inspect the effect, but the smaller version decides whether the artwork still reads. Keep both sizes in your review. Increasing display size with the same viewBox also changes the apparent scale of the texture; do not assume one preview represents every use.

Tune the grain one control at a time

For a small web card illustration, start with the values in the example. Then change one parameter, compare the same two display sizes, and keep a copy of the version you preferred.

ControlWhat to decidePractical check
baseFrequencyCoarser or finer variation in SVG coordinatesTry 0.25 beside 0.65; inspect at the actual display size
numOctavesHow many layers of noise detail to combineCompare 1 and 2 before adding more detail
seedWhich noise realization to useKeep it fixed while comparing other settings
Matrix alpha multiplierHow strongly the black overlay darkens the fillCompare 0.15 and 0.28 on the same artwork
Filter regionThe rectangle available to the filter graphFix missing output without using the rectangle as a substitute for alpha containment

baseFrequency accepts one value for both axes or two values for horizontal and vertical frequency. The MDN baseFrequency reference documents that distinction. Start with one value for this leaf; unequal values are a deliberate choice for directional texture.

numOctaves controls the number of noise octaves, as described in the MDN numOctaves reference. Extra octaves are not extra vector paths. Use them only if they improve the visible surface at the size you need.

The example sets color-interpolation-filters="sRGB" explicitly. Keep that setting unchanged while comparing your candidates so a change in color processing does not confuse the grain comparison.

Fix a rectangle, missing fill, or dirty edge

The texture makes a rectangular patch. Inspect the final output of the filter. If it ends with feTurbulence, it is returning the noise image. Restore the matrix, the SourceAlpha composite, and the merge. Enlarging the filter rectangle will only give uncontained noise more room.

The leaf's color disappears. Check that the first merge node uses SourceGraphic. A final inside result alone contains the dark overlay, not the original coral fill. Also check spelling and capitalization of each named result and in reference.

Noise remains in a transparent opening. Confirm the second composite input is SourceAlpha, not the rectangular noise or an opaque background. Apply the filter to the artwork you want textured. Including an opaque background in the filtered group changes the alpha input.

Part of the output is cropped. Check x, y, width, and height on the filter. These set the available filter region, as described in the MDN filter reference. The example gives modest extra room. A wider region cannot repair a missing containment step, and it does not fix clipping imposed by a separate container.

The small artwork looks muddy. Reduce overlay alpha first, then compare frequency and octave count. If the texture still harms the silhouette, deliver the clean version at that size.

Keep a clean master for delivery

For the unfiltered master, remove filter="url(#grain)" from the path and remove the now-unused filter definition. Preserve the path's d, its fill, and the viewBox. Open that file separately and confirm the leaf and opening match the original clean version.

For a web app, check the textured version in the browsers and exact embedding method you will ship. If you repeat this inline SVG on one page, give each filter a unique ID and update its url(#...) reference. The standalone example uses one ID because it contains one instance.

For a destination that needs an exact raster appearance, export a raster preview at the required size and inspect it there. For a workflow that needs editable or cuttable geometry, hand over the clean paths and clarify that the grain is a display effect. Do not describe filter noise as vector specks, and do not promise that a downstream editor, PDF exporter, or cutter reproduces it. Test the actual destination.

If you deliberately need individually editable specks, that is a separate geometry task. It also needs a cleanup decision; see why an SVG has too many nodes before tracing texture into a mass of tiny contours. Preserving grain from a raster painting is another starting problem, covered in watercolor to vector.

When vectorization helps

If the clean motif survives only as a PNG or JPG, convert that source into editable SVG artwork before adding a browser filter. Inspect the recovered silhouette and opening in the clean version first. PerfectVector supplies the raster-to-vector step; the procedural grain graph in this guide is a separate SVG treatment you add afterward.

Already have the path-based master? Use it directly. A second conversion is unnecessary for the filter job. The image vectorization guide explains that source-recovery step if you need it.

FAQ

Why does feTurbulence create a rectangle instead of following my shape? The noise fills its filter primitive subregion. Composite it inside SourceAlpha and merge it over SourceGraphic to confine the overlay to the artwork while preserving its fill.

Does SVG grain add nodes to my path? This filter does not add speck paths. In the original browser fixture, all six specimens retained one path with identical d data; the filter changed the rendered surface.

Which grain settings should I start with? For the original leaf example, start with fractalNoise, baseFrequency 0.65, two octaves, seed 8, and a black overlay alpha multiplier of 0.28. Compare at the real display size and adjust one setting at a time.

Can I use the grain effect as a cutting file? The generated texture is not editable cutting geometry. Keep a separate unfiltered path master and check the geometry in the actual cutting workflow.

Sources

  1. MDN: feTurbulence — Noise generation and the primitive subregion.
  2. W3C: Filter primitive tree — SourceGraphic, SourceAlpha, and filter image processing.
  3. MDN: feColorMatrix — Color and alpha matrix operations.
  4. MDN: feComposite — Containment using the in operator.
  5. MDN: baseFrequency — One-axis and two-axis frequency values.
  6. MDN: numOctaves — Noise detail layers.
  7. MDN: filter — Filter-region attributes.

If your web illustration needs a clean master recovered from raster, start with image-to-vector conversion, review the paths, and add grain to a separate display copy.

More from the blog

PerfectVector

Start with a cleaner SVG
that is easier to edit

No credit card required