AI CSS Animations

Flip Dot Sign Text

A bus stop flip-dot board turns from CITY to 2 MIN and back, each disc flipping edge-on and landing on its other face in a wave across the columns. A 5 by 7 bitmap built into the markup.

Also known as: flip dot display css, bus destination sign animation, dot matrix text animation, pixel text animation.

HTML

<div class="txt-flip-dot-sign" aria-label="City, due in 2 minutes">
  <span class="txt-flip-dot-sign-board" aria-hidden="true"><i></i><i class="txt-flip-dot-sign-up" style="--x: 1"></i><i class="txt-flip-dot-sign-up" style="--x: 2"></i><i class="txt-flip-dot-sign-up" style="--x: 3"></i><i class="txt-flip-dot-sign-dn" style="--x: 4"></i><i class="txt-flip-dot-sign-dn" style="--x: 5"></i><i class="txt-flip-dot-sign-dn" style="--x: 6"></i><i></i><i></i><i></i><i class="txt-flip-dot-sign-dn" style="--x: 10"></i><i class="txt-flip-dot-sign-dn" style="--x: 11"></i><i class="txt-flip-dot-sign-on"></i><i></i><i></i><i class="txt-flip-dot-sign-dn" style="--x: 15"></i><i class="txt-flip-dot-sign-on"></i><i class="txt-flip-dot-sign-dn" style="--x: 17"></i><i class="txt-flip-dot-sign-dn" style="--x: 18"></i><i class="txt-flip-dot-sign-on"></i><i class="txt-flip-dot-sign-up" style="--x: 20"></i><i class="txt-flip-dot-sign-on"></i><i></i><i></i><i class="txt-flip-dot-sign-up" style="--x: 24"></i><i class="txt-flip-dot-sign-dn" style="--x: 25"></i><i></i><i></i><i class="txt-flip-dot-sign-up" style="--x: 28"></i><i class="txt-flip-dot-sign-up" style="--x: 0"></i><i></i><i></i><i class="txt-flip-dot-sign-dn" style="--x: 3"></i><i class="txt-flip-dot-sign-up" style="--x: 4"></i><i></i><i></i><i class="txt-flip-dot-sign-dn" style="--x: 7"></i><i></i><i></i><i></i><i class="txt-flip-dot-sign-dn" style="--x: 11"></i><i class="txt-flip-dot-sign-up" style="--x: 12"></i><i class="txt-flip-dot-sign-up" style="--x: 13"></i><i></i><i class="txt-flip-dot-sign-up" style="--x: 15"></i><i class="txt-flip-dot-sign-up" style="--x: 16"></i><i class="txt-flip-dot-sign-dn" style="--x: 17"></i><i></i><i></i><i class="txt-flip-dot-sign-up" style="--x: 20"></i><i class="txt-flip-dot-sign-dn" style="--x: 21"></i><i></i><i></i><i class="txt-flip-dot-sign-up" style="--x: 24"></i><i class="txt-flip-dot-sign-on"></i><i></i><i></i><i class="txt-flip-dot-sign-up" style="--x: 28"></i><i></i><i></i><i></i><i class="txt-flip-dot-sign-dn" style="--x: 3"></i><i class="txt-flip-dot-sign-up" style="--x: 4"></i><i></i><i></i><i></i><i></i><i></i><i></i><i class="txt-flip-dot-sign-dn" style="--x: 11"></i><i class="txt-flip-dot-sign-up" style="--x: 12"></i><i></i><i class="txt-flip-dot-sign-up" style="--x: 14"></i><i></i><i class="txt-flip-dot-sign-up" style="--x: 16"></i><i class="txt-flip-dot-sign-dn" style="--x: 17"></i><i></i><i></i><i class="txt-flip-dot-sign-up" style="--x: 20"></i><i></i><i class="txt-flip-dot-sign-dn" style="--x: 22"></i><i></i><i class="txt-flip-dot-sign-on"></i><i></i><i class="txt-flip-dot-sign-up" style="--x: 26"></i><i></i><i class="txt-flip-dot-sign-up" style="--x: 28"></i><i></i><i></i><i></i><i class="txt-flip-dot-sign-on"></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i class="txt-flip-dot-sign-dn" style="--x: 11"></i><i class="txt-flip-dot-sign-up" style="--x: 12"></i><i></i><i class="txt-flip-dot-sign-up" style="--x: 14"></i><i></i><i class="txt-flip-dot-sign-up" style="--x: 16"></i><i class="txt-flip-dot-sign-dn" style="--x: 17"></i><i></i><i></i><i class="txt-flip-dot-sign-up" style="--x: 20"></i><i></i><i></i><i class="txt-flip-dot-sign-dn" style="--x: 23"></i><i class="txt-flip-dot-sign-up" style="--x: 24"></i><i></i><i></i><i class="txt-flip-dot-sign-up" style="--x: 27"></i><i class="txt-flip-dot-sign-up" style="--x: 28"></i><i></i><i></i><i class="txt-flip-dot-sign-up" style="--x: 2"></i><i class="txt-flip-dot-sign-dn" style="--x: 3"></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i class="txt-flip-dot-sign-dn" style="--x: 11"></i><i class="txt-flip-dot-sign-up" style="--x: 12"></i><i></i><i></i><i></i><i class="txt-flip-dot-sign-up" style="--x: 16"></i><i class="txt-flip-dot-sign-dn" style="--x: 17"></i><i></i><i></i><i class="txt-flip-dot-sign-up" style="--x: 20"></i><i></i><i></i><i class="txt-flip-dot-sign-dn" style="--x: 23"></i><i class="txt-flip-dot-sign-up" style="--x: 24"></i><i></i><i></i><i></i><i class="txt-flip-dot-sign-up" style="--x: 28"></i><i></i><i class="txt-flip-dot-sign-up" style="--x: 1"></i><i></i><i class="txt-flip-dot-sign-dn" style="--x: 3"></i><i></i><i></i><i></i><i class="txt-flip-dot-sign-dn" style="--x: 7"></i><i></i><i></i><i></i><i class="txt-flip-dot-sign-dn" style="--x: 11"></i><i class="txt-flip-dot-sign-up" style="--x: 12"></i><i></i><i></i><i></i><i class="txt-flip-dot-sign-up" style="--x: 16"></i><i class="txt-flip-dot-sign-dn" style="--x: 17"></i><i></i><i></i><i class="txt-flip-dot-sign-up" style="--x: 20"></i><i></i><i></i><i class="txt-flip-dot-sign-dn" style="--x: 23"></i><i class="txt-flip-dot-sign-up" style="--x: 24"></i><i></i><i></i><i></i><i class="txt-flip-dot-sign-up" style="--x: 28"></i><i class="txt-flip-dot-sign-up" style="--x: 0"></i><i class="txt-flip-dot-sign-up" style="--x: 1"></i><i class="txt-flip-dot-sign-up" style="--x: 2"></i><i class="txt-flip-dot-sign-up" style="--x: 3"></i><i class="txt-flip-dot-sign-on"></i><i class="txt-flip-dot-sign-dn" style="--x: 5"></i><i class="txt-flip-dot-sign-dn" style="--x: 6"></i><i></i><i></i><i></i><i class="txt-flip-dot-sign-dn" style="--x: 10"></i><i class="txt-flip-dot-sign-dn" style="--x: 11"></i><i class="txt-flip-dot-sign-on"></i><i></i><i></i><i></i><i class="txt-flip-dot-sign-up" style="--x: 16"></i><i class="txt-flip-dot-sign-dn" style="--x: 17"></i><i></i><i class="txt-flip-dot-sign-up" style="--x: 19"></i><i class="txt-flip-dot-sign-up" style="--x: 20"></i><i class="txt-flip-dot-sign-up" style="--x: 21"></i><i></i><i class="txt-flip-dot-sign-dn" style="--x: 23"></i><i class="txt-flip-dot-sign-up" style="--x: 24"></i><i></i><i></i><i></i><i class="txt-flip-dot-sign-up" style="--x: 28"></i></span>
</div>

CSS

.txt-flip-dot-sign {
  --c: var(--txt-color, #3b82f6);
  font-size: calc(var(--txt-size, 32px) * 1);
  font-family: system-ui, sans-serif;
  font-weight: 700;
  line-height: 1.2;
  display: inline-block;
  padding: 0.3em;
  border-radius: 0.35em;
  background: linear-gradient(#2a2a2a, #171717);
  box-shadow: inset 0 0 0 1px rgb(255 255 255 / 0.07), 0 0.4em 1em -0.5em rgb(0 0 0 / 0.5);
  --t: 7s;
  --on: color-mix(in srgb, var(--c) 15%, #f4e04a);}
.txt-flip-dot-sign-board {
  display: grid;
  grid-template-columns: repeat(29, 0.24em);
  grid-auto-rows: 0.24em;
  gap: 0.05em;
  padding: 0.2em 0.25em;
  border-radius: 0.15em;
  background: #0a0a0a;
}
.txt-flip-dot-sign-board i {
  border-radius: 50%;
  background: radial-gradient(circle at 35% 35%, #2c2c2c, #151515);
}
.txt-flip-dot-sign-board .txt-flip-dot-sign-on {
  background: radial-gradient(circle at 35% 35%, color-mix(in srgb, var(--on) 60%, #fff), var(--on) 70%);
}
.txt-flip-dot-sign-up, .txt-flip-dot-sign-dn {
  animation: txt-flip-dot-sign-up var(--t) infinite;
  animation-delay: calc(var(--x) * 0.025s);
}
.txt-flip-dot-sign-dn { animation-name: txt-flip-dot-sign-dn; }
@keyframes txt-flip-dot-sign-up {
  0%, 42% { transform: none; background: radial-gradient(circle at 35% 35%, #2c2c2c, #151515); animation-timing-function: ease-in; }
  44% { transform: scaleX(0.05); background: radial-gradient(circle at 35% 35%, #2c2c2c, #151515); }
  44.01% { transform: scaleX(0.05); background: radial-gradient(circle at 35% 35%, color-mix(in srgb, var(--on) 60%, #fff), var(--on) 70%); animation-timing-function: cubic-bezier(0.34, 1.4, 0.64, 1); }
  47%, 92% { transform: none; background: radial-gradient(circle at 35% 35%, color-mix(in srgb, var(--on) 60%, #fff), var(--on) 70%); animation-timing-function: ease-in; }
  94% { transform: scaleX(0.05); background: radial-gradient(circle at 35% 35%, color-mix(in srgb, var(--on) 60%, #fff), var(--on) 70%); }
  94.01% { transform: scaleX(0.05); background: radial-gradient(circle at 35% 35%, #2c2c2c, #151515); animation-timing-function: cubic-bezier(0.34, 1.4, 0.64, 1); }
  97%, 100% { transform: none; background: radial-gradient(circle at 35% 35%, #2c2c2c, #151515); }
}
@keyframes txt-flip-dot-sign-dn {
  0%, 42% { transform: none; background: radial-gradient(circle at 35% 35%, color-mix(in srgb, var(--on) 60%, #fff), var(--on) 70%); animation-timing-function: ease-in; }
  44% { transform: scaleX(0.05); background: radial-gradient(circle at 35% 35%, color-mix(in srgb, var(--on) 60%, #fff), var(--on) 70%); }
  44.01% { transform: scaleX(0.05); background: radial-gradient(circle at 35% 35%, #2c2c2c, #151515); animation-timing-function: cubic-bezier(0.34, 1.4, 0.64, 1); }
  47%, 92% { transform: none; background: radial-gradient(circle at 35% 35%, #2c2c2c, #151515); animation-timing-function: ease-in; }
  94% { transform: scaleX(0.05); background: radial-gradient(circle at 35% 35%, #2c2c2c, #151515); }
  94.01% { transform: scaleX(0.05); background: radial-gradient(circle at 35% 35%, color-mix(in srgb, var(--on) 60%, #fff), var(--on) 70%); animation-timing-function: cubic-bezier(0.34, 1.4, 0.64, 1); }
  97%, 100% { transform: none; background: radial-gradient(circle at 35% 35%, color-mix(in srgb, var(--on) 60%, #fff), var(--on) 70%); }
}
@media (prefers-reduced-motion: reduce) {
  .txt-flip-dot-sign, .txt-flip-dot-sign *, .txt-flip-dot-sign *::before, .txt-flip-dot-sign *::after { animation: none !important; }
  .txt-flip-dot-sign-board .txt-flip-dot-sign-dn { background: radial-gradient(circle at 35% 35%, color-mix(in srgb, var(--on) 60%, #fff), var(--on) 70%); }
}

@media (prefers-reduced-motion: reduce) {
  .txt-flip-dot-sign, .txt-flip-dot-sign *, .txt-flip-dot-sign::before, .txt-flip-dot-sign::after, .txt-flip-dot-sign *::before, .txt-flip-dot-sign *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

Customizing this snippet

  • Color: set --txt-color on the element or a parent. Currently previewing #3b82f6.
  • Font size: set --txt-size. Every other dimension is in em, so the whole thing scales together. Currently previewing 40px.
  • Speed: change the duration on the transition or animation shorthand. Staggered delays are relative, so they keep their rhythm.
  • Reduced motion: the rule at the end of the CSS turns the motion off for people who asked their OS for less of it. Keep it.

Similar text animations