SVG links: make a shape, text or map region clickable
Wrap a shape or text in an SVG a element to make it a link. How links behave inline, in an object and in an img tag, with code for a clickable map.
Published
SVG has its own <a> element. Wrap it round a shape, a group or a piece of text, give it an href, and that part of the drawing becomes a link, with no script needed.
<svg viewBox="0 0 100 100" width="200">
<a href="/contact/">
<circle cx="50" cy="50" r="40" fill="teal"/>
</a>
</svg>
Click the circle and the browser goes to the contact page. In Chrome the link behaved like an HTML one in every respect tested: the pointer became a hand over it, the Tab key reached it, and Enter followed it.
How it differs from an HTML link
SVG <a> | |
|---|---|
| Goes round | Shapes, groups, text, images: anything its parent may hold, except another <a> |
| Attributes | href, target, rel, download and the others HTML links have |
| Clickable area | The painted parts of the shapes inside it, not a rectangle round them |
| Keyboard | Focusable, and followed with Enter in Chrome. The SVG 2 specification requires browsers to make links focusable and usable from the keyboard |
| Older spelling | xlink:href, still accepted: see href and xlink:href |
The clickable area is the row that matters. An HTML link is a box. An SVG link is exactly the shapes it contains, following the same rules as any pointer event. A circle with fill="none" and a stroke is a link only along its outline: in the test, a click in its empty middle did nothing and a click on the line followed the link. To make the whole inside respond, give the shape fill="transparent" or pointer-events="all". SVG events explains those rules.
A clickable map
Each region is a path inside its own link. A hover style on the link shows which region the pointer is over:
<style>
.region:hover path,
.region:focus path {
fill: crimson;
}
</style>
<svg viewBox="0 0 100 100" width="300">
<a class="region" href="/north/" aria-label="North region">
<path d="M 10 10 H 90 V 45 H 10 Z" fill="teal"/>
</a>
<a class="region" href="/south/">
<title>South region</title>
<path d="M 10 55 H 90 V 90 H 10 Z" fill="gold"/>
</a>
</svg>
Two regions that turn red under the pointer or when reached with the Tab key, and go to their own pages when clicked.
A region that is only a shape has no text for a screen reader to announce, so each link needs a name. Both ways shown here worked in Chrome’s accessibility tree: aria-label on the link named it “North region”, and a <title> element as the link’s first child named the other “South region”. A <title> also shows as a tooltip on hover. Accessible SVG covers naming.
For a real map with dozens of regions, the pattern is the same. Open the file in the SVG viewer to find each region’s path, and wrap each one.
Linked text
A link can go round a whole <text> element, or sit inside one round a few words:
<svg viewBox="0 0 200 100" width="400">
<a href="/guide/">
<text x="10" y="30" font-size="16">Whole line</text>
</a>
<text x="10" y="70" font-size="16">
Read <a href="/guide/" fill="teal" text-decoration="underline">the guide</a> first
</text>
</svg>
The first line is a link from end to end. In the second, only “the guide” is. Clicking “Read” does nothing.
Unlike HTML, SVG gives link text no colour or underline of its own, so add them, as here with fill and text-decoration.
Opening in a new tab
target="_blank" works as in HTML:
<a href="https://example.com/" target="_blank" rel="noopener">
<circle cx="50" cy="50" r="40"/>
</a>
Tested in Chrome, the click opened a second tab and left the first where it was.
Where the SVG lives decides whether links work
| Placement | Do links inside the SVG work? |
|---|---|
Inline <svg> in the page | Yes |
| The .svg file opened directly | Yes |
<object data="map.svg"> | Yes, but the new page loads inside the object’s box unless the link has target="_top" |
<img src="map.svg"> or a CSS background | No |
An SVG shown through <img> is a flat picture: nothing in it can be clicked. In the test a click on a linked circle inside an <img> did nothing at all. Two remedies:
To link the whole picture, wrap the <img> in an HTML link:
<a href="/shop/">
<img src="/logo.svg" alt="Shop home" width="200" height="200">
</a>
The same works with an inline <svg> inside an HTML <a>. The whole box of the image is then the link, empty corners included.
To keep separate links on separate shapes, the SVG has to be inline or in an <object>.
Inside an <object>, the SVG is a document of its own. A plain link replaces the SVG within the object’s rectangle and leaves the page round it in place. target="_top" sends the whole window to the new address. Relative addresses also resolve from the SVG file’s own location, not the page’s: in the test, href="two.html" in /sub/file.svg went to /sub/two.html.
Links from script and CSS
A link is selected and styled like anything else: a:hover, a:focus-visible, svg a path. One difference catches people out in script. On an SVG link, link.href is not text but an object, and the address is in link.href.baseVal or link.getAttribute('href').
For actions that are not navigation, such as opening a panel on the same page, a link is the wrong element. Use a click handler, and make the shape focusable with tabindex="0": see SVG events.
Common problems
| What you see | Cause | Fix |
|---|---|---|
| The link does nothing | The SVG is shown with <img> or as a background | Inline the SVG, use <object>, or wrap the <img> in an HTML link |
| Only the outline is clickable | The shape has fill="none" | fill="transparent" or pointer-events="all" |
| The new page appears inside a small box | The SVG is in an <object> | target="_top" on the link |
| A linked SVG file opens the wrong address | Relative href values are resolved from the SVG file | Use addresses that start with /, or full URLs |
| The link text looks like ordinary text | SVG does not style links | Set fill and text-decoration |
| A link inside another link goes to the outer address | Links cannot be nested: the inner one is ignored | Make them siblings |
| The file will not open after adding links | xlink:href used without declaring xmlns:xlink | Use plain href |
| A screen reader announces only “link” | The link holds shapes and no text | aria-label, or a <title> as its first child |
Questions
Can you put links inside an SVG file? Yes. The <a> element is part of SVG, and links work when the file is opened in a browser or placed inline or in an <object>. They do not work where the file is shown as an image.
Do links survive in other programs? That depends on the program. Browsers follow them. Outside browsers it varies, and cutting or plotting software has no use for a link.
Can one link cover several shapes? Yes. Put all of them inside the same <a>, or put a <g> inside it. Each painted part is then clickable.
How do I change the cursor? A link shows the hand pointer already. For shapes that respond to script, set cursor: pointer in CSS.