
tte.js is a JavaScript library for animating text and ASCII art with 37 terminal-style effects on HTML Canvas.
The built-in set includes decrypt, matrix, laseretch, smoke, fireworks, VHS distortion, rain, and 30 other effects.
Playback can stop, restart, loop, switch effects, or reproduce a seeded animation. The source text stays in the document beneath an aria-hidden Canvas, and reduced-motion mode renders the final frame.
Features
- Plain JavaScript ES modules with no runtime dependencies or WebAssembly.
- Configurable duration, colors, frame rate, looping, and Canvas background.
- Seeded randomization for repeatable animation runs.
- Playback controls for play, stop, restart, effect switching, and cleanup.
prefers-reduced-motionhandling.- Declarative
<text-effect>custom element. - Custom effect registration through
registerEffect(). - Exported effect registry and color/text utility functions for extension work.
Available Effects
beamsbinarypathblackholebouncyballsbubblesburncolorshiftcrumbledecrypterrorcorrectexpandfireworkshighlightlaseretchmatrixmiddleoutorbittingvolleyoverflowpourprintrainrandomsequenceringsscatteredsliceslidesmokespotlightssprayswarmsweepsynthgridthunderstormunstablevhstapewaveswipe
How To Use tte.js
Installation
tte.js ships as JavaScript modules and needs no build step. It requires a modern browser with JavaScript module and Canvas capabilities. Clone the repository into your project, or copy its src/ directory.
git clone https://github.com/flaviocopes/tte-js
Basic Usage
Use a <pre> element when the text or ASCII art must preserve spaces and line breaks. The source element defines the font, dimensions, and layout. Import createTextEffect() from src/index.js. Playback starts automatically unless autoplay is set to false.
<pre id="terminal-title">WELCOME TO THE TERMINAL</pre>
<script type="module">
import { createTextEffect } from './tte-js/src/index.js';
const animation = createTextEffect('#terminal-title', {
effect: 'laseretch',
duration: 2400,
colors: ['#8a5cff', '#00d1ff', '#ffffff'],
});
</script>
Control Playback
The object returned by createTextEffect() has the documented playback and cleanup methods below. With loop: true, the Promise returned by play() or restart() stays pending until playback is stopped.
play(): Starts a new run and returns a Promise.stop(): Stops the current run.restart(): Restarts the current effect and returns a Promise.setEffect(name, options = {}): Changes the effect, applies optional configuration changes, and restarts playback.destroy(): Stops playback, disconnects resize handling, removes the generated Canvas, and restores the source element styles.
await animation.play();
animation.stop();
await animation.restart();
await animation.setEffect('decrypt');
animation.destroy();
Configuration Options
effect(string, default:'laseretch'): Selects a built-in or registered effect.duration(number, default:2400): Sets the animation duration in milliseconds.colors(string[]): Sets the final text gradient. Built-in effects fall back to['#8a5cff', '#00d1ff', '#ffffff'].hotColors(string[]): Sets the laser cooling colors.laseretchfalls back to['#fff4b0', '#ff9d2e', '#ff3d1f'].laserColors(string[]): Sets the laser beam gradient.laseretchfalls back to['#ffffff', '#376cff'].seed(string | number, default:1): Controls deterministic randomization for repeatable runs.fps(number, default:60): Limits rendering frequency.loop(boolean, default:false): Repeats the selected effect.autoplay(boolean, default:true): Starts playback after initialization.respectReducedMotion(boolean, default:true): Renders the final frame whenprefers-reduced-motion: reduceis active.background(string | null, default:null): Fills the Canvas before each frame is drawn.
Repeat A Seeded Animation
Set seed when a randomized effect should reproduce its character choices, particle motion, and movement plan.
const animation = createTextEffect('#terminal-title', {
effect: 'matrix',
seed: 42,
duration: 3000,
});
Loop An Effect
const animation = createTextEffect('#terminal-title', {
effect: 'decrypt',
loop: true,
});
Switch Effects At Runtime
setEffect() accepts configuration changes for the next run.
await animation.setEffect('matrix', {
duration: 3200,
colors: ['#0b3d20', '#00c853', '#b9ffcb'],
});
Use The “ Custom Element
Register the custom element once. defineTextEffectElement() accepts an optional custom tag name and defaults to text-effect. The element maps effect, duration, colors, loop, and seed to controller options.
<script type="module">
import { defineTextEffectElement } from './tte-js/src/index.js';
defineTextEffectElement();
</script>
<text-effect
effect="laseretch"
duration="2400"
colors="#8a5cff,#00d1ff,#ffffff"
>
WELCOME TO THE TERMINAL
</text-effect>
Custom Element Methods
const effect = document.querySelector('text-effect');
await effect.play();
await effect.restart();
effect.stop();
Register A Custom Effect
registerEffect(name, factory, metadata = {}) registers another effect name. The factory receives grid, options, and a seeded random function. Return an object with a render(progress, elapsed) method.
import {
createTextEffect,
registerEffect,
} from './tte-js/src/index.js';
registerEffect('appear', ({ grid }) => ({
render(progress) {
return {
cells: grid.visibleCells.map((cell) => ({
...cell,
alpha: progress,
color: '#ffffff',
})),
particles: [],
};
},
}));
const animation = createTextEffect('#terminal-title', {
effect: 'appear',
});
Alternatives & Related Resources
- Text Glitch (Scramble) Animation In JavaScript – Glitched Writer
- Classic Terminal Typing Effect In JavaScript – Console Typer
- Terminal Style Text Print Animation In JavaScript – tinytyper
- Terminal-style Text Typing Animation – TypeWriting.js
- 10 Best Typewriter Text Animation JavaScript Libraries







