W3docs

CSS :hover Pseudo-Class

Learn how the CSS :hover pseudo-class works, how to combine it with transitions, and how to handle touch devices and accessibility correctly.

The :hover pseudo-class matches an element while the user's pointer is positioned over it. It activates as soon as the pointer moves onto the element and deactivates the moment the pointer moves away — no click required.

This page covers:

  • Basic syntax and how to target links, buttons, and any element
  • Combining :hover with transition for smooth animated effects
  • Hovering a parent to reveal or restyle its children (dropdown pattern)
  • Gating hover styles with @media (hover: hover) for touch-device safety
  • Accessibility requirements and the :focus / :focus-within pairing

Syntax

selector:hover {
  /* declarations applied while pointer is over the element */
}

The selector can be any valid CSS selector — element, class, ID, or a combinator chain.

The most common use of :hover is changing the appearance of anchor links. For predictable link styling, declare rules in LVHA order: :link, :visited, :hover, :active. This order ensures later pseudo-classes can override earlier ones without specificity surprises.

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
    <style>
      a:hover {
        background-color: #8ebf42;
        color: #666;
      }
    </style>
  </head>
  <body>
    <h2>:hover selector example</h2>
    <a href="https://www.w3docs.com/">W3docs.com</a>
  </body>
</html>

Move your pointer over the link to see the background and text color change.

When a link appears inside a paragraph, :hover still targets only that <a> element — surrounding text is unaffected.

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
    <style>
      a {
        color: #1c87c9;
      }
      a:hover {
        background-color: #555;
        color: #eee;
      }
    </style>
  </head>
  <body>
    <h2>:hover selector example</h2>
    <p>Lorem Ipsum is simply dummy text of the printing and <a href="#">typesetting</a> industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into <a href="#">electronic</a> typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like <a href="#">Aldus PageMaker</a> including versions of Lorem Ipsum.</p>
  </body>
</html>

Hovering block elements

:hover works on any element, not just links. Applying it to a <div> lets you create interactive card or panel effects.

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
    <style>
      div {
        padding: 30px;
        background-color: #8ebf42;
        color: #eee;
      }
      div:hover {
        background-color: #444;
        color: #fff;
      }
    </style>
  </head>
  <body>
    <h2>:hover selector example</h2>
    <div>
      Lorem ipsum is simply dummy text...
    </div>
  </body>
</html>

Smooth hover effects with transition

A plain :hover rule switches styles instantly. Adding a transition on the base selector (not the :hover rule) causes the browser to animate the change in both directions — when the pointer enters and when it leaves.

.button {
  background-color: #1c87c9;
  color: #fff;
  padding: 0.5rem 1.2rem;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  /* Place transition on the base rule, not :hover */
  transition: background-color 0.25s ease, box-shadow 0.25s ease;
}

.button:hover {
  background-color: #145e8a;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}

If you put transition only inside the :hover rule the animation plays when entering but snaps back instantly on exit — a common beginner mistake.

You can transition multiple properties by separating them with commas, or use transition: all 0.25s ease as a shorthand (though targeting specific properties is better for performance).

Hovering a parent to style its children

:hover can be part of a combinator selector to react to a parent's hover state and style a descendant. This is the foundation of dropdown navigation menus and reveal-on-hover effects.

/* Card image starts dimmed; brightens when the card is hovered */
.card .card-image {
  opacity: 0.75;
  transition: opacity 0.2s ease;
}

.card:hover .card-image {
  opacity: 1;
}

/* Reveal an overlay label on hover */
.card .card-label {
  display: none;
}

.card:hover .card-label {
  display: block;
}
.nav-item .dropdown {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
}

.nav-item:hover .dropdown {
  display: block;
}
Warning

Hover-only menus are inaccessible to keyboard and touch users. Pair :hover with :focus-within so the menu also opens when a child element receives focus via keyboard navigation:

.nav-item:hover .dropdown,
.nav-item:focus-within .dropdown {
  display: block;
}

Gating hover styles for touch devices

Many touch-screen devices fire a simulated hover on tap, which can leave styles "stuck" until the user taps elsewhere. To prevent this, wrap hover-specific rules in a media query that checks whether the primary input device genuinely supports hover:

/* Only apply on devices with a real pointer (mouse, trackpad) */
@media (hover: hover) {
  .card:hover {
    transform: translateY(-4px);
    box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15);
  }
}

The hover: hover media feature is widely supported in modern browsers. On touch-only devices the block is simply ignored, so your base styles remain clean.

You can also combine it with pointer: fine to target precise pointing devices (mouse/trackpad) while excluding coarse ones (touch):

@media (hover: hover) and (pointer: fine) {
  .button:hover {
    background-color: #145e8a;
  }
}

Accessibility: pairing :hover with :focus

Keyboard users navigate with the Tab key, which triggers :focus rather than :hover. If your hover styles convey important visual feedback (like highlighting the active navigation item), apply the same styles to :focus so keyboard users get equivalent feedback:

/* Always pair hover and focus for interactive elements */
a:hover,
a:focus {
  outline: 2px solid #1c87c9;
  outline-offset: 2px;
  text-decoration: underline;
}

For compound components (like a card containing a button), :focus-within lets you style the parent whenever any child has focus:

.card:hover,
.card:focus-within {
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}
Info

Many touch devices do not fire a persistent :hover state; tapping an element typically triggers :active or :focus instead. Always test interactive hover patterns on a real touch device or with touch emulation.

Hover effects on other properties

:hover is not limited to colors. Any animatable CSS property can be toggled or transitioned on hover:

PropertyTypical hover effect
opacityFade in/out overlays or secondary UI
transformScale, translate, or rotate an element
box-shadowAdd depth to cards and buttons
colorChange text or icon color
cursorSignal that an element is interactive

Best practices

  • Mirror :hover with :focus so keyboard users receive the same visual feedback: a:hover, a:focus { ... }.
  • Gate hover-only animations behind @media (hover: hover) to prevent sticky states on touch devices.
  • Place transition on the base rule, not inside :hover, so the animation applies in both directions.
  • Don't hide essential content that only appears on hover — it is invisible to touch users and may be missed by screen readers.
  • Pair hover menus with :focus-within so keyboard navigation can open them without a mouse.
  • Follow LVHA order when styling links: :link, :visited, :hover, :active.

Browser support

:hover is supported in all modern browsers and has been since IE 7 for most elements (IE 6 supported it only on <a> tags). The @media (hover: hover) feature query is supported in Chrome 41+, Firefox 64+, Safari 9+, and Edge 79+.

Practice

Practice
What is the purpose of the :hover selector in CSS?
What is the purpose of the :hover selector in CSS?
Was this page helpful?