AI CSS Animations

Mechanical Keyboard Typing

An isometric hairline mechanical keyboard where keycaps press down one after another and spring back, ending on the return key in the accent. Each key is a white box drawn back to front.

Also known as: hairline claude, isometric keyboard animation, keyboard typing animation css.

HTML

<div class="hln-keyboard-typing" role="img" aria-label="Keys pressing on a mechanical keyboard">
  <svg viewBox="-110 -60 220 120" aria-hidden="true">
    <g transform="translate(-23.9 -33.7) scale(1.04)">
      <g><polygon points="-44.24,19 -44.16,18.59 -43.92,18.19 -43.53,17.82 -43,17.5 -3,-2.5 -2.36,-2.76 -1.62,-2.96 -0.83,-3.08 0,-3.12 0.83,-3.08 1.62,-2.96 2.36,-2.76 3,-2.5 89,40.5 89.53,40.82 89.92,41.19 90.16,41.59 90.24,42 90.24,46 90.16,46.41 89.92,46.81 89.53,47.18 89,47.5 49,67.5 48.36,67.76 47.62,67.96 46.83,68.08 46,68.12 45.17,68.08 44.38,67.96 43.64,67.76 43,67.5 -43,24.5 -43.53,24.18 -43.92,23.81 -44.16,23.41 -44.24,23"/><polygon points="89,40.5 89.53,40.82 89.92,41.19 90.16,41.59 90.24,42 90.16,42.41 89.92,42.81 89.53,43.18 89,43.5 49,63.5 48.36,63.76 47.62,63.96 46.83,64.08 46,64.12 45.17,64.08 44.38,63.96 43.64,63.76 43,63.5 -43,20.5 -43.53,20.18 -43.92,19.81 -44.16,19.41 -44.24,19 -44.16,18.59 -43.92,18.19 -43.53,17.82 -43,17.5 -3,-2.5 -2.36,-2.76 -1.62,-2.96 -0.83,-3.08 0,-3.12 0.83,-3.08 1.62,-2.96 2.36,-2.76 3,-2.5"/></g>
      <g><g><polygon points="-9.4,3.5 0,8.2 0,6 -9.4,1.3"/><polygon points="9.4,3.5 0,8.2 0,6 9.4,1.3"/><polygon points="0,-3.4 9.4,1.3 0,6 -9.4,1.3"/></g></g>
      <g><g><polygon points="1.6,9 11,13.7 11,11.5 1.6,6.8"/><polygon points="20.4,9 11,13.7 11,11.5 20.4,6.8"/><polygon points="11,2.1 20.4,6.8 11,11.5 1.6,6.8"/></g></g>
      <g><g><polygon points="12.6,14.5 22,19.2 22,17 12.6,12.3"/><polygon points="31.4,14.5 22,19.2 22,17 31.4,12.3"/><polygon points="22,7.6 31.4,12.3 22,17 12.6,12.3"/></g></g>
      <g><g><polygon points="23.6,20 33,24.7 33,22.5 23.6,17.8"/><polygon points="42.4,20 33,24.7 33,22.5 42.4,17.8"/><polygon points="33,13.1 42.4,17.8 33,22.5 23.6,17.8"/></g></g>
      <g><g><polygon points="34.6,25.5 44,30.2 44,28 34.6,23.3"/><polygon points="53.4,25.5 44,30.2 44,28 53.4,23.3"/><polygon points="44,18.6 53.4,23.3 44,28 34.6,23.3"/></g></g>
      <g><g><polygon points="45.6,31 55,35.7 55,33.5 45.6,28.8"/><polygon points="64.4,31 55,35.7 55,33.5 64.4,28.8"/><polygon points="55,24.1 64.4,28.8 55,33.5 45.6,28.8"/></g></g>
      <g class="hln-keyboard-typing-key" style="--i: 3"><g><polygon points="56.6,36.5 66,41.2 66,39 56.6,34.3"/><polygon points="75.4,36.5 66,41.2 66,39 75.4,34.3"/><polygon points="66,29.6 75.4,34.3 66,39 56.6,34.3"/></g></g>
      <g><g><polygon points="67.6,42 77,46.7 77,44.5 67.6,39.8"/><polygon points="86.4,42 77,46.7 77,44.5 86.4,39.8"/><polygon points="77,35.1 86.4,39.8 77,44.5 67.6,39.8"/></g></g>
      <g><g><polygon points="-20.4,9 -11,13.7 -11,11.5 -20.4,6.8"/><polygon points="-1.6,9 -11,13.7 -11,11.5 -1.6,6.8"/><polygon points="-11,2.1 -1.6,6.8 -11,11.5 -20.4,6.8"/></g></g>
      <g class="hln-keyboard-typing-key" style="--i: 0"><g><polygon points="-9.4,14.5 0,19.2 0,17 -9.4,12.3"/><polygon points="9.4,14.5 0,19.2 0,17 9.4,12.3"/><polygon points="0,7.6 9.4,12.3 0,17 -9.4,12.3"/></g></g>
      <g><g><polygon points="1.6,20 11,24.7 11,22.5 1.6,17.8"/><polygon points="20.4,20 11,24.7 11,22.5 20.4,17.8"/><polygon points="11,13.1 20.4,17.8 11,22.5 1.6,17.8"/></g></g>
      <g><g><polygon points="12.6,25.5 22,30.2 22,28 12.6,23.3"/><polygon points="31.4,25.5 22,30.2 22,28 31.4,23.3"/><polygon points="22,18.6 31.4,23.3 22,28 12.6,23.3"/></g></g>
      <g><g><polygon points="23.6,31 33,35.7 33,33.5 23.6,28.8"/><polygon points="42.4,31 33,35.7 33,33.5 42.4,28.8"/><polygon points="33,24.1 42.4,28.8 33,33.5 23.6,28.8"/></g></g>
      <g class="hln-keyboard-typing-key" style="--i: 1"><g><polygon points="34.6,36.5 44,41.2 44,39 34.6,34.3"/><polygon points="53.4,36.5 44,41.2 44,39 53.4,34.3"/><polygon points="44,29.6 53.4,34.3 44,39 34.6,34.3"/></g></g>
      <g><g><polygon points="45.6,42 55,46.7 55,44.5 45.6,39.8"/><polygon points="64.4,42 55,46.7 55,44.5 64.4,39.8"/><polygon points="55,35.1 64.4,39.8 55,44.5 45.6,39.8"/></g></g>
      <g><g><polygon points="56.6,47.5 66,52.2 66,50 56.6,45.3"/><polygon points="75.4,47.5 66,52.2 66,50 75.4,45.3"/><polygon points="66,40.6 75.4,45.3 66,50 56.6,45.3"/></g></g>
      <g><g><polygon points="-31.4,14.5 -22,19.2 -22,17 -31.4,12.3"/><polygon points="-12.6,14.5 -22,19.2 -22,17 -12.6,12.3"/><polygon points="-22,7.6 -12.6,12.3 -22,17 -31.4,12.3"/></g></g>
      <g><g><polygon points="-20.4,20 -11,24.7 -11,22.5 -20.4,17.8"/><polygon points="-1.6,20 -11,24.7 -11,22.5 -1.6,17.8"/><polygon points="-11,13.1 -1.6,17.8 -11,22.5 -20.4,17.8"/></g></g>
      <g><g><polygon points="-9.4,25.5 0,30.2 0,28 -9.4,23.3"/><polygon points="9.4,25.5 0,30.2 0,28 9.4,23.3"/><polygon points="0,18.6 9.4,23.3 0,28 -9.4,23.3"/></g></g>
      <g class="hln-keyboard-typing-key" style="--i: 2"><g><polygon points="1.6,31 11,35.7 11,33.5 1.6,28.8"/><polygon points="20.4,31 11,35.7 11,33.5 20.4,28.8"/><polygon points="11,24.1 20.4,28.8 11,33.5 1.6,28.8"/></g></g>
      <g><g><polygon points="12.6,36.5 22,41.2 22,39 12.6,34.3"/><polygon points="31.4,36.5 22,41.2 22,39 31.4,34.3"/><polygon points="22,29.6 31.4,34.3 22,39 12.6,34.3"/></g></g>
      <g><g><polygon points="23.6,42 33,46.7 33,44.5 23.6,39.8"/><polygon points="42.4,42 33,46.7 33,44.5 42.4,39.8"/><polygon points="33,35.1 42.4,39.8 33,44.5 23.6,39.8"/></g></g>
      <g><g><polygon points="34.6,47.5 44,52.2 44,50 34.6,45.3"/><polygon points="53.4,47.5 44,52.2 44,50 53.4,45.3"/><polygon points="44,40.6 53.4,45.3 44,50 34.6,45.3"/></g></g>
      <g class="hln-keyboard-typing-key hln-keyboard-typing-ret" style="--i: 4"><g><polygon points="45.6,53 55,57.7 55,55.5 45.6,50.8"/><polygon points="64.4,53 55,57.7 55,55.5 64.4,50.8"/><polygon points="55,46.1 64.4,50.8 55,55.5 45.6,50.8"/></g><polygon class="hln-keyboard-typing-a" points="58,50.2 58.21,50.33 58.37,50.48 58.46,50.63 58.5,50.8 58.46,50.97 58.37,51.12 58.21,51.27 58,51.4 56.2,52.3 55.94,52.41 55.65,52.48 55.33,52.53 55,52.55 54.67,52.53 54.35,52.48 54.06,52.41 53.8,52.3 52,51.4 51.79,51.27 51.63,51.12 51.54,50.97 51.5,50.8 51.54,50.63 51.63,50.48 51.79,50.33 52,50.2 53.8,49.3 54.06,49.19 54.35,49.12 54.67,49.07 55,49.05 55.33,49.07 55.65,49.12 55.94,49.19 56.2,49.3"/></g>
      <g><g><polygon points="-42.4,20 -33,24.7 -33,22.5 -42.4,17.8"/><polygon points="-23.6,20 -33,24.7 -33,22.5 -23.6,17.8"/><polygon points="-33,13.1 -23.6,17.8 -33,22.5 -42.4,17.8"/></g></g>
      <g><g><polygon points="-31.4,25.5 -22,30.2 -22,28 -31.4,23.3"/><polygon points="-12.6,25.5 -22,30.2 -22,28 -12.6,23.3"/><polygon points="-22,18.6 -12.6,23.3 -22,28 -31.4,23.3"/></g></g>
      <g><g><polygon points="-20.4,31 22,52.2 22,50 -20.4,28.8"/><polygon points="31.4,47.5 22,52.2 22,50 31.4,45.3"/><polygon points="-11,24.1 31.4,45.3 22,50 -20.4,28.8"/></g></g>
      <g><g><polygon points="23.6,53 33,57.7 33,55.5 23.6,50.8"/><polygon points="42.4,53 33,57.7 33,55.5 42.4,50.8"/><polygon points="33,46.1 42.4,50.8 33,55.5 23.6,50.8"/></g></g>
      <g><g><polygon points="34.6,58.5 44,63.2 44,61 34.6,56.3"/><polygon points="53.4,58.5 44,63.2 44,61 53.4,56.3"/><polygon points="44,51.6 53.4,56.3 44,61 34.6,56.3"/></g></g>
    </g>
  </svg>
</div>

CSS

.hln-keyboard-typing {
  --c: var(--hln-color, #ff4f2e);
  font-size: var(--hln-size, 16px);
  position: relative;
  display: grid;
  place-items: center;
  width: 22em;
  height: 12em;
  border-radius: 0.75em;
  background: #f6f5f1;
  overflow: hidden;
}
.hln-keyboard-typing svg {
  width: 100%;
  height: 100%;
  overflow: visible;
  fill: #ffffff;
  stroke: #1c1d21;
  stroke-width: 1.25;
  stroke-linejoin: round;
  stroke-linecap: round;
}
.hln-keyboard-typing svg * {
  vector-effect: non-scaling-stroke;
}
.hln-keyboard-typing .hln-keyboard-typing-a {
  stroke: var(--c);
}
.hln-keyboard-typing .hln-keyboard-typing-key {
  animation: hln-keyboard-typing-press 4.5s calc(var(--i) * 0.26s) infinite both;
}
.hln-keyboard-typing .hln-keyboard-typing-ret {
  animation-delay: 1.3s;
}
@keyframes hln-keyboard-typing-press {
  0% { transform: matrix(1, 0, 0, 1, 0, 0); }
  11.11% { transform: matrix(1, 0, 0, 1, 0, 0); animation-timing-function: cubic-bezier(.55,0,.85,.3); }
  12.89% { transform: matrix(1, 0, 0, 1, 0, 1.7); animation-timing-function: linear(0, 0.035, 0.125, 0.247, 0.384, 0.524, 0.655, 0.771, 0.87, 0.948, 1.008, 1.05, 1.077, 1.091, 1.095, 1.091, 1.083, 1.071, 1.058, 1.045, 1.032, 1.021, 1.012, 1.005, 0.999, 0.995, 0.993, 0.991, 0.991, 0.991, 0.992, 0.993, 1); }
  25.56% { transform: matrix(1, 0, 0, 1, 0, 0); }
  100% { transform: matrix(1, 0, 0, 1, 0, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .hln-keyboard-typing * {
    animation: none !important;
  }
}

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

Customizing this snippet

  • Color: set --hln-color on the element or a parent. Currently previewing #3b82f6.
  • Base size: set --hln-size. Every other dimension is in em, so the whole thing scales together. Currently previewing 16px.
  • 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 hairline animations