Issue with SVG marker not functioning properly when hovered over

I am having an issue with buttons containing SVG elements, here is an example code snippet:

<button>
 Checkout
 <ArrowSvg />
</button>

The ArrowSvg component looks like this (with the line having a class of "svg-line"):

<svg fill="none" stroke="#000">
  <defs>
    <marker id="m" overflow="visible">
      <path d="M-4,-4L0,0 -4,4" />
    </marker>
  </defs>
  <line x1="0" y1="50%" x2="100%" y2="50%" marker-end="url(#m)" class="svg-line" />
</svg>


When a button is hovered over, I change the stroke color of the arrow:

btn:hover > .svg-line {
  stroke: blue;
}

While this functionality works as expected when only one button is present, issues arise when multiple buttons are displayed. Hovering over one button causes all other button arrows to also change color. This seems to affect the arrow head part of all buttons.
I am unable to use paths instead of lines due to the need for adjusting the arrow width. What might I be missing here? Why is this hover effect spreading to other buttons?

Answer №1

Utilize a native JS Web Component, which is compatible with all modern browsers, to generate the <svg>

  • as each SVG necessitates a distinct marker ID

  • please note: an individual SVG is produced for every occurrence, rendering a marker unnecessary; utilize the path on its own

customElements.define("svg-button",class extends HTMLElement{
  connectedCallback(){
    let id = "id" + (Math.floor(Math.random() * 1e10));
    let stroke = this.getAttribute("stroke") || "#000";
    this.innerHTML = `
          <button> 
           Checkout
            <svg fill="none" stroke="${stroke}" viewBox="0 0 10 10">
              <defs>
                <marker id="${id}" overflow="visible">
                  <path d="M-4,-4L0,0 -4,4"/>
                </marker>
              </defs>
              <line x1="0" y1="5" x2="9" y2="5" marker-end="url(#${id})"/>
            </svg>
          </button>`
    }
});
<style>
  button:hover svg {
    stroke:gold;
  }
</style>

<svg-button></svg-button>
<svg-button stroke="red"></svg-button>
<svg-button stroke="green"></svg-button>
<svg-button stroke="blue"></svg-button>

Answer №2

It seems like the code you are working on resembles .JSX syntax, but there is a missing react tag in the question. I will assume it for this response, although other frameworks utilizing the same format should also perform similarly.

To create a unique id for the <marker> element, simply define the <ArrowSvg> as a function and enclose it in another factory function to generate a closure over an incrementing number:

const ArrowSvg = (() => {
  let id = 0;
  return function (props) {
    return (
      const ref = 'arrowMarker' + ++id;
      <svg fill="none" stroke="#000">
        <defs>
          <marker id=(ref) overflow="visible">
            <path d="M-4,-4L0,0 -4,4" />
          </marker>
        </defs>
        <line x1="0" y1="50%" x2="100%" y2="50%"
              marker-end=(`url(#${ref})`) class="svg-line" />
      </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

React router will only replace the last route when using history.push

I'm working on implementing a redirect in React Router that triggers after a specific amount of time has elapsed. Here's the code I've written so far: submitActivity(){ axios.post('/tiles', { activityDate:thi ...

When making an axios post request and using node pdfkit, the generated PDF appears blank

I encountered an issue while using react with axios to send a post request to the express server for creating a PDF using pdfkit. Even though the file is automatically downloaded upon receiving, the content of the PDF appears to be blank when opened. impor ...

The toggleCategories function seems to be malfunctioning as it is only showing the sequence number as 0 in ReactJS

I am currently working on a portfolio using the React framework. One of the features I have implemented is a project page where multiple projects are displayed within tabs. However, I am facing some issues with the functionality. toggleCategories(){ ...

How can I use JQuery to select an element with a style attribute in Internet Explorer?

When using JQuery, I have set my target to be the following: <li style="margin-left: 15px;">blah<li> I am using this code to achieve that: $(".block-category-navigation li[style='margin-left: 15px;']").addClass('sub-menu' ...

Exploring the bond between siblings from a child's perspective

Is there a way to apply styling to the .item class when the corresponding input field is checked? <input> <span class="item"> I have discovered that I can achieve this using input:checked ~ .item {} However, my challenge lies in obtaining th ...

Can you help me modify the navbar color in Bootstrap 4 based on the screen width?

For example, if I use the navbar-dark and bg-dark classes in a nav tag, I want to switch them to navbar-light and bg-light when the screen width is changed to approximately 600px (using Bootstrap 4). ...

Is there a Container with a Heading in Material UI?

Does anyone know how to create a container with a top title like the one shown in this screenshot: https://i.sstatic.net/vh2zv.png I've attempted using Box or Paper components, but I can't seem to find the option for a top title. Any suggestions ...

Customizing the appearance of individual columns in the Material-UI DataGrid

My goal is to center an IconButton within a DataGrid table, all of which are MUI components. Despite reading the documentation and trying various methods, I haven't achieved the desired result yet. In my latest attempt, I implemented the following: G ...

I'm facing an issue in React where using onChange is causing all DOM elements to be cleared. The input form functions correctly when used with a button, but for some reason, the onChange event does not

Currently, I'm working on a grid that can be resized using two input fields in the application. The setup involves an input for cells across, an input for cells down, and a button to set the grid, which is functioning well. However, I would like to ma ...

The positioning of the text appears to be in the center, but it is actually

Currently, my text "lorum ipsum" is centered in CSS, but I want to align it to the left and add padding on the right later. Can someone explain what I've created here? #ubba { font-family: "Open Sans", sans-serif; font-size: 20px; ...

Guide to setting up value observation in React Context for optimal functionality

Imagine a scenario where there is a Parent Component that provides a Context containing a Store Object. This Store holds a value and a function to update this value. class Store { // value // function updateValue() {} } const Parent = () => { const ...

Is there a way to change the border property of an element when clicked, without causing the displacement of other elements?

I'm in the process of creating a webpage where users can choose the color and storage capacity of an item. Only one color/capacity can be selected at a time, and once chosen, it should be highlighted with a border. The issue I encountered is that whe ...

Having trouble resolving a missing dependency warning with the useEffect React Hook in my Next.js app. Any tips on how to fix this

Currently, I'm facing the following warning: Warning: React Hook useEffect has a missing dependency: 'router'. Either include it or remove the dependency array Here is the code snippet from _app.js that seems to be causing this issue: cons ...

Chrome's struggle with displaying multiple backgrounds on retina screens due to CSS complications

My goal is to create top and bottom shadows for a parent container when scrolling through the content. This effect works perfectly everywhere except on Chrome browser with retina screens, where it behaves strangely. The background becomes stuck at the top, ...

Can side effects be safely incorporated within the callback of the useState hook?

Consider this scenario: const [value, setValue] = useState(false); const setSomething = (val) => { setValue((prev) => { fn(); dispatch(action); // or any other side effect return prev + val; }); }; Is it acceptable and in line with ...

Altering the dimensions of radio buttons

I am a newcomer to using material-ui. I am currently working on incorporating radio buttons in a component and would like to reduce its size. While inspecting it in Chrome, I was able to adjust the width of the svg icon (1em). However, I am unsure how to a ...

Adjusting the position of a stationary element when the page is unresponsive and scrolling

Managing a large web page with extensive JavaScript functionality can be challenging, especially when dealing with fixed position elements that update based on user scroll behavior. A common issue that arises is the noticeable jumping of these elements whe ...

Unable to update to the most recent version of React-Bootstrap

I'm facing an issue while trying to upgrade to the newest version of react-bootstrap. When I run: npm install --save react-bootstrap The following message appears: npm notice created a lockfile as package-lock.json. You should commit this file. npm ...

What could be the reason for my CSS animation with :hover @keyframes not functioning?

As a newcomer, I am struggling to understand why this code isn't functioning correctly. My goal is to create the illusion of a flying bird. This is my HTML: <img src="http://dl.dropboxusercontent.com/u/105046436/tw.png" /> <br> <div c ...

Send a GET request from a Node.JS server application to a React.JS client

Recently, I've been working on a project involving a Koa/Node JS backend that needs to make a GET request to an external API and pass the response body to a React JS client app. However, given my limited experience with Koa, Node JS, or servers in gen ...