Composing effects

Stack components as layers and nest them to control which layers an effect touches. This page builds one hero background, a grid over a flowing swirl, a layer at a time.

Stacking layers

Every component inside a <Shader> is a layer. Layers are drawn in the order they appear in your markup, like layers in Figma: the first is at the bottom, the last on top.

Some components draw something new, like a swirl or a grid. Others are effects: they change what's already been drawn. An effect on its own applies to every layer before it.

Here <Swirl> is the background, <Grid> draws lines over it, and <GridDistortion> bends both around your cursor:

<Shader>
  {/* Bottom: the background */}
  <Swirl
    colorA="#7355fe"
    colorB="#91e040"
    colorSpace="oklab"
    blend={18}
    detail={0.9}
    speed={1.5}
  />

  {/* Grid lines over the swirl */}
  <Grid
    color="#00a2fa"
    cells={10}
    thickness={3.2}
    blendMode="hardLight"
  />

  {/* Bends everything before it around your cursor */}
  <GridDistortion
    intensity={5}
    radius={1.75}
    decay={1.8}
    gridSize={8}
    edges="wrap"
  />
</Shader>

Move your cursor over the canvas. <GridDistortion> comes last, so it bends the swirl and the grid together. The grid's blendMode sets how its lines mix with the swirl underneath; blending and masking covers every mode.

Applying effects to specific layers

To limit an effect to specific layers, put those layers inside it. The effect then applies to its children only.

Let's make the grid ripple on its own. Wrapped in <WaveDistortion>, the grid lines bend in a slow triangle wave, and the swirl behind them is left alone:

<Shader>
  <Swirl
    colorA="#7355fe"
    colorB="#91e040"
    colorSpace="oklab"
    blend={18}
    detail={0.9}
    speed={1.5}
  />

  {/* Only the grid waves */}
  <WaveDistortion
    waveType="triangle"
    strength={0.8}
    frequency={0.7}
    angle={235}
    speed={0.5}
    edges="mirror"
    blendMode="linearDodge"
  >
    <Grid
      color="#00a2fa"
      cells={10}
      thickness={3.2}
      blendMode="hardLight"
    />
  </WaveDistortion>

  <GridDistortion
    intensity={5}
    radius={1.75}
    decay={1.8}
    gridSize={8}
    edges="wrap"
  />
</Shader>

<GridDistortion> still applies to everything, because it stays outside the wrapper. Without the wrapper, <WaveDistortion> would bend the swirl too.

This works at any depth. An effect can wrap another effect, and they apply from the inside out: the innermost layer is drawn first, and each wrapper applies to the result.

Knowing which components take children

Components that draw something new, such as <Swirl> and <Grid>, don't take children. Effects such as <WaveDistortion> and <GridDistortion> do. On an effect's component page, the usage example shows it wrapping a child.

Next steps

  • Blending and masking: control how layers mix, and reveal one layer through another.
  • Dynamic props: drive props from the mouse or animate them without writing animation code.
  • Performance: what each layer costs and how to keep effects fast.