Distortion✨ Premium

Dot Matrix Printer

A perforated paper ticket whose lines print one by one, in order, then print again each time the ticket comes back on screen.

CSSAnimationPrint

Updated

This effect is part of Effect.Labs — 840 vanilla effects, some free, some premium. Distortion has 31 effects, including 5 free. Explore the category →

3 usage examples

Receipt coming out after "Pay" on a food truck kiosk — Dot Matrix Printer example 1

① Receipt coming out after "Pay" on a food truck kiosk

WhenOn a food truck's ordering kiosk, the customer checks the order and taps "Pay €22.00": the receipt appears under the printer slot and prints the order number, the items, the total, then "THANK YOU".
WhyLine-by-line printing confirms the payment in a concrete way, like a real kiosk; the order number, printed first, is what the customer needs to remember.
Settings--dmp-w: 226px, --dmp-size: 11.5px, --dmp-start: .15s, --dmp-gap: .28s; columns aligned by the scene (white-space: pre on the lines). The click only shows the root, hidden before.
A weather station's night log, printed when you scroll down to it — Dot Matrix Printer example 2

② A weather station's night log, printed when you scroll down to it

WhenOn a mountain weather station's page, the current temperature and the night's curve fill the top. Scrolling down, the visitor reaches the printed log: six hourly lines that print as it arrives.
WhyReplaying on arrival brings an otherwise dry table of readings to life; the paper-listing look fits the idea of a device recording all night long.
Settings--dmp-w: 100%, --dmp-size: 12.5px, --dmp-start: .1s, --dmp-gap: .3s, six lines. In the scene, a click scrolls the panel down to the log; the effect's IntersectionObserver replays the print.
Paper listing behind an "Our story" section — Dot Matrix Printer example 3

③ Paper listing behind an "Our story" section

WhenOn the site of a software maker for craftspeople, the "Our story" section sits on a large paper listing that prints a 1983 BASIC program; the opaque panel on the right carries the title, the story and three dates.
WhyThe listing tells the company's origin without a photo: the first program appears while you read the story. The opaque panel keeps the text readable above the paper.
SettingsRoot in position: absolute; inset: 0, paper at height: 100%, --dmp-w: 100%, --dmp-size: 13px, --dmp-gap: .24s, eight lines (the most handled without a per-line setting).

How it works

.dmp-paper draws the paper: ivory background, grey edge, red margin 20 px from the left edge, and two columns of 16 tractor-feed holes (.dmp-holes-l, .dmp-holes-r). The text lines, in 13 px Courier New, sit inside .dmp-lines.

Each .dmp-line starts invisible and follows the dmpPrint animation (0.3 s): it appears while rising by 4 px. Its start is --dmp-start + rank × --dmp-gap, i.e. 0.5 s, 1.2 s, 1.9 s, 2.6 s, 3.3 s for the five lines provided; the rank is set on the first eight lines. The old version counted the hole columns among the lines: lines 4 and 5 showed on load, before the first three. That is fixed.

A small script watches each ticket with an IntersectionObserver (30 % threshold): when the ticket comes back on screen, its lines are reset and the print replays. Each copy of the effect is tracked separately; the script adds nothing to window and runs no loop.

Accessibility

  • Real text: every line is in the HTML from the start; a screen reader reads them without waiting for the print. The holes, decorative, have aria-hidden="true".
  • Contrast: #333 ink on ivory paper, a ratio of about 12:1.
  • Reduced motion: under prefers-reduced-motion: reduce, the ticket shows complete at once; replaying when it comes back on screen has no visible effect.
  • Nothing to operate: the effect creates no focusable element. The replay depends on scrolling, never on hovering.

Browser compatibility

CSS + 0.7 KB of JavaScript, no dependency. The most recent feature is IntersectionObserver (Chrome 51, Firefox 55, Safari 12.1 according to MDN data); without it, the print plays once on load. Measured in Chromium 151, Firefox 153 and WebKit 26.5: at 1 s only line 1 is visible, at 3.8 s all five lines, in order; with two tickets, bringing the second one back only replays the second.

Chrome 51+✓ Full (measured)
Firefox 55+✓ Full (measured)
Safari 12.1+✓ Full (measured in WebKit)
Edge 79+✓ Full
Mobile iOS 12.2+✓ Full
Android Chrome 51+✓ Full

Without JavaScript, the print plays once on load, even if the ticket is off screen. Without CSS animations, the lines would stay invisible: the reduced-motion rule shows them; for always-visible text, remove the animation from .dmp-line.

The code

HTML structure to paste into your page (the CSS + JS come with your purchase):

index.html — structure
<div class="fx-0278-root">
  <div class="dmp-paper">
    <div class="dmp-holes dmp-holes-l" aria-hidden="true">
      <span></span>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
    </div>
    <div class="dmp-holes dmp-holes-r" aria-hidden="true">
      <span></span>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
    </div>
    <div class="dmp-lines">
      <div class="dmp-line">INVOICE #00142</div>
      <div class="dmp-line">Date: 1989-03-15</div>
      <div class="dmp-line">Item: Floppy Disk x10</div>
      <div class="dmp-line">Total: $24.99</div>
      <div class="dmp-line">*** THANK YOU ***</div>
    </div>
  </div>
</div>

One-time payment, no subscription — the code is yours forever

Customize

Options passed to the API or data-* attributes:

Option / propertyDefaultEffect
Lines (HTML — <div class="dmp-line"> inside .dmp-lines) 5 lines Up to 8 lines follow one another on their own; beyond that, set the rank: style="--dmp-i: 8". To align columns, add white-space: pre.
Pace (CSS — --dmp-start, --dmp-gap) 0.5 s, then 0.7 s between lines 0.1 s and 0.25 s for a quick till receipt; a 1 s gap for a slow, noisy printer.
Width (CSS — --dmp-w) 280 px 100% fills the parent; with a fixed height on .dmp-paper, the paper covers a whole area.
Paper and ink (CSS — --dmp-paper, --dmp-ink) ivory, #333 Green printer paper #e8f3e3, purple ink #4c1d95 for a till-stamp look.
Text size (CSS — --dmp-size) 13 px 11 to 12 px in a narrow receipt; line height stays at twice the size.
Replay on return (JS — threshold) 0.3 (30 % of the ticket visible) 0.6 waits until the ticket is well in view; remove the script for a single print on load.
Demo frame (CSS — --dmp-page, --dmp-root-h) #0a0a0f, at least 300 px tall transparent and 0 drop the ticket into your page.

FAQ

That is on purpose: each time the ticket comes back on screen (30 % visible), the script resets its lines. For a single print, remove the JavaScript; the CSS animation will play once on load.
Yes: keep the ticket in display: none and show it when you want. An element that becomes visible replays its CSS animations: the lines then print from the first one.
No. Each .fx-0278-root has its own observer; bringing one ticket back on screen only replays that one. The old version only tracked the first ticket on the page.