infogulch
infogulch

Reputation: 1291

How to make svg added as css ::after content scale to the size of the font

I have some generated html that has headers with appended anchors (no content, but with a unique id), and I'm adding a 'link icon' that pops up when you hover the header to make it easy to get a link directly to that header. Like github does with rendered markdown.

What I have so far works OK and has some nice benefits for me:

The issue is that the icon size doesn't scale with with the font size of the header. Notice how the icon is a somewhat reasonable size when you hover h1-h2, but then it is way too big for h3-h6:

Target code shape

:where(h1, h2, h3, h4, h5, h6):hover span.icon.icon-link:after {
  /* example svg; real svg is much bigger */
  content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 100 100" class="keyicon"><circle cx="50" cy="50" r="50" fill="currentColor"/></svg>');
  margin-left: 0.1em;
  cursor: pointer;
}
<h1>Hello h1<a id="hello"><span class="icon icon-link"></span></a></h1>
<h2>World h2<a id="world"><span class="icon icon-link"></span></a></h2>
<h3>Test h3<a id="test"><span class="icon icon-link"></span></a></h3>
<h4>Foo h4<a id="foo"><span class="icon icon-link"></span></a></h4>
<h5>Bar h5<a id="bar"><span class="icon icon-link"></span></a></h5>
<h6>Blah h6<a id="blah"><span class="icon icon-link"></span></a></h6>

Non-solution: Just embed the svg into the html

This is visually what I'm looking for, but is problematic for two reasons: 1. it duplicates the svg for each header; the real svg is big and this would be wasteful. 2. it's easier for me to modify css than the html generated by the tool I'm using.

:where(h1, h2, h3, h4, h5, h6) span.icon.icon-link svg {
  display: none;
  
  margin-left: 0.1em;
  cursor: pointer;
}

:where(h1, h2, h3, h4, h5, h6):hover span.icon.icon-link svg {
  display: inline;
  
  height: 0.8em;
  width: 0.8em;
}
<h1>Hello h1<a id="hello"><span class="icon icon-link"><svg viewBox="0 0 100 100" class="keyicon"><circle cx="50" cy="50" r="50" fill="currentColor"/></svg></span></a></h1>
<h2>World h2<a id="world"><span class="icon icon-link"><svg viewBox="0 0 100 100" class="keyicon"><circle cx="50" cy="50" r="50" fill="currentColor"/></svg></span></a></h2>
<h3>Test h3<a id="test"><span class="icon icon-link"><svg viewBox="0 0 100 100" class="keyicon"><circle cx="50" cy="50" r="50" fill="currentColor"/></svg></span></a></h3>
<h4>Foo h4<a id="foo"><span class="icon icon-link"><svg viewBox="0 0 100 100" class="keyicon"><circle cx="50" cy="50" r="50" fill="currentColor"/></svg></span></a></h4>
<h5>Bar h5<a id="bar"><span class="icon icon-link"><svg viewBox="0 0 100 100" class="keyicon"><circle cx="50" cy="50" r="50" fill="currentColor"/></svg></span></a></h5>
<h6>Blah h6<a id="blah"><span class="icon icon-link"><svg viewBox="0 0 100 100" class="keyicon"><circle cx="50" cy="50" r="50" fill="currentColor"/></svg></span></a></h6>

Notes

Upvotes: 3

Views: 635

Answers (1)

infogulch
infogulch

Reputation: 1291

In this case I used content: url( ... ) but I could use background-image: url( ... ) instead. Thanks to @enxaneta for the observation.

This also has a nice little animation when hovering over the link icons:

body {
  font-size: 1.6em;
}

:where(h1, h2, h3, h4, h5, h6) a[id] {
  display: inline;
  background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg>');
  background-repeat: no-repeat;
  background-position: center center;
  background-size: 0;
  height: 1em;
  width: 1em;
  padding-left: 1em;
  padding-right: 0.5em;
  cursor: pointer;
  transition: background-size 32ms;
}

:where(h1, h2, h3, h4, h5, h6):hover a[id] {
  background-size: 0.8em;
  transition-duration: 64ms;
}

:where(h1, h2, h3, h4, h5, h6):hover a[id]:hover {
  background-size: 0.9em;
  transition-duration: 128ms;
}
<h1>Hello h1<a id="hello" href="#hello" title="Link to header"></a></h1>
<h2>World h2<a id="world" href="#world" title="Link to header"></a></h2>
<h3>Test h3<a id="test" href="#test" title="Link to header"></a></h3>
<h4>Foo h4<a id="foo" href="#foo" title="Link to header"></a></h4>
<h5>Bar h5<a id="bar" href="#bar" title="Link to header"></a></h5>
<h6>Blah h6<a id="blah" href="#blah" title="Link to header"></a></h6>

Editable: https://codepen.io/infogulch/pen/BaYBZxa?editors=1100

Upvotes: 2

Related Questions