Focus frame
One word at a time comes into focus inside gliding corner brackets while the rest stay soft.
- enhancer
- loop
- hover
- words
- blur
- since 0.2
Background Studio: tune it below, then copy the code
Your system asks for reduced motion: the demo shows its final state and nothing moves.
Live demo
Focus frame example
Look at one word at a time
Look at one word at a time
Code
It follows the controls above: change an option and the code changes with it.
<link rel="stylesheet" href="/axi0/motion/motion.css?v=6">
<script src="/axi0/motion/motion.js?v=10" defer></script>
<p class="demo-big" data-motion="focus-frame">Look at one word at a time</p>
import { FocusFrame } from "./motion/react/FocusFrame";
<FocusFrame>Your content</FocusFrame>
<script setup lang="ts">
import FocusFrame from "./motion/vue/FocusFrame.vue";
</script>
<template>
<FocusFrame>Your content</FocusFrame>
</template>
const el = document.querySelector("#title");
el.dataset.motion = "focus-frame";
The wrappers: FocusFrame.tsx (React, TypeScript) and FocusFrame.vue (Vue). Both render the same attributes as the HTML; the loader does the rest.
Options
| Attribute | Default | What it does |
|---|---|---|
data-motion-mode | auto | Focus moves |
data-motion-interval | 1500 | Time per word |
data-motion-blur | 4 | Blur of the other words |
data-motion-color | #f6a04d | Bracket color |
Accessibility
The words stay real text, readable and selectable; the brackets are aria-hidden and move with transforms, so nothing reflows. Reduced motion shows every word sharp and no brackets. The loop stops off screen and in hidden tabs.
Size
focus-frame.js is 1.3 KB gzip, with text-kit.js 2.6 KB it needs. A page loads the loader (2.7 KB) and core.js (1.4 KB) once, whatever it uses.