Skip to content

Backlight

A soft coloured glow behind an image or a card. It takes its colours from a list you give, or from a blurred, enlarged copy of the content itself.

Motionv0.1.0experimentalWCAG 2.2 AAView spec

Optional, and kept apart.

Nothing here is included in a project unless you add it, and the plain component it builds on is unchanged. This effect is decoration: it is hidden from screen readers, stands still for visitors who prefer reduced motion, and can be paused. Use Still on a preview to see that version.

import { Backlight } from "@rdloom/react";

export default function BacklightWithColorsExample() {
  return (
    <div className="flex w-full justify-center py-10">
      <Backlight colors={["#7c5cff", "#22d3ee", "#f472b6"]} intensity={0.55} blur={44}>
        <div
          role="img"
          aria-label="A sample picture drawn with a gradient"
          className="h-40 w-64 rounded-xl"
          style={{ background: "linear-gradient(135deg, #1e293b, #475569)" }}
        />
      </Backlight>
    </div>
  );
}

Installation

npx rdloom add backlight

Copies the source into src/components/rdloom. Edit it freely: rdloom upgrade merges later versions into your changes.

It also adds rdloom-motion.css next to your tokens and imports it from the tokens file, once: no setup, and no inline styles. The plain components you already use are untouched.

Use another registry client
npx shadcn@latest add https://rdloom.vimalbhatt.com/r/backlight.json

Works, but without upgrade tracking, and you import the motion CSS yourself.

Usage

import { Backlight } from "@rdloom/react";

<div className="flex w-full justify-center py-10">
  <Backlight colors={["#7c5cff", "#22d3ee", "#f472b6"]} intensity={0.55} blur={44}>
    <div
      role="img"
      aria-label="A sample picture drawn with a gradient"
      className="h-40 w-64 rounded-xl"
      style={{ background: "linear-gradient(135deg, #1e293b, #475569)" }}
    />
  </Backlight>
</div>

From content

import { Backlight } from "@rdloom/react";

// With no colors, the glow is a blurred, enlarged copy of the content, so it always matches it.
export default function BacklightFromContentExample() {
  return (
    <div className="flex w-full justify-center py-10">
      <Backlight intensity={0.7} blur={36}>
        <div
          role="img"
          aria-label="A sample picture drawn with a gradient"
          className="h-40 w-64 rounded-xl"
          style={{ background: "linear-gradient(120deg, #f97316, #eab308 45%, #22c55e)" }}
        />
      </Backlight>
    </div>
  );
}

Card

Team plan

Up to ten people, shared projects and a monthly report.

import { Backlight } from "@rdloom/react";

export default function BacklightCardExample() {
  return (
    <div className="flex w-full justify-center py-10">
      <Backlight colors={["#38bdf8", "#818cf8"]} isStill intensity={0.45}>
        <div className="w-64 rounded-xl border border-[var(--rd-color-border-default)] bg-[var(--rd-color-surface-default)] p-5">
          <h3 className="text-base font-medium text-[var(--rd-color-text-default)]">Team plan</h3>
          <p className="mt-1 text-sm text-[var(--rd-color-text-muted)]">Up to ten people, shared projects and a monthly report.</p>
        </div>
      </Backlight>
    </div>
  );
}

API Reference

Defined by the spec. Components also accept the props of the React Aria component they wrap.

PropTypeDefault
childrenrequired

The image or card the glow sits behind.

nodenone
colors

Glow colours, any CSS colours. Leave out to use a blurred copy of the children instead.

string[]none
intensity

How strong the glow is, from 0 to 1.

number0.6
blur

Blur radius of the glow in pixels.

number40
scale

How much larger than the content the glow is.

number1.1
duration

Seconds for one slow cycle of the glow.

number14
isStill

Keeps the glow still instead of slowly moving.

booleanfalse

Accessibility

Role none, WCAG 2.2 AA. Tested with axe and keyboard tests; screen reader checks are in the audit checklist.

Keyboard

Not interactive.

Screen readers announce

  • The glow is not announced; the content is read as normal

What your code must do

  • The glow is decoration: aria-hidden, pointer-events none, and it never takes focus
  • In copy mode the copy is inert as well as hidden, so it adds no focus stops and no duplicate content for assistive technology
  • The content on top is unchanged and keeps its own contrast; the glow never sits in front of text
  • The slow movement can be stopped with isStill or the rdm-still class, and stops for visitors who ask for less motion (prefers-reduced-motion)
  • In forced-colors (high contrast) mode the glow is removed
  • Does not flash: the glow changes slowly, never more than three times in a second (WCAG 2.3.1)

Guidelines

Use it when

  • Giving a product screenshot or a card some depth
  • A hero image that should feel lit from behind

Avoid it when

  • Content with ids or form fields in copy mode, where the copy repeats them (give colors instead)
  • Dense layouts where the glow would colour the text next to it

Don't

  • A very high intensity that lowers the contrast of nearby text
  • Using copy mode on a large video