Design a hover zone that allows for interaction without disrupting click events

I am looking to create a tooltip box that appears when hovering over an element, and I want the tooltip to only disappear when the user's mouse exits a specific custom hover area outlined by a vector graphic.

My current implementation is working, but the hover area is causing click events to be blocked from reaching the tooltip, as illustrated below.

$(document).ready(function() {
  $("#hover-me").mouseenter(function(e) {
    $("#mouse-box").css("visibility", "visible");
    $("#tooltip").show();
  });
  $("#mouse-box").mouseleave(function(e) {
    $("#mouse-box").css("visibility", "hidden");
    $("#tooltip").hide();
  });
});
#tooltip {
  position: absolute;
  top: 20px;
  display: none;
  height: 60px;
}

#hover-me {
  position: absolute;
  top: 40px;
  left: 140px;
}

svg {
  position: absolute;
  left: 0;
  width: 210px;
  height: 83px;
  opacity: 0.03;
  pointer-events: none;
}

svg clipPath rect:first-child {
  width: 90px;
  height: 100%;
  x: 0;
  y: 0;
}

svg clipPath rect:last-child {
  width: 130px;
  height: 35px;
  x: 90px;
  y: 25px;
}

#mouse-box {
  fill: red;
  visibility: hidden;
  width: 100%;
  height: 100%;
  pointer-events: visible;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="tooltip">Can't click</button>
<div id="hover-me">Hover me</div>
<svg>
    <defs>
      <clipPath id="clip">
        <rect/><rect/>
      </clipPath>
    </defs>
    <rect id="mouse-box" clip-path="url(#clip)"/>
</svg>

Answer №1

If you're having trouble with all mouse events working properly, there's a neat trick you can use specifically for the click() event - the hide-test-show-click technique.

$(document).ready(function() {
  $("#hover-me").mouseenter(function(e) {
    $("#mouse-box").css("visibility", "visible");
    $("#tooltip").show();
  });
  $("#mouse-box").mouseleave(function(e) {
    $("#mouse-box").css("visibility", "hidden");
    $("#tooltip").hide();
  });

  $("#mouse-box").click(function(e) {
    $("#mouse-box").hide();
    var elem = document.elementFromPoint(e.pageX, e.pageY);
    $("#mouse-box").show();
    $(elem).click();
  });
  
  $("#tooltip").click(function(e) {
    alert("Clicked!");
  });
});
#tooltip {
  display: none;
  height: 150px;
}

#hover-me {
  position: absolute;
  top: 65px;
  left: 140px;
}

svg {
  position: absolute;
  left: 0;
  width: 210px;
  height: 150px;
  opacity: .03;
  pointer-events: none;
}

svg clipPath rect:first-child {
  width: 70px;
  height: 670px;
  x: 0;
  y: 0;
}

svg clipPath rect:last-child {
  width: 150px;
  height: 35px;
  x: 70px;
  y: 50px;
}

#mouse-box {
  fill: red;
  visibility: hidden;
  width: 100%;
  height: 100%;
  pointer-events: visible;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="tooltip">Tooltip</button>
<div id="hover-me">Hover me</div>
<svg>
    <defs>
      <clipPath id="clip">
        <rect/><rect/>
      </clipPath>
    </defs>
    <rect id="mouse-box" clip-path="url(#clip)"/>
</svg>

Answer №2

After adjusting the z-index of the tooltip, it now displays on top of the hover area as intended.

However, a new issue arose where the hover area's mouseleave handler triggered when the mouse entered the tooltip, causing it to disappear.

To address this issue, I included a condition

if ($('#tooltip:hover').length === 0)
in the mouseleave handler so that the tooltip is only hidden when the mouse exits the hover area completely.

$(document).ready(function() {
  $("#hover-me").mouseenter(function(e) {
    $("#mouse-box").css("visibility", "visible");
    $("#tooltip").show();
  });
  $("#mouse-box").mouseleave(function(e) {
    if ($('#tooltip:hover').length === 0) {
      $("#mouse-box").css("visibility", "hidden");
      $("#tooltip").hide();
    }
  });
});
#tooltip {
  position: absolute;
  top: 20px;
  display: none;
  height: 60px;
  z-index: 10;
}

#hover-me {
  position: absolute;
  top: 40px;
  left: 140px;
}

svg {
  position: absolute;
  left: 0;
  width: 210px;
  height: 83px;
  opacity: 0.03;
  pointer-events: none;
}

svg clipPath rect:first-child {
  width: 90px;
  height: 100%;
  x: 0;
  y: 0;
}

svg clipPath rect:last-child {
  width: 130px;
  height: 35px;
  x: 90px;
  y: 25px;
}

#mouse-box {
  fill: red;
  visibility: hidden;
  width: 100%;
  height: 100%;
  pointer-events: visible;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="tooltip">Can click</button>
<div id="hover-me">Hover me</div>
<svg>
    <defs>
      <clipPath id="clip">
        <rect/><rect/>
      </clipPath>
    </defs>
    <rect id="mouse-box" clip-path="url(#clip)"/>
</svg>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Executing TipTap commands from a script tag in Vue 3: A step-by-step guide

One of the components I'm working with includes the following: <button @click="$refs.image.click(); editor.chain().focus().setImage({ src: state.image }).run()"></button> <input type="file" ref="image" sty ...

How come an absolutely positioned element does not disregard its sibling's position and appears after it?

<div> is styled flexibly, while <section> is inserted within it and formatted statically. However, <section> shows up underneath the lower right corner of the image, rather than at the upper left corner of its flexible parent. I am strugg ...

Struggling to make the height attribute work in Bootstrap 4 alpha

I'm currently in the process of learning Bootstrap, and I've encountered an issue with the height attribute in version 4 (for example: "row h-25") not functioning properly. I attempted to add another CSS rule that sets the height of "container-f ...

What is the reason that the 400 status code consistently causes the enter catch block to execute when using axios?

In the frontend of my website, there is a contact form with three fields -> name, email, message. These fields are then sent to the backend using Axios. If a user fails to fill out any of the required fields, they should see a message saying "please f ...

Encasing the window global variable within an AngularJS framework

Currently, I am encapsulating a global variable within a factory in order to make it injectable. Here is an example of how it's done: angular.module('Analytics').factory('woopra', [ '$window', function ($window) ...

The HTTP GET request was successful, however, there is no data being displayed on the screen

I am currently facing an issue with fetching data from a web server. The data is retrieved successfully as I can see the object in the console log, but it does not render in the component template. export class CountrydetailsComponent implements OnInit { ...

Express file response problems affecting React front-end communication

I am currently developing a basic questionnaire on a React full stack website that uses React, Express, and SQL. Right now, my main goal is to return an error message from React and have it displayed on the front end. This is the code for my express endp ...

Retrieve the value of [routerLinkActive] in the component's class

Recently, I've been working on a tab component called TabComponent and it includes the following HTML template: <a [routerLink]='link' [routerLinkActive]="[is-active]">link label</a> <button>Close tab</button> The c ...

Leveraging PHP for parsing an HTML document

I am currently working on a PHP application that involves parsing HTML content. My goal is to extract a particular column from a table and store it in PHP variables. Below is the code I'm using: $dom = new domDocument; @$dom->loadHTML($html); $d ...

How does Chrome have the capability to access the gist json file? Isn't that typically not allowed?

Fetching a JSON file from Github Gist can sometimes be straightforward, but in certain situations, I have faced difficulties due to CORS restrictions. This has led me to resort to using JSONP instead. Can you shed some light on why this is the case? ...

Having trouble getting a value from a textbox to PHP using jQuery - can anyone lend a hand?

<script type="text/javascript" src="http://code.jquery.com/jquery-1.5b1.js"></script> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.7/jquery-ui.min.js"></script> <input type="text" id= ...

How to implement bi-directional scroll animation in JavaScript for top and bottom movements

In my JS project, I experimented with creating animations using the bounding client feature. By scrolling down to reveal certain text or content, I was able to adjust its opacity to 1 by applying the CSS class ".active". However, once the user scrolls back ...

Creating a stunning HTML 5 panorama with GigaPixel resolution

Interested in creating a gigapixel panorama using HTML 5 and Javascript. I found inspiration from this example - Seeking advice on where to begin or any useful APIs to explore. Appreciate the help! ...

Why won't setInterval function properly with innerHTML?

I've been attempting to include a small feature on my website that displays the running seconds, but for some reason my JavaScript function isn't working. Strangely, it's not throwing any errors either. Here's the code I'm using: f ...

`In what way can I acquire auto-generated identifiers for selected documents?`

I am currently using Vue and Firestore in my project. Below is the code snippet I used to generate a document in the collection: <template> <input type="text" v-model="form.title"> </template> methods: { async sa ...

Problems with displaying Wordpress content on your web browser

I am having trouble getting my website content to display properly in a web browser, even though I built it using Wordpress. It appears that only the logo and the 'Services' bar are showing up on the page, while the rest seems to be missing. I s ...

A guide to displaying a countdown timer in an Angular application during the app's loading process

Displaying a loader that shows the time in seconds while loading an app is my goal. Here is the code snippet: HTML <body> <div class="app-loader"> <div class="loader-spinner"> <div class="loading-text"></div> ...

Concentrate on all elements within the form

I am in the process of developing a form with multiple input fields, one of which is shown below. I am interested in triggering an event using jQuery's focusout function. The form goes by the name: form_test <form id="form_test"> <input ...

Why isn't the background-image displaying with the use of the url() function?

I've been attempting to set an image as the background using background-img:url(imageLing), but it's not working properly. When I inspect the element, it shows me background-image: url(assets/backgrounds/5.jpg);. What could be causing this issue? ...

Is there a way to integrate PHP into HTML without using a specific tag?

Before diving into something complex, I wanted to start with a basic PHP and HTML project. Unfortunately, my HTML page doesn't seem to be processing the PHP code correctly. Below is the PHP code embedded in my HTML: <?php echo '<p>Hell ...