How to create responsive click events for overlapping HTML and SVG elements

Can the html based div and the SVG based line in the code snippet below both be made interactive with javascript?

I am familiar with the pointer-events css property. However, it seems to apply globally - I want both elements to be responsive individually...

#main {
  position: relative;
  width: 600px;
}

svg {
  border: 1px solid blue;
  red;
  position: absolute;
  top: 0;
  width: 100%;
  height: 100%;
  stroke: rgb(155, 155, 155);
  stroke-width: 10
}

#box-container {
  display: flex;
}

.box {
  width: 200px;
  background-color: pink;
  height: 100px;
}
<div>
  <p>
    Html based boxes should be clickable
  </p>
  <p>
    SVG based line should be clickable
  </p>
</div>
<div id="main">
  <svg>
    <line onClick="alert('line')" x1="0" y1="0" x2="600" y2="100" />
  </svg>
  <div style="display:flex;">
    <div onClick="alert('one')" class="box">
      One
    </div>
    <div onClick="alert('two')" style="margin-left:auto" class="box">
      Two
    </div>
  </div>
</div>

Answer №1

<div id=”container”>
  <p>Click on the HTML boxes to interact.</p>
  <p>The SVG line is also clickable.</p>
</div>

<div id=”main”>
  <svg>
    <line style=”cursor:pointer;” onClick=”alert('SVG line clicked')” x1=”0” y1=”0” x2=”600” y2=”100” />
  </svg>

  <div style=”display:flex;”>
    <div onClick=”alert('Box one clicked')” class=”box”>
      Box One
    </div>
    <div onClick=”alert('Box two clicked')” class=”box”>
      Box Two
    </div>
  </div>
</div>

Answer №2

Unfortunately, there is no direct way to achieve this. However, you can simulate a click event on another element using the following method.

function lineClick() {
  alert('line')
  document.querySelector("#one").click()
}
#main {
  position: relative;
  width: 600px;
}

svg {
  border: 1px solid blue;
  position: absolute;
  top: 0;
  width: 100%;
  height: 100%;
  stroke: rgb(155, 155, 155);
  stroke-width: 10
}

#box-container {
  display: flex;
}

.box {
  width: 200px;
  background-color: pink;
  height: 100px;
}
<div>
  <p>
    Html based boxes should be clickable
  </p>
  <p>
    SVG based line should be clickable
  </p>
</div>
<div id="main">
  <svg>
    <line onClick="lineClick()" x1="0" y1="0" x2="600" y2="100" />
  </svg>
  <div style="display:flex;">
    <div onClick="alert('one')" class="box" id="one">
      One
    </div>
    <div onClick="alert('two')" style="margin-left:auto" class="box">
      Two
    </div>
  </div>
</div>

Answer №3

To make the SVG not respond to mouse events, you can use svg{pointer-events:none}. For the line to respond to mouse events, you should use line{pointer-events:all}. If you want both the one and the line to respond to the same event, refer to @dgknca's solution.

#main {
  position: relative;
  width: 600px;
}

svg {
  border: 1px solid blue;
  red;
  position: absolute;
  top: 0;
  width: 100%;
  height: 100%;
  stroke: rgb(155, 155, 155);
  stroke-width: 10;
  pointer-events:none;
}

line{pointer-events:all;}

#box-container {
  display: flex;
}

.box {
  width: 200px;
  background-color: pink;
  height: 100px;
}
<div>
  <p>
    Html based boxes should be clickable
  </p>
  <p>
    SVG based line should be clickable
  </p>
</div>
<div id="main">
  <svg>
    <line onClick="alert('line')" x1="0" y1="0" x2="600" y2="100" />
  </svg>
  <div style="display:flex;">
    <div onClick="alert('one')" class="box">
      One
    </div>
    <div onClick="alert('two')" style="margin-left:auto" class="box">
      Two
    </div>
  </div>
</div>

Answer №4

To streamline event handling, consider using the elementsFromPoint(x,y) method for a unified delegation approach.

<script>
  function clickHandler(evt) {
    // Retrieve all elements at the specified X,Y coordinates
    let elements = document.elementsFromPoint(evt.clientX, evt.clientY);
    // Exclude the SVG element from consideration
    let element = elements[(elements[0].nodeName == "svg") ? 1 : 0];
    console.log(elements);
    console.log(element);
  }
</script>
<style>
  #main {
    position: relative;
    width: 600px;
  }
  svg {
    position: absolute;
    top: 0;
    width: 100%;
    height: 100%;
    stroke: green;
    stroke-width: 10
  }
  .box {
    width: 200px;
    background-color: pink;
    height: 100px;
  }
</style>
<div id="main" onclick="clickHandler(event)">
  <svg>
    <line x1="0" y1="0" x2="600" y2="100" />
  </svg>
  <div style="display:flex;">
    <div class="box" id=ONE>
      One
    </div>
    <div style="margin-left:auto" class="box" id=TWO>
      Two
    </div>
  </div>
</div>

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

Tips for patiently anticipating an object to undergo asynchronous modifications?

I have an array containing items, and I need to incorporate the asynchronous value from getProductMinQuantity. The issue I'm facing is that the response with res.status(200)... gets sent before modifying item.order_quantity_minimum. I had assumed us ...

Order comments based on their category using vue.js

I have a component form with select filter: <template> <div class="form-group"> <select name="" v-model="filterRev" @change="filterReviews(filterRev)" class="form-control" id=""> <option ...

How can I create a CSS div with a 20px margin-top distance from the div directly above

Here is the code that I am working with: https://jsfiddle.net/kc94aq33/ I am looking to set the top margin of the .wrapper to be 20px from the bottom of the .header. Does anyone know how I can achieve this? ...

Explore the new feature in React Vis LineMarkSeries where you can customize the style property to have distinct stroke and fill

In the component I have, the following code is included: <XYPlot height={300} width={500} xType="ordinal" yType="ordinal"> <XAxis /> <YAxis /> <LineMarkSeries data={data1} style={{line: {fill:"red"}, mark: {fill:"red", s ...

"Unlocking the secret to retrieving the initial text inputted into a textbox using jQuery's on

I'm facing a small issue that I believe has an easy solution, but my skills aren't quite there yet. My challenge is to retrieve the original value entered in an input type=textbox without getting the dots displayed. Can someone guide me on how to ...

Steps to convert a subelement into a string

I am looking to update the value of a specific key in each object within an array as new objects are dynamically added. Why? My goal is to further my understanding of array methods and JSON manipulation. To progress, I posed myself this question: How ca ...

Implementing react router functionality with Material-UI tabs

Could you please provide some insight on how to integrate my routes with MUI tabs? I'm not very familiar with MUI and could use some guidance on how to get it working. Any suggestions would be appreciated. To simplify the code, I have removed the imp ...

What is the best way to make "inline-block" elements move to a new line when needed?

Check out my fiddle: #container { background-color: green; } .result { border-radius: 6px; display: inline-block; width: 100%; max-width: 160px; min-width: 100px; height: 160px; border: 1px solid black; background-color: white; marg ...

Optimizing CSS usage within Django: top recommendations

Throughout a 6-month-long project, I have continuously added new URLs. However, I am now encountering an issue when using the extend 'base.html' function on other pages where the CSS overlaps and creates confusion. My question is: What are the b ...

Exploring the possibilities of applying a fragmentShader texture to repeat a ThreeJS Matcap

Here are the vertex and fragment shader materials: material = new THREE.ShaderMaterial( { uniforms: { textureMap: { type: 't', value: THREE.ImageUtils.loadTexture( 'img/matcap/green.jpg' ) }, normalMap: { type: 't' ...

Creating a custom design for multiple data-tooltips

If you're struggling with managing numerous tooltips on your site generated through data-tooltip, then I have a solution for you. With data-tooltip being an attribute, customizing its styles such as width or color can be challenging. Here's a sni ...

Ability to utilize an alternative attribute type within a TypeScript object

Within my class, I have: class Target { ... readonly overlay: { type: 'none' } | { type: 'centering', style?: { color?: string, offset?: number, size?: number, } } | { type: 'enterin ...

Setting up a recurring task with a while loop in a cron job

Discover numerous libraries dedicated to implementing cron jobs in NodeJS and Javascript, allowing for hosting on a server. Ultimately, cron jobs are simply repetitive tasks set to run at specific times/dates. This led me to ponder the distinction betwee ...

establishing a minimum number of characters in a regular expression enclosed in parentheses

/^[a-z]+[0-9]*$/igm Tom //valid tom12123 //valid 12tom //invalid to12m //invalid T23 //valid T //valid but I want a minimum of two characters. /^([a-z]+[0-9]*){2,}$/igm Tom //valid tom12123 //valid 12tom //invalid to12m //should be inval ...

The React initialization and construction process leads to excessive memory consumption

Hi there, I am facing an issue while trying to start or build my React app as it keeps giving me a heap out of memory error. Despite adding the --max_old_space_size=8192 flag to my script, the problem persists. yarn run v1.22.5 $ react-scripts --max_old_ ...

What is the best way to ensure a div spans the entire width of the screen?

I came across a helpful post on extending my container to the edge of the screen. Despite following the instructions, I still noticed a white space (highlighted in red): https://i.sstatic.net/w0bGf.png To address this issue, I experimented with setting t ...

Inform the user that an error has occurred when attempting to perform an invalid

While using redux promise middleware for my front end, I am wondering about the correct status code to throw from my backend in case of an error. I know that I can use res.status(500).json(something), but is 500 the appropriate code for all types of erro ...

Switch out button with AngularJS post request

One of the features in my project is a "favorite/unfavorite" button that switches its function when clicked by the user. <button id="favoriteButton" class="btn btn-default btn-sm" type="button" ng-click="@Model.GetFavoriteClick()"> <span aria ...

Opt for a line break over a semicolon when using jQuery

I need assistance with breaking the line wherever a semicolon is present. var locdata = { "locations": [{ "id": 0, "name": 'USA', "cx": 100, "cy": 100, "address":'545, 8t ...

Retrieving data from several checkboxes in AngularJS

Here is my code snippet where I am attempting to retrieve values of multiple selected checkboxes, but it seems to be malfunctioning. Can you please guide me on what mistake I might be making? Just to clarify, the list is dynamic and will not be limited to ...