/ marion.dev

Web design · CSS · SVG

Unlocking the full power of SVG filters for typography

Turn the browser rendering engine into a vector composition tool with custom SVG filters.

By Marion Herault

SVG FILTERS

Beyond standard CSS filters

In front-end development, the CSS filter property is often associated with basic adjustments such as blur(), drop-shadow() or grayscale(). When paired with custom SVG filters declared through <filter>, however, the browser becomes a genuine vector composition tool.

One of the clearest use cases is large display type with complex outlines, which is difficult to control with standard CSS properties.

The problem with -webkit-text-stroke

On a heading with overlapping letters or a transparent fill, the CSS stroke falls short for two reasons.

Sequential rendering

Each character and its stroke are rendered separately. Where letters overlap, one letter’s outline can cover the body of the previous one.

A centred stroke

Half of the outline extends into the glyph. With reduced opacity, this inner portion remains visible and changes the text colour.

Treating the word as a single mask

The solution is to stop seeing the text as a sequence of letters and treat it as one vector shape. The filter intercepts the SourceGraphic before display and passes it through a pipeline of five primitives.

  1. 1feMorphology

    Expands the overall silhouette of the word.

  2. 2feComposite · out

    Subtracts the original text to hollow out the centre.

  3. 3feFlood + composite

    Applies colour to the outline only.

  4. 4feComponentTransfer

    Controls the opacity of the inner text independently.

  5. 5feMerge

    Layers the outline and processed text.

Step 1

Dilation with feMorphology

The dilate operator expands every text pixel outwards according to the radius value. It produces a fuller, heavier shape and fills the gaps between overlapping letters.

Step 2

Subtraction with feComposite

The out operator works like a cookie cutter: it removes the original text from the expanded shape. The centre genuinely disappears, leaving a clean outline with no pixels spilling into the glyph.

Step 3

Colouring the outline

feFlood creates a solid colour surface. A second feComposite, this time using the in operator, confines that colour to the ring created in the previous step.

Step 4

Processing the interior

feComponentTransfer isolates the original text so its alpha channel can be changed. A 0.3 slope reduces its opacity to 30%, independently of the outer outline.

Step 5

The final merge with feMerge

The two layers are stacked: the coloured outline first, then the adjusted text. The result is one cleanly outlined word whose interior remains fully independent.

Implementation source code

The filter can be declared once inside an invisible SVG, then applied to any HTML element with the CSS filter property.

HTML · Filter declaration
<svg
  style="position: absolute; width: 0; height: 0; pointer-events: none;"
  aria-hidden="true"
>
  <filter id="hollow-stroke" x="-40%" y="-40%" width="180%" height="180%"
    color-interpolation-filters="sRGB">
    <!-- Step 1: Expand the overall silhouette -->
    <feMorphology operator="dilate" radius="2" in="SourceGraphic" result="expanded" />

    <!-- Step 2: Hollow out the centre by subtraction -->
    <feComposite in="expanded" in2="SourceGraphic" operator="out" result="outline" />

    <!-- Step 3: Colour the outline -->
    <feFlood flood-color="#7000FF" result="outline-color" />
    <feComposite in="outline-color" in2="outline" operator="in" result="final-outline" />

    <!-- Step 4: Set the inner text opacity -->
    <feComponentTransfer in="SourceGraphic" result="transparent-fill">
      <feFuncA type="linear" slope="0.3" />
    </feComponentTransfer>

    <!-- Step 5: Merge the layers -->
    <feMerge>
      <feMergeNode in="final-outline" />
      <feMergeNode in="transparent-fill" />
    </feMerge>
  </filter>
</svg>
CSS · Application
.outlined-title {
  color: #7000FF;
  filter: url(#hollow-stroke);
  font-size: 140px;
  font-weight: 900;
  letter-spacing: -12px;
  line-height: 0.85;
}

What else can you create?

Gooey effect

A Gaussian blur combined with a colour matrix can fuse several shapes together like drops of mercury.

Grain and organic textures

feTurbulence generates Perlin noise to create grain, retro paper, refraction or frosted glass effects.

Warping and distortion

feDisplacementMap shifts pixels using a texture to produce glitch, ripple or ink effects.

Inner drop shadow

By combining offsets, blur and compositing, the filter applies a shadow inside a complex silhouette.

Conclusion

SVG filters provide a powerful bridge between graphic design and front-end development. Their logic requires a gradual understanding of compositing primitives, but the result remains vector-based, accessible to screen readers and perfectly suited to modern design systems.