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
- Create a repeating ASCII tile (banner, symbols, or a converted image).
- Rasterize the ASCII into a high‑contrast image.
- Generate animation frames by panning the tile.
- Assemble frames into animated WebP (with GIF fallback).
Tools
figletortoilet— banner text.chafaorjp2a— 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
ffmpegto extract frames,chafa/jp2ato ASCII, then assemble. - Terminal capture: Record a session with
asciinemaand export to GIF/MP4 for authentic keystroke motion. - Halftone feel: Render text in off‑white on near‑black and add grain via
+noisebefore 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.