Reputation: 2786
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?
Upvotes: 175
Views: 163433
Reputation: 57
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.
Upvotes: 1
Reputation: 113
This is very late, but I was wondering why energee's solution works: specifically, how the <object>
element affects its parent elements.
<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.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 MouseEvent
s 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)
Upvotes: 3
Reputation: 983
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>
Upvotes: 0
Reputation: 596
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
Upvotes: 49
Reputation: 9942
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.
Upvotes: 27
Reputation: 2853
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/
Upvotes: 271
Reputation: 2568
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.
Upvotes: 34
Reputation: 31
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>
Upvotes: 3
Reputation: 8186
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.Upvotes: 12
Reputation: 31
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)
Upvotes: 3
Reputation: 1067
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.
Upvotes: 36
Reputation: 61026
The easiest way is to not use <object>. Instead use an <img> tag and the anchor should work just fine.
Upvotes: 19
Reputation: 1141
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>
Upvotes: -5