# How to Create a Sketchy/Hand‑Drawn Primitive Using an SVG Turbulence Filter

> Learn to create sketchy hand-drawn primitives with SVG turbulence filters. Combine feTurbulence and feDisplacementMap for organic, hand-drawn edges in your diagrams.

- Repository: [Cathryn Lavery/diagram-design](https://github.com/cathrynlavery/diagram-design)
- Tags: how-to-guide
- Published: 2026-09-05

---

**A sketchy primitive in Diagram Design is built by combining `feTurbulence` for fractal noise generation with `feDisplacementMap` to distort the original graphic, producing organic, hand‑drawn edges.**

The **Diagram Design** repository implements this effect as a reusable SVG filter that adds subtle noise to any shape group. According to the source code in `cathrynlavery/diagram-design`, the filter is defined once in **[`primitive-sketchy.md`](https://github.com/cathrynlavery/diagram-design/blob/main/primitive-sketchy.md)** and applied selectively to non‑text elements, preserving readability while giving illustrations a rough, editorial character.

---

## SVG Filter Architecture

The sketchy effect relies on two chained filter primitives working in sequence.

### feTurbulence: Generating the Noise

The `<feTurbulence>` element creates fractal noise that serves as the displacement map:

- `type="fractalNoise"` produces smooth, organic noise rather than blocky turbulence
- `baseFrequency` controls the spatial frequency of the noise
- `numOctaves` adds layers of detail
- `seed` provides deterministic randomness

### feDisplacementMap: Distorting the Graphic

The `<feDisplacementMap>` uses the turbulence output to shift pixels in the source graphic:

- `in="SourceGraphic"` specifies what to distort
- `scale` determines displacement magnitude in pixels

---

## Complete Filter Definition

The standard filter definition from [`skills/diagram-design/references/primitive-sketchy.md`](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/references/primitive-sketchy.md):

```svg
<defs>
  <filter id="sketchy" x="-2%" y="-2%" width="104%" height="104%">
    <feTurbulence type="fractalNoise"
                  baseFrequency="0.02"
                  numOctaves="2"
                  seed="4"/>
    <feDisplacementMap in="SourceGraphic" scale="1.5"/>
  </filter>
</defs>

```

The expanded filter region (`x="-2%" y="-2%" width="104%" height="104%"`) prevents edge clipping when displacement pushes pixels outward.

---

## Applying the Sketchy Primitive to SVG Elements

The filter is attached to a `<g>` element that wraps **only non‑text shapes**. Text elements must remain unfiltered to maintain legibility.

```svg
<!-- Shapes receive the hand‑drawn effect -->
<g filter="url(#sketchy)">
  <rect x="10" y="10" width="80" height="40" />
  <circle cx="50" cy="70" r="20" />
</g>

<!-- Labels stay crisp and readable -->
<text x="15" y="35" font-family="sans-serif">Label</text>

```

This separation is critical—the displacement that creates the sketchy aesthetic would render body text illegible if applied uniformly.

---

## Tuning Parameters for Different Visual Styles

| Parameter | Typical Range | Visual Effect |
|-----------|---------------|---------------|
| `baseFrequency` | 0.01–0.04 | Lower values produce lazy, flowing waviness; higher values create jitterier, more nervous lines |
| `numOctaves` | 1–3 | Additional octaves add finer noise detail and complexity |
| `scale` | 1–6 | Controls displacement strength: 1 for subtle texture, 4+ for exaggerated cartoon effects |
| `seed` | Any integer | Changes the noise pattern while keeping all other parameters constant |

The **tuning table** in [`primitive-sketchy.md`](https://github.com/cathrynlavery/diagram-design/blob/main/primitive-sketchy.md) provides these guidelines for adapting the filter to specific creative contexts.

---

## Complete Working Example

A self‑contained SVG demonstrating the sketchy primitive implementation:

```svg
<svg width="120" height="100" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <filter id="sketchy" x="-2%" y="-2%" width="104%" height="104%">
      <feTurbulence type="fractalNoise" baseFrequency="0.02" numOctaves="2" seed="4"/>
      <feDisplacementMap in="SourceGraphic" scale="1.5"/>
    </filter>
  </defs>

  <g filter="url(#sketchy)">
    <rect x="10" y="10" width="80" height="40" fill="#4caf50"/>
    <circle cx="60" cy="70" r="15" fill="#ff9800"/>
  </g>

  <text x="15" y="35" font-size="12" fill="#000">Sketchy Box</text>
</svg>

```

### More Jittery Variant

For a rougher, more energetic appearance, increase frequency and scale:

```svg
<feTurbulence baseFrequency="0.035" numOctaves="3" seed="7"/>
<feDisplacementMap in="SourceGraphic" scale="3"/>

```

---

## Where to Use the Sketchy Filter

According to the repository's **README** (approximately line 568), the sketchy primitive excels in:

- **Essays and blog posts** — adds personality and human warmth
- **Newsletters** — distinguishes editorial content from sterile graphics
- **Work‑in‑progress diagrams** — signals draft status visually

Avoid the filter in:

- Dense technical documentation where precision matters
- Dark backgrounds where noise patterns become distracting
- Any context requiring exact measurement or alignment

The **SKILL.md** file under `skills/diagram-design/` lists the "Sketchy variant" as an optional primitive with a link to the full reference implementation.

---

## Summary

- The **sketchy primitive** combines `feTurbulence` and `feDisplacementMap` in a single SVG filter definition
- **[`primitive-sketchy.md`](https://github.com/cathrynlavery/diagram-design/blob/main/primitive-sketchy.md)** contains the canonical filter code and tuning guidance
- Apply `filter="url(#sketchy)"` only to shape groups, keeping text elements separate
- Tune `baseFrequency`, `numOctaves`, `scale`, and `seed` to match your desired aesthetic intensity
- Use for editorial and informal diagrams; avoid for precise technical documentation

---

## Frequently Asked Questions

### What makes the sketchy filter different from simple CSS filters?

**CSS filters like `blur` or `contrast` operate uniformly across pixels**, whereas the SVG turbulence filter generates spatially varying displacement that follows organic noise patterns. This creates the irregular, hand‑drawn line quality impossible to achieve with CSS alone. The `feDisplacementMap` component is what enables this pixel‑by‑pixel distortion based on the turbulence texture.

### Why must text stay outside the filtered group in the sketchy primitive implementation?

**Displacement would distort glyph shapes and degrade readability.** The filter intentionally separates `<g filter="url(#sketchy)">` for shapes from unwrapped `<text>` elements. This architectural choice in Diagram Design preserves sharp, vector‑precise typography while surrounding elements carry the rough aesthetic.

### How do I make the sketchy effect more or less pronounced?

**Adjust the `scale` attribute on `feDisplacementMap` and the `baseFrequency` on `feTurbulence`.** Increasing `scale` from 1.5 to 4–6 amplifies the wobble dramatically. Raising `baseFrequency` from 0.02 toward 0.04 introduces finer, more frequent noise. The [`primitive-sketchy.md`](https://github.com/cathrynlavery/diagram-design/blob/main/primitive-sketchy.md) tuning table documents these relationships with specific value ranges.

### Can the sketchy filter be animated or changed dynamically?

**Yes, by modifying filter attributes via JavaScript or SMIL animation.** Changing the `seed` attribute generates new random patterns, while animating `baseFrequency` or `scale` produces evolving distortion effects. The deterministic nature of `seed` ensures reproducible results when static, or controlled variation when animated.