Canvas Fractal Tree Generator — Free Recursive Branching Snippet

Canvas Fractal Tree Generator · Animations · Plain HTML, CSS & JS · Live preview

Share & Support

What's included

Features

Pure recursive drawing
One function, two recursive calls, no tree data structure.
Depth-driven styling
Color, width, and leaf dots derived from recursion depth.
Live depth control
A slider changes how many branch generations render.
Live spread-angle control
A slider changes the branching angle for every branch.
Organic randomization
Per-branch shrink/angle jitter avoids mechanical symmetry.
Cursor-driven wind sway
Outer branches sway more than the trunk, proportional to depth.
Leaf accents
Small dots render at the outermost branch tips.
DPR-aware rendering
Crisp branch linework on high-density displays.

About this UI Snippet

Canvas Fractal Tree Generator — Recursion as the Entire Algorithm

Screenshot of the Canvas Fractal Tree Generator snippet rendered live

A fractal tree is one of the clearest illustrations of recursion producing organic complexity: one function, branch(), calls itself twice per invocation, and the tree's entire branching structure falls out of how those calls compound.

One function draws a segment, then recurses twice

Every call to branch() draws exactly one line segment from a starting point at a given angle and length, then calls itself twice more — once angled left by spreadRad, once angled right — each with a shrunken length and one less depth remaining. There's no tree data structure built up in memory; the recursive call stack *is* the tree structure, and the canvas drawing happens as a side effect of walking it.

Two knobs control the whole shape: depth and spread angle

maxDepth (via the Depth slider) controls how many branch generations occur before recursion bottoms out — small values produce a stick with a few forks, large values produce a dense, twiggy canopy. spreadRad (via Branch angle) controls how far each child branch diverges from its parent's direction — narrow angles produce a tall, columnar tree; wide angles produce a broad, sprawling one. Every branch in the whole tree obeys the same two parameters, which is why such a small amount of code produces such varied results.

Randomized shrink and spread avoid mechanical symmetry

If every branch shrank by exactly the same factor and split at exactly the same angle, the tree would look like a rigid, obviously-generated diagram. Small per-branch randomization on both the length-shrink factor and the spread angle (0.8 + Math.random() * 0.4) breaks that symmetry just enough to read as organic rather than mathematical, without changing the underlying recursive structure at all.

Depth-based rendering, not a separate pass

Line width, color (green fading toward brown near the trunk, leaf dots at the outermost depth), and wind sensitivity are all derived directly from the current depth value relative to maxDepth inside the same recursive call — there's no second traversal to add color or leaves after the fact.

Wind as an angle offset proportional to distance from the trunk

Cursor position sets a targetSway value, smoothly eased into sway each frame. Every branch's angle is nudged by sway * windFactor, where windFactor grows for branches further from the trunk — so outer twigs visibly sway more than the thick trunk, exactly like a real tree in wind, using the same depth value already available in the recursive call.

Build with AI

Build, Understand, Optimize, and Extend It With AI

Paste this snippet's HTML, CSS, and JS into an AI coding assistant like Claude and ask it to explain why a single recursive function with two self-calls is sufficient to produce the entire tree structure with no explicit data structure, and how the depth parameter doubles as both the recursion's stopping condition and the input to the wind-sway and color calculations. It's a great snippet to extend with an assistant — ask for an animated growth sequence (depth incrementing over time), a version using an L-system string-rewriting approach instead of direct recursion for more varied branching rules, or seasonal color palettes (blossoms in spring, bare branches in winter) swapped based on a parameter.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build a "recursive fractal tree" generator in plain HTML, CSS, and JavaScript using only the Canvas 2D API — no external library, pure recursion and trigonometry.

Requirements:
- A single recursive function that draws one branch as a line segment from a given start point, at a given angle and length, then recursively calls itself exactly twice for the two child branches — one angled left by a "spread" angle, one angled right — each with a reduced length (shrunk by a randomized factor per call, e.g. 0.72 plus a small random jitter) and one less remaining "depth." Recursion stops when depth reaches 0 or the branch length drops below a small threshold (e.g. 2px).
- Expose a live "Depth" slider (roughly 4-13) controlling how many branch generations occur, and a live "Branch angle" slider (roughly 10-55 degrees) controlling how far child branches diverge from their parent's direction — re-render the full tree from scratch whenever either changes.
- Derive per-branch visual styling directly from the current recursion depth relative to the max depth in the same recursive call (no separate pass): line width should taper from thick near the trunk to thin near the tips, color should shift from a brownish trunk tone near the base to greener tones toward the tips, and small leaf-like dots should render at the outermost 1-2 depth levels.
- Add a small random angle/length jitter to every recursive call (not just a uniform fixed shrink and spread) so the tree reads as organic rather than perfectly symmetric.
- Track cursor (and touch) horizontal position across the canvas, mapping it to a "target sway" angle offset, smoothly eased toward each frame. Apply that sway to every branch's angle in the recursive draw, scaled by how far that branch is from the trunk (using the same depth value already available in the recursion) so outer branches visibly sway more than the trunk, simulating wind.
- Handle window resize by recalculating canvas dimensions and re-rendering the tree from its base, and scale for devicePixelRatio so branches render crisply on high-DPI screens.

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

Step by step

How to Use

  1. 1
    Paste HTML, CSS, and JSA recursive fractal tree renders from the base upward.
  2. 2
    Move the cursor left/rightThe tree leans and sways like it's caught in wind.
  3. 3
    Adjust DepthMore generations of branches produce a denser canopy.
  4. 4
    Adjust Branch angleWider angles produce a broader, more sprawling shape.
  5. 5
    Watch the outer twigsThey sway more than the trunk, proportional to their depth.
  6. 6
    Resize the windowThe tree re-renders from its base to fit the new canvas.

Real-world uses

Common Use Cases

Educational tools
A canonical, readable recursion teaching example.
Nature/eco brand landing pages
An organic, growing visual metaphor.
Portfolio pieces
Demonstrate recursive algorithm and canvas skill.
Generative art backgrounds
A unique tree shape from randomized parameters.
Growth/progress visualizations
Animate depth increasing over time to show growth.
Computer science coursework demos
Illustrate recursion with an immediately visual result.

Got questions?

Frequently Asked Questions

branch() draws a single line segment, then calls itself exactly twice with a reduced length, one less depth, and an angle offset left or right by the spread angle. Because each of those two calls does the same thing again, the recursive call stack expands into every branch of the tree; there's no explicit tree data structure being built anywhere, the recursion itself is the branching structure.

Two guard conditions at the top of branch(): depth <= 0 (the branch has used up its allotted number of generations, set by the Depth slider) or len < 2 (the branch has shrunk small enough that drawing it further would be visually meaningless). Either condition returns immediately without recursing further, which is what keeps a tree with a large depth value from recursing infinitely.

Each recursive call applies a small random jitter to both the length-shrink factor and the spread angle of its two children, rather than using fixed values everywhere. That small per-branch randomization is applied identically at every level of recursion, so the irregularity compounds naturally across generations without needing any special-case logic.

It reuses the same depth value already passed through the recursion. windFactor is computed as (maxDepth - depth) / maxDepth, which is 0 near the trunk (where depth is close to maxDepth) and approaches 1 near the outermost twigs (where depth is close to 0). Multiplying the cursor-driven sway value by that factor means outer branches lean noticeably more than the trunk, with zero extra bookkeeping beyond the recursion depth that was already tracked.

Yes — instead of rendering at a fixed Depth value from the slider, drive an incrementing depth variable up from 0 over time (e.g. incrementing roughly once per second inside the animation loop, capped at the slider's max) and re-render on each increment. Since render() always draws the full tree fresh from the trunk outward, incrementing depth over time naturally produces a growth animation with no other code changes.