Refrakt v1.0.0

Optics Cookbook · Level 2

The Optics Cookbook

You are two rungs up. Each recipe here is a finished optical look you paste in whole. If a slider is not yet running with your own pictures, start one rung lower.

  1. Level 1 Start here Your images and text in a working slider.
  2. Level 2 Customizing Size, colours, autoplay, controls, one setting at a time.

Want the exact range of every number a recipe sets? Options reference Level 3.

Stuck on any of it? Email jawad.ahbab.turna@gmail.com — that reaches me, the developer who wrote the slider, not a ticket queue. Usually answered within a working day. What support covers.

Twelve ready-made looks, one per buyer niche. Every recipe below is a complete, copy-paste configuration: a preset name in data-refrakt, overrides in data-rf-options, and the two theme tokens. Nothing here uses anything a preset file cannot express — paste it, add your slides, done.

Using a recipe

Every recipe assumes the standard markup contract — a container with .rf-slide figures as direct children:

<link rel="stylesheet" href="dist/refrakt.css">

<div data-refrakt="atelier" data-rf-options='{ …overrides… }'>
  <figure class="rf-slide">
    <img src="img/look-01-lqip.jpg" data-rf-src="img/look-01.jpg" alt="Look 01">
    <figcaption class="rf-text"><h2>Autumn 01</h2></figcaption>
  </figure>
  <!-- more .rf-slide children… -->
</div>

<script src="dist/refrakt.umd.js"></script>

Options merge in a fixed order: factory defaults ← preset ← data-rf-options ← constructor options. Later sources win per key, so a recipe only lists what it changes. Out-of-range values are clamped with a console warning — a bad number produces a different look, never a broken slider.

Chrome color is CSS, not configuration: set --rf-ink (text and chrome) and --rf-paper (surface) on the container. Each recipe includes its intended pairing inline so the paste is complete.

Prefer turning knobs to reading JSON? Open the Optics Lab from the demo hub, adjust any option live, and press Copy JSON — the clipboard result is a valid recipe in the same format used on this page.

01 Fashion lookbook

The signature reeded-glass carousel: the center look is pin-sharp while its neighbors dissolve into slow-sheening vertical flutes, like garments seen through fluted atelier glass. Wide, deep flutes make the side slides read as texture rather than blur; the light drift is slowed so the sheen crawls rather than flickers. Warm paper, near-black ink.

<div data-refrakt="atelier"
     style="--rf-ink:#1c1917; --rf-paper:#f2ede4;">
  <figure class="rf-slide">
    <img src="img/look-01-lqip.jpg" data-rf-src="img/look-01.jpg"
         alt="Look 01 — wool overcoat">
    <figcaption class="rf-text"><h2>Look 01</h2><p>Wool overcoat</p></figcaption>
  </figure>
  <!-- …one figure per look -->
</div>

The atelier preset needs no overrides — it ships tuned for exactly this. If your photography is very high-key, deepen the flutes slightly so the sides keep definition:

<div data-refrakt="atelier" data-rf-options='{
  "glass": { "reeded": { "frequency": 16, "depth": 0.75 } }
}'>

02 Agency hero

prism-noir at full throttle is awards-bait; this recipe is the same wedge prism pulled back to production strength. Hard flicks still tear the image into visible RGB fringes, but slow drags stay at a shimmer, grain is dialed down for legibility, and the giant editorial menu is swapped for arrows and a counter — a hero a client will actually sign off on. White ink on true black.

<div data-refrakt="prism-noir"
     style="--rf-ink:#f2f2f2; --rf-paper:#0a0a0a;"
     data-rf-options='{
  "dispersion": { "amount": 0.55, "velocityGain": 1.0, "maxTear": 0.65 },
  "exposure":   { "settleAmount": 0.3, "bloom": 0.2, "grain": 0.08 },
  "nav":        { "arrows": true, "editorialMenu": false, "counter": true }
}'>

Want the full poster-child look instead? Drop the overrides and run data-refrakt="prism-noir" bare.

03 Corporate & SaaS

The answer to “will this scare my client?” — no rest-state distortion at all (glass.kind "none"), a whisper of wedge shimmer only while dragging, slow autoplay that pauses on hover. Slides are always literal; the optics engine only announces itself in transit. Dark ink on white paper.

<div data-refrakt="boardroom"
     style="--rf-ink:#16181d; --rf-paper:#ffffff;">

The preset autoplays every 7 seconds. For a slower, more institutional pace:

<div data-refrakt="boardroom" data-rf-options='{
  "motion": { "autoplay": { "interval": 9000 } }
}'>

04 Photography portfolio

The exposure subsystem as the star. Each photograph “develops” on arrival — a strong overbrighten that settles like paper in a tray — under visible silver grain, and the autoplay idle is a slow exposure breath instead of a Ken Burns pan. Glass is a thin frost veil, so the develop effect carries the look, not refraction. Built for film and black-and-white work; near-black paper.

<div data-refrakt="darkroom"
     style="--rf-ink:#e8e6e1; --rf-paper:#0a0a0a;">

For color work the full 0.18 grain can feel heavy — pull it back and let the frames sit still:

<div data-refrakt="darkroom" data-rf-options='{
  "exposure": { "grain": 0.08, "breathing": false }
}'>

05 Product vitrine — multi-instance

Two boxed sliders on one page, each a different look, both opening a shared de-refracting lightbox on click. All instances render through one shared canvas and one texture budget (see texture memory), so a page of vitrines stays as cheap as a single hero.

<div id="vitrine-lookbook" data-refrakt="atelier" data-rf-options='{
  "layout":   { "mode": "lens" },
  "lightbox": { "enabled": true }
}'>
  <!-- .rf-slide children… -->
</div>

<div id="vitrine-details" data-refrakt="boardroom" data-rf-options='{
  "lightbox": { "enabled": true }
}'>
  <!-- .rf-slide children… -->
</div>

Boxed instances need an explicit height from your page CSS — for example #vitrine-lookbook { height: 480px; } or an aspect-ratio. Refrakt fills whatever box you give it.

06 Frosted testimonials

Quotes behind condensation. The frost element runs at near-full coverage and the pointer is the light source: moving the cursor wipes a warm, clear patch through the glass to reveal the face behind the words. Put the quote in the figcaption — it is real DOM text, always crisp above the frost.

<div data-refrakt="frost"
     style="--rf-ink:#10222b; --rf-paper:#e9f1f4;"
     data-rf-options='{
  "glass":  { "frost": { "coverage": 0.95 } },
  "light":  { "followPointer": 0.5, "clearRadius": 0.65 },
  "motion": { "autoplay": { "enabled": true, "interval": 9000, "pauseOnHover": true } },
  "text":   { "parallax": 0.1 }
}'>
  <figure class="rf-slide">
    <img src="img/client-01-lqip.jpg" data-rf-src="img/client-01.jpg"
         alt="Portrait of Amara Osei">
    <figcaption class="rf-text">
      <blockquote><p>“They rebuilt our brand in eight weeks.”</p></blockquote>
      <p>Amara Osei — COO, Meridian</p>
    </figcaption>
  </figure>
</div>

07 Typography splash

The DOM text layer leads and the imagery supports. Headlines are your own HTML — selectable, crawlable, styled by your CSS — and with text.rgbEcho on they shear into red/blue echoes in exact sync with the image tear beneath them. The Spectrum bar replaces dots: dispersed light condensing to a single white stripe as each slide settles. Size the headings huge in your page CSS; the engine only moves them.

<div data-refrakt="spectra"
     style="--rf-ink:#111111; --rf-paper:#f4f4f0;">
  <figure class="rf-slide">
    <img src="img/issue-01-lqip.jpg" data-rf-src="img/issue-01.jpg"
         alt="Issue 01 cover backdrop">
    <figcaption class="rf-text">
      <h2>THE COLOR ISSUE</h2>
      <p>Nº 01 — Spring</p>
    </figcaption>
  </figure>
</div>

08 Event & music

eclipse with the light bolted to the crowd’s hand: at followPointer 0.85 the cursor is the light source, relighting deep glossy flutes, caustics and bloom in real time, with dispersion raised so fast drags flash rainbow fringes across artist imagery. Loud on purpose — the audience is here for the show.

<div data-refrakt="eclipse"
     style="--rf-ink:#f5efe6; --rf-paper:#050505;"
     data-rf-options='{
  "light":      { "followPointer": 0.85, "intensity": 1.2 },
  "dispersion": { "amount": 0.45, "maxTear": 0.55 },
  "nav":        { "counter": true }
}'>

09 Showreel

Self-hosted video behind light reeded glass. Clips autoplay muted when centered, pause when they leave, and the flutes give resting frames a projection-booth texture without hiding the footage. preload 2 keeps the next two clips’ posters warm so drags never land on an empty frame. See the media guide for encoding requirements.

<div data-refrakt="client-safe"
     style="--rf-ink:#eeeeee; --rf-paper:#101014;"
     data-rf-options='{
  "glass": { "kind": "reeded", "ior": 0.1,
             "reeded": { "frequency": 14, "depth": 0.55, "sheen": 0.45 } },
  "media": { "preload": 2 },
  "nav":   { "counter": true, "progressRule": true, "spectrum": false }
}'>
  <figure class="rf-slide"
          data-rf-video="video/reel-01.mp4"
          data-rf-poster="img/reel-01-poster.jpg">
    <img src="img/reel-01-lqip.jpg" alt="Reel 01 — title sequence">
    <figcaption class="rf-text"><h2>Title Sequence</h2></figcaption>
  </figure>
  <!-- …one figure per clip -->
</div>

10 Client-safe starter

The factory defaults, stated as a recipe on purpose. Refraction is confined to subtle reeded side ribs and a barely-there drag shimmer; dispersion.maxTear is capped at 0.15, comfortably below the ~0.3 threshold where tearing becomes visible, so no gesture can ever shear the image. Grain sits at 0.06 — invisible on white backgrounds. This is the configuration to ship when the imagery must stay literal and the review chain is long.

<div data-refrakt="client-safe">

That attribute is the entire configuration — client-safe is the default option set, so it is equivalent to an empty data-rf-options='{}'. Start here, then raise one namespace at a time in the Optics Lab until the client blinks.

11 Reduced-motion-first

For audiences where vestibular safety is the brief — healthcare, government, accessibility-led brands. Setting a11y.reducedMotion to "always" makes the reduced experience the only experience, for every visitor, regardless of OS setting: transitions become gentle crossfades, tear and echo effects are suppressed, and autoplay keeps its visible pause control (WCAG 2.2.2). Zeroing the remaining texture effects makes the stillness deliberate rather than accidental.

<div data-refrakt="client-safe" data-rf-options='{
  "a11y":     { "reducedMotion": "always" },
  "exposure": { "grain": 0, "bloom": 0 },
  "motion":   { "autoplay": { "enabled": false } }
}'>

The default, "auto", already honors prefers-reduced-motion per visitor on every preset — "always" is for sites that choose stillness as policy.

12 Boxed in-page carousel

Not every slider is a hero. This one lives inside a card between paragraphs: lens layout so neighbors peek in from the edges, arrows and a counter for explicit paging, a hairline progress rule, and a lightbox for the full-size view. The container is an ordinary block element — give it a height in your page CSS and place it anywhere.

<div class="card-slider" data-refrakt="client-safe" data-rf-options='{
  "layout":   { "mode": "lens", "gap": 0.1, "sideScale": 0.8 },
  "nav":      { "arrows": true, "counter": true, "spectrum": false,
                "progressRule": true },
  "lightbox": { "enabled": true }
}'>
  <!-- .rf-slide children… -->
</div>
/* your page CSS */
.card-slider { height: 420px; }

Avoid transform, filter, or backdrop-filter on the card or its ancestors — they create a CSS containing block that offsets the fixed shared canvas. Details in troubleshooting.