Textmode Vibes That Move (ASCII → Animated Image)

• Design, Terminal

Zine‑ish, textmode, ANSI/ASCII—think Phrack meets demoscene. You can get that gritty moving background vibe without CSS or JavaScript by pre‑rendering the motion into an animated image (WebP/GIF) and embedding it like any other image. This post shows a minimal Linux toolchain: generate ASCII, render to images, pan subtly across frames, then assemble into an animation.

Inspiration: colonelpanic.tech

Overview

  1. Create a repeating ASCII tile (banner, symbols, or a converted image).
  2. Rasterize the ASCII into a high‑contrast image.
  3. Generate animation frames by panning the tile.
  4. Assemble frames into animated WebP (with GIF fallback).

Tools

  • figlet or toilet — banner text.
  • chafa or jp2a — convert images to ASCII (optional).
  • magick (ImageMagick) — rasterize text and build animations.
  • ffmpeg (optional) — alternative encoder, post‑processing.

1) Build an ASCII tile

Make a noisy, repeatable pattern. Use a mix of symbols to mimic photocopy texture, plus a title banner:

mkdir -p work && cd work
printf '%s\n' "@@@@ #### **** //// \\\\ \\// -- ++ == ~~" \
"@@@@ #### **** //// \\\\ \\// -- ++ == ~~" \
"@@@@ #### **** //// \\ \\// -- ++ == ~~" \
"@@@@ #### **** //// \\ \\// -- ++ == ~~" \
> noise.txt

figlet -f slant "ZINE" > banner.txt
cat banner.txt noise.txt banner.txt noise.txt > tile.txt

Or convert any source image into ASCII (coarse, high contrast works best):

# Example using chafa (install via package manager)
chafa --symbols 2x2 --size 120x40 /images/originals/sample.jpg > tile.txt

2) Rasterize the ASCII to an image

Render the ASCII with a monospace font to a large tile you can pan across. The label:@file trick reads text directly:

magick -background black -fill white \
-font DejaVu-Sans-Mono -pointsize 22 \
label:@tile.txt tile.png

If the line breaks are too tight or too loose, adjust -pointsize or pad with -splice/-extent:

magick tile.png -bordercolor black -border 20x20 tile-padded.png

3) Generate subtle motion frames

Loop the tile on a larger canvas and crop moving windows to simulate a drifting background:

magick tile-padded.png -virtual-pixel tile -distort SRT 0 \
-resize 1600x900! large-tile.png

mkdir frames
# 48 frames of slow diagonal pan
for i in $(seq 0 47); do 
x=$((i*6)); y=$((i*4));
magick large-tile.png -crop 1280x720+${x}+${y} +repage frames/f-$(printf %02d $i).png
done

4) Assemble into animated WebP (and GIF fallback)

# WebP (small, widely supported in modern browsers)
magick -delay 7 -loop 0 frames/f-*.png -quality 85 zine-bg.webp

# GIF fallback (bigger, universal)
magick -delay 7 -loop 0 -dither FloydSteinberg -colors 32 \
frames/f-*.png zine-bg.gif

Tip: If the motion feels too fast/slow, tweak -delay or change the per‑frame offset in the loop. Keep the movement subtle—your eye should feel texture, not distraction.

Embed on the blog

<picture>
<source type="image/webp" srcset="images/zine-bg-800w.webp 800w, images/zine-bg-1200w.webp 1200w">
<img src="images/zine-bg-800w.gif" alt="Animated ASCII zine‑style texture" 
width="800" height="450" loading="lazy" decoding="async">
</picture>

If you want it as a hero background behind text without CSS, place the image above your content as a figure with a descriptive caption; keep contrast high for readability.

Live Demo (click to start)

Demo note: No hotlinking here. Generate your own texture with figlet (banner art) or by converting an image to ASCII (chafa/jp2a), then assemble frames and embed your animated WebP locally using the steps above.

Variations

  • ASCII from video: Use ffmpeg to extract frames, chafa/jp2a to ASCII, then assemble.
  • Terminal capture: Record a session with asciinema and export to GIF/MP4 for authentic keystroke motion.
  • Halftone feel: Render text in off‑white on near‑black and add grain via +noise before encoding.

Notes on licensing and performance

  • Don’t hotlink other sites’ assets; generate your own textures.
  • Animated WebP is usually much smaller than GIF at similar quality.
  • Keep motion gentle to avoid eye strain and preserve readability.