AI CSS Animations

Keyboard Shortcut Tooltip

An icon button tooltip that shows its keyboard shortcut as keycaps, and the keys press down one after the other as it opens. Uses real kbd elements with an --i stagger.

Also known as: tooltip with kbd keys, shortcut hint tooltip, hotkey tooltip css.

Quick search ⌘K

HTML

<span class="tip-keyboard-shortcut">
  <button type="button" aria-label="Search" aria-describedby="tip-keyboard-shortcut-tip"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="11" cy="11" r="6.5"/><path d="m20 20-4.4-4.4"/></svg></button>
  <span class="tip-keyboard-shortcut-tip" id="tip-keyboard-shortcut-tip" role="tooltip">Quick search <kbd style="--i: 0">⌘</kbd><kbd style="--i: 1">K</kbd></span>
</span>

CSS

.tip-keyboard-shortcut {
  --c: var(--tip-color, #3b82f6);
  font-size: var(--tip-size, 16px);
  position: relative;
  display: inline-flex;
}
.tip-keyboard-shortcut button {
  display: grid;
  place-items: center;
  width: 2.6em;
  height: 2.6em;
  padding: 0;
  border: 1px solid color-mix(in srgb, var(--c) 35%, transparent);
  border-radius: 0.6em;
  background: color-mix(in srgb, var(--c) 8%, transparent);
  color: var(--c);
  cursor: pointer;
}
.tip-keyboard-shortcut svg {
  width: 1.25em;
  height: 1.25em;
}
.tip-keyboard-shortcut button:focus-visible {
  outline: 2px solid var(--c);
  outline-offset: 2px;
}
.tip-keyboard-shortcut-tip {
  position: absolute;
  bottom: calc(100% + 0.75em);
  left: 50%;
  z-index: 10;
  display: flex;
  align-items: center;
  gap: 0.25em;
  padding: 0.35em 0.4em 0.35em 0.75em;
  border-radius: 0.5em;
  background: color-mix(in srgb, var(--c) 14%, #0f172a);
  box-shadow: 0 0 0 1px rgb(255 255 255 / 0.07), 0 0.5em 1em -0.4em rgb(0 0 0 / 0.5);
  color: #fff;
  font: 500 0.85em/1.3 system-ui, sans-serif;
  white-space: nowrap;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transform: translate(-50%, 0.35em);
  transition: opacity 0.18s ease, transform 0.25s cubic-bezier(0.2, 0.8, 0.2, 1), visibility 0.25s;
}
.tip-keyboard-shortcut-tip::before {
  content: "";
  position: absolute;
  top: 100%;
  left: 50%;
  width: 0.6em;
  height: 0.6em;
  background: inherit;
  transform: translate(-50%, -50%) rotate(45deg);
}
.tip-keyboard-shortcut-tip kbd {
  display: inline-grid;
  place-items: center;
  box-sizing: border-box;
  min-width: 1.7em;
  height: 1.7em;
  padding: 0 0.35em;
  border-radius: 0.35em;
  background: rgb(255 255 255 / 0.12);
  box-shadow: inset 0 -0.15em 0 rgb(255 255 255 / 0.14), inset 0 0 0 1px rgb(255 255 255 / 0.1);
  font: 600 0.85em/1 system-ui, sans-serif;
}
.tip-keyboard-shortcut-tip kbd:first-of-type { margin-left: 0.35em; }
.tip-keyboard-shortcut:hover .tip-keyboard-shortcut-tip,
.tip-keyboard-shortcut:focus-within .tip-keyboard-shortcut-tip {
  opacity: 1;
  visibility: visible;
  transform: translate(-50%, 0);
}
.tip-keyboard-shortcut:hover .tip-keyboard-shortcut-tip kbd,
.tip-keyboard-shortcut:focus-within .tip-keyboard-shortcut-tip kbd {
  animation: tip-keyboard-shortcut-press 0.3s ease calc(0.3s + var(--i) * 0.15s) both;
}
@keyframes tip-keyboard-shortcut-press {
  0%, 100% { transform: translateY(0); }
  45% {
    transform: translateY(0.12em);
    background: var(--c);
    box-shadow: inset 0 -0.03em 0 rgb(255 255 255 / 0.14), inset 0 0 0 1px rgb(255 255 255 / 0.2);
  }
}

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

Customizing this snippet

  • Color: set --tip-color on the element or a parent. Currently previewing #3b82f6.
  • Base size: set --tip-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 tooltips