make an html svg object also a clickable link

HtmlObjectSvgAnchor

Html Problem Overview


I have an SVG object in my HTML page and am wrapping it in an anchor so when the svg image is clicked it takes the user to the anchor link.

<a href="http://www.google.com/">
    <object data="mysvg.svg" type="image/svg+xml">
        <span>Your browser doesn't support SVG images</span>
    </object>
</a>

When I use this code block, clicking the svg object doesn't take me to google. In IE8< the span text is clickable.

I do not want to modify my svg image to contain tags.

My question is, how can I make the svg image clickable?

Html Solutions


Solution 1 - Html

Actually, the best way to solve this is... on the <object> tag, use:

pointer-events: none;

Note: Users which have the Ad Blocker plugin installed get a tab-like [Block] at the upper right corner upon hovering (the same as a flash banner gets). By settings this css, that'll go away as well.

http://jsfiddle.net/energee/UL9k9/

Solution 2 - Html

I had the same issue and managed to solve this by:

Wrapping the object with an element set to block or inline-block

<a>
    <span>
        <object></object>
    </span>
</a>

Adding to <a> tag:

display: inline-block;
position: relative; 
z-index: 1;

and to the <span> tag:

display: inline-block;

and to the <object> tag:

position: relative; 
z-index: -1

See an example here: http://dabblet.com/gist/d6ebc6c14bd68a4b06a6

Found via comment 20 here https://bugzilla.mozilla.org/show_bug.cgi?id=294932

Solution 3 - Html

Would like to take credit for this but I found a solution here:

https://teamtreehouse.com/forum/how-do-you-make-a-svg-clickable

add the following to the css for the anchor:

a.svg {
  position: relative;
  display: inline-block; 
}
a.svg:after {
  content: ""; 
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left:0;
}


<a href="#" class="svg">
  <object data="random.svg" type="image/svg+xml">
    <img src="random.jpg" />
  </object>
</a>

Link works on the svg and on the fallback.

Solution 4 - Html

You could also stick something like this in the bottom of your SVG (right before the closing </svg> tag):

<a xmlns="http://www.w3.org/2000/svg" id="anchor" xlink:href="/" xmlns:xlink="http://www.w3.org/1999/xlink" target="_top">
	<rect x="0" y="0" width="100%" height="100%" fill-opacity="0"/>
</a>

Then just amend the link to suit. I have used 100% width and height to cover the SVG it sits in. Credit for the technique goes to the smart folks at Clearleft.com - that's where I first saw it used.

Solution 5 - Html

A simplification of Richard's solution. Works at least in Firefox, Safari and Opera:

<a href="..." style="display: block;">
    <object data="..." style="pointer-events: none;" />
</a>

See http://www.noupe.com/tutorial/svg-clickable-71346.html for additional solutions.

Solution 6 - Html

The easiest way is to not use <object>. Instead use an <img> tag and the anchor should work just fine.

Solution 7 - Html

To accomplish this in all browsers you need to use a combination of @energee, @Richard and @Feuermurmel methods.

<a href="" style="display: block; z-index: 1;">
    <object data="" style="z-index: -1; pointer-events: none;" />
</a>

Adding:

  • pointer-events: none; makes it work in Firefox.
  • display: block; gets it working in Chrome, and Safari.
  • z-index: 1; z-index: -1; makes it work in IE as well.

Solution 8 - Html

I resolved this by editing the svg file too.

I wrapped the xml of the whole svg graphic in a group tag that has a click event as follows:

<svg .....>
<g id="thefix" onclick="window.top.location.href='http://www.google.com/';">
 <!-- ... your graphics ... -->
</g>
</svg>

Solution works in all browsers that support object svg script. (default a img tag inside your object element for browsers that don't support svg and you'll cover the gamut of browsers)

Solution 9 - Html

i tried this clean easy method and seems to work in all browsers. Inside the svg file:

<svg>
<a id="anchor" xlink:href="http://www.google.com" target="_top">
  
<!--your graphic-->
  
</a>
</svg>
  

Solution 10 - Html

I was using simply

        <a href="#">
            <img src="../../assets/images/logo.svg" alt="">
        </a>

Which works fine except I was trying to apply a :hover state. What brought me here was when I used

        <a href="#">
            <object data="../../assets/images/logo.svg" type="image/svg+xml" class="logo">
            </object>
        </a>

I lost my link and noticed in DevTools that the link still appeared around the SVG, but the :hover state worked. Utilizing energee's elegant answer, my link worked, but of course I lost the :hover. So it looks like the object tag isn't a great solution for applying a :hover change to an SVG.

I am curious, why would you not use the img tag to display an SVG without anything special added to it, like :hover? Using the img tag also works with the a tag.

Solution 11 - Html

Just don't use <object>. Here's a solution that worked for me with <a> and <svg> tags:

<a href="<your-link>" class="mr-5 p-1 border-2 border-transparent text-gray-400 rounded-full hover:text-white focus:outline-none focus:text-white focus:bg-red-700 transition duration-150 ease-in-out" aria-label="Notifications">
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="30" 
    height="30"><path class="heroicon-ui" fill="#fff" d="M17 16a3 3 0 1 1-2.83 
    2H9.83a3 3 0 1 1-5.62-.1A3 3 0 0 1 5 12V4H3a1 1 0 1 1 0-2h3a1 1 0 0 1 1 
    1v1h14a1 1 0 0 1 .9 1.45l-4 8a1 1 0 0 1-.9.55H5a1 1 0 0 0 0 2h12zM7 12h9.38l3- 
   6H7v6zm0 8a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm10 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/>
    </svg>
</a>

Solution 12 - Html

This is very late, but I was wondering why energee's solution works: specifically, how the <object> element affects its parent elements.

tl;dr You cannot click on an anchor that has an <object> element in it because the click events are being captured by whatever is inside of the <object> element, which then doesn't bubble it back out.

jsfiddle


To expand on the symptom described in the original question: not only will an <object> element inside an anchor element cause the anchor to become unclickable, it seems that an <object> element as a child of any element will cause click, mousedown, and mouseup events (possibly touch events too) to not fire on the parent element, (when you are clicking inside the <object>'s bounding rect.)

<span>
    <object type="image/svg+xml" data="https://icons.getbootstrap.com/icons/three-dots.svg">
    </object>
</span>
document
    .querySelector('span')
    .addEventListener('click', console.log) // will not fire

Now, <object> elements behave somewhat "like" <iframe>s, in the sense that they will establish new browsing contexts, including when the content is an <svg> document. In JavaScript, this is manifested through the existence of the HTMLObjectElement.contentDocument and HTMLObjectElement.contentWindow properties.

This means that if you add an event listener to the <svg> element inside the <object>:

document
    .querySelector('object')
    .contentDocument  // returns null if cross-origin: the same-origin policy
    .querySelector('svg')
    .addEventListener('click', console.log)

and then click on the image, you will see the events being fired.

Then it becomes clear why the pointer-events: none; solution works:

  • Without this style, any MouseEvent that is considered "interactive" (such as click and mousedown, but not mouseenter) is sent to the nested browsing context inside the <object>, which will never bubble out of it.

  • With this style, the MouseEvents aren't sent into the <object> in the first place, then the <object>'s parent elements will receive the events as usual.

This should explain the z-index solution as well: as long as you can prevent click events from being sent to the nested document, the clicking should work as expected.

(In my test, the z-index solution will work as long as the parent element is not inline and the <object> is positioned and has a negative z-index)

(Alternatively, you can find a way to bubble the event back up):

let objectElem = document.querySelector('object')
let svgElemt = objectElem.contentDocument.querySelector('svg')

svgElem.addEventListener('click', () => {
    window.postMessage('Take this click event please.')
    // window being the outermost window
})

window.addEventListener('message', console.log)

Solution 13 - Html

Do it with javascript and add a onClick-attribute to your object-element:

<object data="mysvg.svg" type="image/svg+xml" onClick="window.location.href='http://google.at';">
    <span>Your browser doesn't support SVG images</span>
</object>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestioniancolemanView Question on Stackoverflow
Solution 1 - HtmlenergeeView Answer on Stackoverflow
Solution 2 - HtmlRichardView Answer on Stackoverflow
Solution 3 - HtmlnoelmcgView Answer on Stackoverflow
Solution 4 - HtmlBen FrainView Answer on Stackoverflow
Solution 5 - HtmlFeuermurmelView Answer on Stackoverflow
Solution 6 - HtmlErik DahlströmView Answer on Stackoverflow
Solution 7 - HtmlChristopherStrydomView Answer on Stackoverflow
Solution 8 - HtmlBruce PezzloView Answer on Stackoverflow
Solution 9 - HtmlDario RigonView Answer on Stackoverflow
Solution 10 - HtmlRostasanView Answer on Stackoverflow
Solution 11 - HtmlEge HurturkView Answer on Stackoverflow
Solution 12 - HtmlTony WuView Answer on Stackoverflow
Solution 13 - HtmlStefan FandlerView Answer on Stackoverflow