Home > database >  React: display element on hover (touch) but prevent initial click within div
React: display element on hover (touch) but prevent initial click within div

Time:02-22

This is a similar question to others on here, but I haven't found a question or answer that properly matches my scenario (yet).

I have a site that uses :hover CSS in a couple of places to reveal an interactive overlay with clickable elements (buttons, etc) in the overlay. This works great on desktop: user hovers to see more info and can then choose to click buttons, or not. On mobile the user needs to click the element to trigger the hover pseudo-class and reveal the overlay. This is actually the behaviour I want, but has the issue that if there is a button directly underneath where the user clicked it is triggered immediately.

The effect I'm after is that for mobile/touch, the user first has to click the element to reveal the overlay, then they can click on buttons, etc, within the element. Desktop should continue to work with hover as it does now.

I don't think this behaviour can be achieved with CSS alone, although that would be ideal of course...

Example code here: https://stackblitz.com/edit/react-epunjm?file=src/App.js

// App.js
import React from "react";
import "./style.css";

export default function App() {
  return (
    <div className="container">
      <div className="content">
        Hello StackBlitz!
      </div>
      <div className="overlay">
        <span>This is overlay</span>
        <button onClick={() => alert("clicked!")}>BUTTON</button>
      </div>
    </div>
  );
}
// style.css
div {
  font-family: Lato;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
  gap: 10px;
}

div.container {
  position: relative;
  width: 200px;
  height: 100px;
}

div.content {
  background: orange;
}

div.content, div.overlay {
  position: absolute;
  font-weight: bold;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}

div.overlay {
  display: none;
  color: white;
  background: rgba(0,0,0,0.7);
}

div.container:hover div.overlay {
  display: inherit;
}

EDIT:

Many thanks to Onkar Ruikar for his answer. I took inspiration from his ideas but ended up using focus state (using tab index), and disabling pointer events for the overlay contents until the overlay has focus. This requires detecting when device has touch using a media query and may not be totally reliable but should serve my needs.

Working example here: https://stackblitz.com/edit/react-dupeks

CodePudding user response:

On single tap, at button location, following events are fired:

content   touchStart
container touchStart   //here CSS rule brings overlay forth
content   touchEnd
container touchEnd

container mouseEnter
overlay   mouseEnter
button    mouseEnter
button    clicked        // the button gets clicked in same tap!            
  • Related