Hover effect

Reinforce interactivity on pointer hover while keeping layout stable.

Preview

Live preview

Visual change when the cursor moves over an element.

Preview
Authoritative vocabulary

Definition and close-term distinctions

English definitions are preserved verbatim from Animation Vocabulary; translations and distinctions help you choose precisely.

Canonical termhover-effect

Hover effect

悬停效果
Authoritative definition

Visual change when the cursor moves over an element.

Chinese translation

光标移到元素上方时产生的视觉变化。

Browse all 91 terms
Design contract

Decide before this motion ships

Purpose, frequency, trigger, timing, interruptibility, and gesture rules shape the implementation.

Purpose

Reinforce interactivity on fine-pointer hover while keeping layout and hit targets stable.

Frequency

Suitable for frequent controls when amplitude and duration remain very small.

Trigger

Trigger on pointerenter only when hover:hover and pointer:fine match.

Enter / exit

Enter the emphasized state on hover and restore quickly on leave, keeping content position stable.

Interruptibility

Return from current styles during rapid pointer movement without queuing animations.

Gesture and keyboard

Touch devices do not emulate hover, and focus-visible provides equivalent affordance.

Reduced-motion strategy

Keep static hover and focus color, border, or shadow changes while removing travel and scale.

Output

Copy into your interface

Current parameters update visual-state CSS, semantic HTML, the required vanilla JS runtime, and an interaction prompt.

Updates with parameters
motion.css
.motion-demo.motion-demo--hover-effect {
  position: relative;
  display: grid;
  place-items: center;
  width: min(100%, 34rem);
  min-height: 15rem;
  padding: 2rem;
  overflow: hidden;
  color: #18181b;
  background: #fafafa;
  border: 1px solid #e4e4e7;
  border-radius: 12px;
  isolation: isolate;
}

.motion-demo.motion-demo--hover-effect *, .motion-demo.motion-demo--hover-effect *::before, .motion-demo.motion-demo--hover-effect *::after {
  box-sizing: border-box;
}

.motion-demo.motion-demo--hover-effect .motion-surface {
  position: relative;
  display: grid;
  gap: 0.65rem;
  width: min(100%, 18rem);
  padding: 1.25rem;
  background: #ffffff;
  border: 1px solid #e4e4e7;
  border-radius: 8px;
  box-shadow: 0 1px 2px rgb(0 0 0 / 6%), 0 10px 28px rgb(0 0 0 / 7%);
}

.motion-demo.motion-demo--hover-effect .motion-line {
  display: block;
  width: 100%;
  height: 0.5rem;
  background: #e4e4e7;
  border-radius: 999px;
}

.motion-demo.motion-demo--hover-effect .motion-line:last-child { width: 62%; }

.motion-demo.motion-demo--hover-effect .motion-button {
  position: relative;
  min-height: 2.75rem;
  padding: 0.75rem 1.1rem;
  color: white;
  font: inherit;
  font-weight: 700;
  background: #18181b;
  border: 0;
  border-radius: 7px;
  cursor: pointer;
}

.motion-demo.motion-demo--hover-effect .motion-button:focus-visible { outline: 3px solid rgb(37 99 235 / 32%); outline-offset: 3px; }

.motion-demo.motion-demo--hover-effect .motion-action-row {
  display: flex;
  justify-content: center;
  gap: 0.5rem;
  margin-top: 0.85rem;
}

.motion-demo.motion-demo--hover-effect .motion-replay-scene {
  width: min(100%, 22rem);
  display: grid;
  place-items: center;
}

.motion-demo.motion-demo--hover-effect .motion-pausable-scene {
  width: min(100%, 22rem);
  display: grid;
  place-items: center;
}

.motion-demo.motion-demo--hover-effect button.motion-surface {
  color: inherit;
  font: inherit;
  text-align: start;
  cursor: pointer;
}

.motion-demo.motion-demo--hover-effect .motion-replay-button,
.motion-demo.motion-demo--hover-effect .motion-undo-button,
.motion-demo.motion-demo--hover-effect .motion-dismiss-button,
.motion-demo.motion-demo--hover-effect .motion-pause-button {
  min-height: 2.75rem;
  padding: 0.65rem 0.9rem;
  color: #18181b;
  font: 650 0.78rem/1 ui-sans-serif, system-ui, sans-serif;
  background: #ffffff;
  border: 1px solid #d4d4d8;
  border-radius: 7px;
  cursor: pointer;
}

.motion-demo.motion-demo--hover-effect .motion-replay-button:focus-visible,
.motion-demo.motion-demo--hover-effect .motion-undo-button:focus-visible,
.motion-demo.motion-demo--hover-effect .motion-dismiss-button:focus-visible,
.motion-demo.motion-demo--hover-effect .motion-pause-button:focus-visible,
.motion-demo.motion-demo--hover-effect [data-reorder-item]:focus-visible,
.motion-demo.motion-demo--hover-effect [data-swipe-target]:focus-visible {
  outline: 3px solid rgb(37 99 235 / 32%);
  outline-offset: 3px;
}

.motion-demo.motion-demo--hover-effect .motion-status {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.motion-demo.motion-demo--hover-effect .motion-ripple-ink {
  position: absolute;
  width: 12px;
  height: 12px;
  pointer-events: none;
  background: rgb(255 255 255 / 72%);
  border-radius: 50%;
  transform: translate(-50%, -50%) scale(0.95);
  opacity: 0;
}

.motion-demo.motion-demo--hover-effect .motion-state-stack { position: relative; width: min(100%, 18rem); height: 9rem; }
.motion-demo.motion-demo--hover-effect .motion-state { position: absolute; inset: 0; display: grid; place-items: center; padding: 1rem; background: #ffffff; border: 1px solid #e4e4e7; border-radius: 8px; }
.motion-demo.motion-demo--hover-effect .motion-state--to { background: #18181b; color: white; }

.motion-demo.motion-demo--hover-effect .motion-scroll-track > span { color: #71717a; font: 600 0.72rem/1.2 ui-monospace, monospace; letter-spacing: 0.08em; text-transform: uppercase; }
.motion-demo.motion-demo--hover-effect .motion-orbit-item { display: grid; place-items: center; width: 2.5rem; height: 2.5rem; color: white; background: #2563eb; border-radius: 50%; }
.motion-demo.motion-demo--hover-effect .motion-text-stack { position: relative; width: min(100%, 18rem); min-height: 4rem; }
.motion-demo.motion-demo--hover-effect svg { width: min(100%, 20rem); height: auto; }

.motion-demo.motion-demo--hover-effect .motion-button { transition: transform 150ms cubic-bezier(0.16, 1, 0.3, 1); }
@media (hover: hover) and (pointer: fine) {
  .motion-demo.motion-demo--hover-effect .motion-button:hover { transform: translateY(-4px) scale(1.01); box-shadow: 0 14px 28px rgb(0 0 0 / 16%); }
}

@keyframes motion-hover-effect-reduced-fade {
  from { opacity: 0.84; }
  to { opacity: 1; }
}

.force-reduced-motion .motion-demo.motion-demo--hover-effect {
  animation: motion-hover-effect-reduced-fade 160ms cubic-bezier(0.23, 1, 0.32, 1) both !important;
}

.force-reduced-motion .motion-demo.motion-demo--hover-effect *,
.force-reduced-motion .motion-demo.motion-demo--hover-effect *::before,
.force-reduced-motion .motion-demo.motion-demo--hover-effect *::after {
  animation: none !important;
  animation-delay: 0ms !important;
  animation-iteration-count: 1 !important;
  transition-property: opacity, color, background-color, border-color !important;
  transition-duration: 160ms !important;
  transition-delay: 0ms !important;
  scroll-behavior: auto !important;
}

.force-reduced-motion .motion-demo.motion-demo--hover-effect .motion-button,
.force-reduced-motion .motion-demo.motion-demo--hover-effect [data-reorder-item],
.force-reduced-motion .motion-demo.motion-demo--hover-effect [data-swipe-target],
.force-reduced-motion .motion-demo.motion-demo--hover-effect [data-spring-target] {
  transform: none !important;
}

.force-reduced-motion .motion-demo.motion-demo--hover-effect .motion-path { stroke-dashoffset: 0 !important; }
.force-reduced-motion .motion-demo.motion-demo--hover-effect .motion-word--from { opacity: 0 !important; visibility: hidden; }
.force-reduced-motion .motion-demo.motion-demo--hover-effect .motion-word:not(.motion-word--from) { opacity: 1 !important; filter: none !important; transform: none !important; }

@media (prefers-reduced-motion: reduce) {
  .motion-demo.motion-demo--hover-effect {
    animation: motion-hover-effect-reduced-fade 160ms cubic-bezier(0.23, 1, 0.32, 1) both !important;
  }

  .motion-demo.motion-demo--hover-effect *, .motion-demo.motion-demo--hover-effect *::before, .motion-demo.motion-demo--hover-effect *::after {
    animation: none !important;
    animation-delay: 0ms !important;
    animation-iteration-count: 1 !important;
    transition-property: opacity, color, background-color, border-color !important;
    transition-duration: 160ms !important;
    transition-delay: 0ms !important;
    scroll-behavior: auto !important;
  }

  .motion-demo.motion-demo--hover-effect .motion-button,
  .motion-demo.motion-demo--hover-effect [data-reorder-item],
  .motion-demo.motion-demo--hover-effect [data-swipe-target],
  .motion-demo.motion-demo--hover-effect [data-spring-target] {
    transform: none !important;
  }

  .motion-demo.motion-demo--hover-effect .motion-path { stroke-dashoffset: 0 !important; }
  .motion-demo.motion-demo--hover-effect .motion-word--from { opacity: 0 !important; visibility: hidden; }
  .motion-demo.motion-demo--hover-effect .motion-word:not(.motion-word--from) { opacity: 1 !important; filter: none !important; transform: none !important; }
}
Review notes

Pre-delivery review

  • Keep hover from carrying unique information.
  • Ensure shadow and transform changes do not cause layout movement.
Accessibility

Keep information accessible

Reduced motion

Keep static hover and focus color, border, or shadow changes while removing travel and scale.

Parameters

Parameter reference

ParameterRange / optionsDefaultPurpose
duration80ms–1200ms150msControls the time required for one motion cycle.
distance0px–16px4pxControls how far the element travels.
scale70%–105%101%Controls the starting size relative to the final state.
easeSoft / Snap / Calm / LinearSnapControls how velocity changes over time.