htmlcsshovertouch

How to remove/ignore :hover css style on touch devices


I want to ignore all :hover CSS declarations if a user visits our website via touch device. Because the :hover CSS does not make sense, and it can even be disturbing if a tablet triggers it on click/tap because then it might stick until the element loses focus. To be honest, I don't know why touch devices feel the need to trigger :hover in first place - but this is reality, so this problem is reality as well.

a:hover {
  color:blue;
  border-color:green;
  /* etc. > ignore all at once for touch devices */
}

So, (how) can I remove/ignore all CSS :hover declarations at once (without having to know each one) for touch devices after having them declared?


Solution

  • Update for 2024

    /* set link hover styles as normal */
    
    a:hover {
      color: red;
      text-decoration: underline wavy;
      /* etc. > ignore all at once for touch devices */
    }
    
    
    /* revert all link hover declarations for touch devices */
    
    @media (pointer: coarse) {
      a:hover {
        all: revert-layer;
      }
    }
    <a href="#">Some link</a>

    Specifics

    @media (pointer: coarse) {}: Targets only coarse pointers; from MDN:

    The primary input mechanism includes a pointing device of limited accuracy, such as a finger on a touchscreen.

    all: revert-layer: Reverts declarations to the previous layer or origin. from MDN:

    Specifies that all the element's properties should roll back the cascade to a previous cascade layer, if one exists. If no other cascade layer exists, the element's properties will roll back to the matching rule, if one exists, in the current layer or to a previous style origin.


    Original Answer

    hover CSS Media Feature to the rescue! Using only CSS, you can override styles when a device does not have hover capabilities.

    The following demo is supported by modern touch devices.

    /* hover query styles */
    
    a {
      color: red;
      font-size: 3em;
    }
    
    a:hover {
      color: blue;
    }
    
    @media (hover: none) {
      a:link,
      a:visited {
        color: blue;
        text-decoration: none;
        border: 0.1em solid currentColor;
        padding: 0 0.1em;
      }
    }
    
    /* used to show if demo browser has hover capabilities */
    .detection:before {
      content: 'UNKNOWN';
      color: red;
    }
    
    @media(hover) {
      .detection:before {
        content: 'YES';
        color: green;
      }
    }
    
    @media (hover: none) {
      .detection:before {
        content: 'NO';
      }
    }
    <p>Hoverable pointer detected: <span class="detection"></span></p>
    
    <h3>Experiences between device hover capabilities</h3>
    
    <p>If the device has a hover capability, the link below:</p>
    
    <ul>
      <li>should be red</li>
      <li>should be blue when hovered</li>
    </ul>
    
    <p>If the device does not have a hover capability, the link below:</p>
    
    <ul>
      <li>should always be blue</li>
      <li>should be surrounded by a blue border</li>
    </ul>
    
    <p><a href="https://www.google.com">Link</a></p>

    Note: Keep in mind that since a Surface PC's primary input (capability) is a mouse, it will end up being a blue link, even if it's a detached (tablet) screen. Browsers will (should) always default to the most precise input's capability.