Click SVG Element to Focus (and Style)

Avatar of Chris Coyier
Chris Coyier on

UGURUS offers elite coaching and mentorship for agency owners looking to grow. Start with the free Agency Accelerator today.

A reader writes in:

Is there anything on your site that shows me how to make an SVG clickable using CSS? As in, I have an SVG and I click on part of it and it should reveal an outline on that part of the element? I have a telephone interview Tuesday for a job as a remote SVG Illustrator and I don’t want to look like a turkey.

Say I have an <svg> of The United States and it’s like this:

<svg class="us" viewBox="0 0 500 400">

  <path d="..." class="wisconsin" />

  <polygon points="..." class="colorado" />

  <g class="michigan">
    <path d="..." class="michigan--up">
    <path d="..." class="michigan--main">
  </g>

  <!-- etc -->

</svg>

Each state then is kind of a direct descendant of the <svg>, the selector would be svg.us > *.

Typically, when I think “clickable”, I think JavaScript. Here’s how we could watch for clicks on each state. We’ll also apply a class to the state clicked:

var allStates = $("svg.us > *");

allStates.on("click", function() {
  
  allStates.removeClass("on");
  $(this).addClass("on");
  
});

That class will do the styling for us. You mentioned an outline, so let’s do that and a fill color as well:

.on {
  fill: pink;
  stroke: red;
  stroke-width: 2;
}

Tada!

See the Pen Click State to Activate by Chris Coyier (@chriscoyier) on CodePen.

But you DID say “clickable using CSS” specifically. That’s a little trickier. Usually we have :focus in CSS, but I don’t think there is any tried-and-true way to make an SVG element itself focusable. There was talk (long ago) of a focusable attribute, but I think that’s out. The HTML-way is tabindex, which I believe works in some browsers, but we can’t count on it. I think the best way is using anchors in SVG (yep, we can use them in SVG too!) which are focusable in all browsers. Then apply the :focus style to the anchor which cascades into the shapes.

Amelia Bellamy-Royds did just this in a StackOverflow thread. Here’s my slightly simplified version:

<svg viewBox="0 0 95 50">
  <a xlink:href="#0">
    <circle cx="20" cy="25" r="5" data-Name="shape 1" data-tabindex="0" />
  </a>
  <a xlink:href="#0">
    <circle cx="40" cy="25" r="5" data-Name="shape 2" data-tabindex="0" />
  </a>
  <a xlink:href="#0">
    <circle cx="60" cy="25" r="5" data-Name="shape 3" data-tabindex="0" />
  </a>
  <a xlink:href="#0">
    <circle cx="80" cy="25" r="5" data-Name="shape 4" data-tabindex="0" />
  </a>
</svg>
a:focus {
  fill: pink;
  stroke: red;
  stroke-width: 1;
}

That should do it:

See the Pen SVG with Focusable Elements by Chris Coyier (@chriscoyier) on CodePen.