6

I have an SVG element as an icon that appears after a link:

enter image description here

<a class="external-link" href="http://www.google.com">google.com
    <svg class="external-link-svg">...</svg>
</a>

I want the underline to extend underneath the svg element. I have this working as seen from the image but the only way I've managed to do it is by inserting blank spaces in the CSS:

.external-link:after {
    content: "\00a0\00a0\00a0\00a0";
}

This feels like a bit of a hack because if I change icons, say for a wider or narrower one, the underline would no longer be the correct length.

Is there a way to extend the underline without resorting to injecting blank spaces?

Many thanks

RobotEyes
  • 4,929
  • 6
  • 42
  • 57

4 Answers4

8

2. Line Decoration: Underline, Overline, and Strike-Through

By default underlines, overlines, and line-throughs are applied only to non-replaced inline boxes, and are drawn across all text (including white space, letter spacing, and word spacing). Atomic inlines, such as images, are not decorated.

And I suppose SVGs are part of the atomic inlines. However if there is <text> element in the <svg>, it may inherit the line decoration style set on the container.

There are some alternative ways to get the similar results as underline decoration.

1. border-bottom

a {
  text-decoration: none;
  color: black;
  border-bottom: 1px solid;
}
<a href="#">Link <svg width='12' height='9' viewBox='0 0 12 9' fill-rule='evenodd'><path d='M4.1 6.1L1.4 3.4 0 4.9 4.1 9l7.6-7.6L10.3 0z'></path></svg></a>

2. box-shadow

a {
  text-decoration: none;
  color: black;
  box-shadow: inset 0 -1px 0 0 black;
}
<a href="#">Link <svg width='12' height='9' viewBox='0 0 12 9' fill-rule='evenodd'><path d='M4.1 6.1L1.4 3.4 0 4.9 4.1 9l7.6-7.6L10.3 0z'></path></svg></a>

3. background

a {
  text-decoration: none;
  color: black;
  background: linear-gradient(black, black) 0 100% / 1px 1px repeat-x;
}
<a href="#">Link <svg width='12' height='9' viewBox='0 0 12 9' fill-rule='evenodd'><path d='M4.1 6.1L1.4 3.4 0 4.9 4.1 9l7.6-7.6L10.3 0z'></path></svg></a>
Community
  • 1
  • 1
Stickers
  • 75,527
  • 23
  • 147
  • 186
3

Here a solution with the use of the default text-decoration where you can easily manage the overflow of the line:

span {
  position: relative;
  overflow: hidden;
  display: inline-block;
  vertical-align: bottom;
  padding-right: 10px;
  /* Control the overflow of line*/
}

span:after {
  content: "\00A0";
  position: absolute;
  text-decoration: underline;
  right: 0;
  left: 0;
  bottom: 0;
  top: 0;
  letter-spacing: 1000px;
}
a.through,a.through span:after {
 text-decoration:line-through;
}
<script defer src="https://use.fontawesome.com/releases/v5.0.6/js/all.js"></script>
<a href="#">google Link 
<span><svg width='12' height='9' viewBox='0 0 12 9' fill-rule='evenodd'><path d='M4.1 6.1L1.4 3.4 0 4.9 4.1 9l7.6-7.6L10.3 0z'></path></svg></span></a>
<br>
<a href="#">google Link <span><svg width="50" height="10">
  <rect width="50" height="10" style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
</svg></span></a>
<br>
<a href="#" class="through">google Link <span><svg height="10" width="10" viewbox="0 0 200 250 ">
  <polygon points="200,10 250,190 160,210" style="fill:lime;stroke:purple;stroke-width:1" />
</svg></span></a>
<br>
<a href="#" class="through">google Link 
<span><svg width='12' height='9' viewBox='0 0 12 9' fill-rule='evenodd'><path d='M4.1 6.1L1.4 3.4 0 4.9 4.1 9l7.6-7.6L10.3 0z'></path></svg></span></a>

How it works?

Since we cannot apply text-decoration to svg the idea is to wrap the svg inside a span and using a pseudo-element within the span we create a non-breakable space on where we can apply the text-decoration. The trick is to make this element absolute position and stretch it to the whole span and thus its size will be the same as the svg.

Then we use a big value of letter-spacing to be sure the line is big enough and we simply hide the non-needed part with overflow:hidden. And to control the overflow we can simply add some padding to the span.

Temani Afif
  • 245,468
  • 26
  • 309
  • 415
1

You can use :after pseudo css to draw the underline beneath..

Note: I have added a icon for now...you can place your svg instead of icon. Remember to put svg inside <a>

Stack Snippet

.external-link {
  position: relative;
  text-decoration: none;
  font-weight: bold;
  color: #000;
  font-family: verdana;
}

a.external-link:after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  border-bottom: 1px solid #000;
}
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">
<a class="external-link" href="#">google.com<i class="fa fa-home"></i></a>
Bhuwan
  • 16,525
  • 5
  • 34
  • 57
  • Where is the svg? – Stickers Feb 08 '18 at 15:07
  • @Stickers OP did not provide any svg..so I put the icon for reference...OP can use `svg` instead of icon – Bhuwan Feb 08 '18 at 15:16
  • it's not me but i have a simple question : why a pseudo element for border ? simply apply it to the element directly, easier and with few code – Temani Afif Feb 08 '18 at 15:39
  • 1
    Web font icons are considered as special characters (still text) and a svg is like image I think. BTW I didn't downvote. – Stickers Feb 08 '18 at 15:39
  • and i agree with @Stickers icon are still text .. text-decoration can still be applied to them check this https://stackoverflow.com/questions/48583982/underline-a-and-span-like-a-whole-link/48584144#48584144 – Temani Afif Feb 08 '18 at 15:40
  • in your case you simply need to change the icone to inline and keep text-decoration [ @Stickers ] .. so i agree a bit with the downvoter – Temani Afif Feb 08 '18 at 15:42
  • @TemaniAfif I used the pseudo element for the border because it gives you flexibility to change the position of border which can be seen in the OP provided image... – Bhuwan Feb 08 '18 at 15:45
  • and am sure you know padding :) we can manage the border with padding, so still don't see the utility of pseudo element – Temani Afif Feb 08 '18 at 15:47
  • @TemaniAfif the border beneath text is above the text baseline...can you control it with padding..? – Bhuwan Feb 08 '18 at 15:49
1

This is sort of a hack too but might be a starting point for improvments:

<span style="border-bottom: solid blue 1px;">
    <a href="http://google.com" style="text-decoration: none">google.com<img src="https://linearicons.com/free/icon/lnr-book.svg"/></a>
</span>

Also works with inline svg elements:

<span style="border-bottom: solid blue 1px;">
    <a href="http://google.com" style="text-decoration: none">google.com<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="20" height="20" viewBox="0 0 20 20">
<path fill="#000000" d="M14.5 18h-10c-0.276 0-0.5-0.224-0.5-0.5s0.224-0.5 0.5-0.5h10c0.276 0 0.5 0.224 0.5 0.5s-0.224 0.5-0.5 0.5z"></path>
<path fill="#000000" d="M16.5 3c-0.276 0-0.5 0.224-0.5 0.5v15c0 0.276-0.224 0.5-0.5 0.5h-11c-0.827 0-1.5-0.673-1.5-1.5s0.673-1.5 1.5-1.5h9c0.827 0 1.5-0.673 1.5-1.5v-12c0-0.827-0.673-1.5-1.5-1.5h-10c-0.827 0-1.5 0.673-1.5 1.5v15c0 1.378 1.122 2.5 2.5 2.5h11c0.827 0 1.5-0.673 1.5-1.5v-15c0-0.276-0.224-0.5-0.5-0.5zM3.5 2h10c0.276 0 0.5 0.224 0.5 0.5v12c0 0.276-0.224 0.5-0.5 0.5h-9c-0.562 0-1.082 0.187-1.5 0.501v-13.001c0-0.276 0.224-0.5 0.5-0.5z"></path>
</svg></a>
    
</span>
collapsar
  • 17,010
  • 4
  • 35
  • 61