0

Has anyone come up with a good solution to ensure that an icon is always next to the word preceding it (i.e., it never wraps to the next line)?

Run the code snippet below to see the problem...

div {
  width: 52ch;
}

img {
  width: 16px;
  height: 16px;
}
<div>
  The next sentence has a multi-word link where the (i) icon should always be next to the word "link".
  This is a <a href="#">sample link<img src="https://www.svgrepo.com/show/20745/info.svg"></a>.
</div>

The goal is to always keep the (i) icon next to the word "link" so that it never becomes an orphan on the next line. If the sentence needs to wrap, then "link(i)" should wrap together as one unit.

Restrictions that I have no control over:

  1. I cannot do this because I'm not able to manipulate the DOM (this would have to be a pure CSS solution): <a href="#">sample <span class="no-wrap">link<img src="https://www.svgrepo.com/show/20745/info.svg"></span></a>

  2. I cannot use pseudo elements like ::before and ::after to render the icon because the icon can be after any word in the link, not necessarily the last word.

UPDATE: Thank you everyone who tried to help. They closed this as a duplicate, even though it's not a duplicate since the question was not about how to "stop text from taking up more than 1 line". This is taking up more effort than it's worth, so instead of trying to get this reopened I'm going to keep it closed and just accept that sometimes the icon will not be next to the preceding word. It's not aesthetically pleasing, but not the end of the world.

thdoan
  • 18,421
  • 1
  • 62
  • 57
  • You are making the div a fixed width and that is why the image is breaking to a new line. Remove or expand that width declaration amount and it will not break to a new line. Or use `white-space: nowrap` on the anchor. – TylerH May 02 '23 at 14:01
  • @TylerH the fixed width was used for demonstration purposes (so users can see the icon wrapping to the next line). – thdoan May 02 '23 at 20:51

4 Answers4

1

use font awesome icons, with css pseudo element ::after :

div {
  width: 52ch;
}

.infoLink::after {
  content: "\f05a";
  font-family: "Font Awesome 5 Free";
  font-weight: 900;
  margin-left: 5px;
}
<head>
<meta charset="UTF-8">
<title>Your Title Here</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" integrity="sha512-iecdLmaskl7CVkqkXNQ/ZH/XLlvWZOJyj7Yy7tcenmpD1ypASozpmT/E0iPtmFIB46ZmdtAc9eNBvH0H/ZpiBw==" crossorigin="anonymous" referrerpolicy="no-referrer" />
</head>
<div>
The next sentence has a multi-word link where the (i) icon should always be 
next to the word "link".
This is a <a class="infoLink" href="#">sample link</a>.
</div>

Links

AJ Zack
  • 205
  • 1
  • 8
  • 1
    The OP specifically says that: "I cannot use pseudo elements like ::before and ::after to render the icon."? – AngYC May 02 '23 at 01:09
  • Thanks, so far this is the best potential solution! I will need to see whether it's possible to replace the image with icon fonts first. If confirmed, I will accept this solution. – thdoan May 02 '23 at 06:08
  • Update: I cannot use this solution because the (i) icon isn't always after the last word in the link. Now I remember this was why one of the restrictions is no pseudo-elements. – thdoan May 02 '23 at 06:25
  • @thdoan I'm gonna submit how you can do that with font-awesome iframe, make sure to check it out ! – AJ Zack May 02 '23 at 13:15
0

What you need is a display: inline-block property on your a anchor tag. By default, the display property for a is inline.

The main difference between both of them is inline-block will ensures everything inside the element stays within the same line (acts as 1 single element regardless of what is inside the element), whereas inline will wrap to the next line if it runs out of space by creating new line inside the element, which is not what you want in this case.

a {
  display: inline-block;
}

div {
  width: 52ch;
}

img {
  width: 16px;
  height: 16px;
}
<div>
  The next sentence has a multi-word link where the (i) icon should always be next to the word "link".
  This is a <a href="#">sample link<img src="https://www.svgrepo.com/show/20745/info.svg" /></a>.
</div>

Reference: https://developer.mozilla.org/en-US/docs/Web/CSS/display


An alternative approach is to make use of characters that force the browser to never make newline:

div {
  width: 52ch;
}

img {
  width: 16px;
  height: 16px;
}

span {
  white-space: nowrap;
}
<div>
  The next sentence has a multi-word link where the (i) icon should always be next to the word "link".
  This is a <a href="#">sample link<span>&#8288;<img src="https://www.svgrepo.com/show/20745/info.svg" /></span></a>.
</div>

The &#8288; character is \u2060 in unicode that stands for Zero width no-break space (Word-joiner), it renders nothing on screen but is actually a character that forces it to not break at this character in Flow Layout. When used together with white-space: nowrap, the browser will not break at this character thus making sure the icon stays with the last word.

Specification on how Unicode breaks text which browser should follows: https://www.unicode.org/reports/tr14/#WJ

AngYC
  • 3,051
  • 6
  • 20
  • Thank you for submitting a solution. Unfortunately, I cannot use solution 1 because I still want the link to wrap in between words; I cannot use solution 2 because I cannot add elements inside the link. – thdoan May 02 '23 at 06:04
  • Hi @thdoan, but you specifically say no `::before` or `::after` but you still accept it... – AngYC May 02 '23 at 06:19
  • AngYC you're right, I cannot accept that solution because of the restriction -- I had forgotten about why there was that restriction in the first place. I have clarified the restrictions in the question. – thdoan May 02 '23 at 06:32
  • Hi @thdoan, can I check with you can the icon be anything other than `img`? Or is that a requirement as well? Thanks – AngYC May 02 '23 at 06:58
0

position the image relatively to the anchor parent:

div {
  width: 52ch;
}
a{
  position:relative;
}

img {
  width: 16px;
  height: 16px;
  position:absolute;
}
<div>
  The next sentence has a multi-word link where the (i) icon should always be next to the word "link".
  This is a <a href="#">sample link<img src="https://www.svgrepo.com/show/20745/info.svg"></a>.
</div>
AJ Zack
  • 205
  • 1
  • 8
  • Thanks for submitting a solution, however I cannot use this because making (i) absolute removes it from the layout, and I need it to be within the layout so that "link" wraps to the next line properly (for example, when you change width to 50ch). – thdoan May 02 '23 at 06:07
0

you can add the Icon anywhere in the link with font-aweseome and iframes:

div {
  width: 52ch;
}
<head>
<meta charset="UTF-8">
<title>Your Title Here</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" integrity="sha512-iecdLmaskl7CVkqkXNQ/ZH/XLlvWZOJyj7Yy7tcenmpD1ypASozpmT/E0iPtmFIB46ZmdtAc9eNBvH0H/ZpiBw==" crossorigin="anonymous" referrerpolicy="no-referrer" />
</head>
<div>
The next sentence has a multi-word link where the (i) icon should always be 
next to the word "link".
This is a 

<a class="infoLink" href="#">
  <i class="fa-solid fa-circle-info"></i>
icon at start link</a> ,

<a class="infoLink" href="#">
 icon at the 
 <i class="fa-solid fa-circle-info"></i>
middle link</a> ,
  
   <a class="infoLink" href="#">
icon at end link
<i class="fa-solid fa-circle-info"></i>
  </a> .

</div>
AJ Zack
  • 205
  • 1
  • 8