I have the following CSS used to suffix a little SVG icon after every link text:
:any-link::after {
content: url("data:image/svg+xml,%3Csvg height='16' width='16' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath d='M320 0c-17.7 0-32 14.3-32 32s14.3 32 32 32l82.7 0L201.4 265.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L448 109.3l0 82.7c0 17.7 14.3 32 32 32s32-14.3 32-32l0-160c0-17.7-14.3-32-32-32L320 0zM80 32C35.8 32 0 67.8 0 112L0 432c0 44.2 35.8 80 80 80l320 0c44.2 0 80-35.8 80-80l0-112c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 112c0 8.8-7.2 16-16 16L80 448c-8.8 0-16-7.2-16-16l0-320c0-8.8 7.2-16 16-16l112 0c17.7 0 32-14.3 32-32s-14.3-32-32-32L80 32z' fill='blue' /%3E%3C/svg%3E");
}
p {
border: solid;
width: 16ch;
overflow: scroll;
resize: both;
}
<p>
Text with
<a href="#">short link</a>
and
<a href="#">some longer link</a>. (←Full stop.)
And even
<a href="#">very verbose link text</a>.
And
<a href="#">last link</a>!
</p>
My question: How do I prevent a line-break/line-wrap/word-wrap between an <a>…</a>
element and the little SVG icon that follows it, where the icon alone is left on the following line?
I also get a very similar problem, with a full stop following a link, leaving just the full stop on the next line:
The text-wrap
property does exactly what you want. It is considered Baseline newly available, though all browsers have supported the nowrap
property since at least early 2024 and many since 2023. Alternatively, you can use white-space: pre
. Both of these must be applied to the anchor tag to keep your pseudo elements together with the anchor tag text.
In order to deal with the wrapping of your ending punctuation, you have to make sure that there is no space (or line-break) between it and the last word or element in your sentence in your HTML. This will ensure that the HTML engine treats it as a single fragment.
Note that in the demo when you resize the first div the example anchor can break over a line-break, while neither the text-wrap nor the white-space anchors will wrap. Also, the exclamation point doesn't ever wrap in the first div. However, in the second div, where there's a line-break in the HTML before the exclamation point, it will wrap.
a[href^="https://" i]::after,
a[href^="http://" i]::after {
content: url("data:image/svg+xml,%3Csvg height='16' width='16' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath d='M320 0c-17.7 0-32 14.3-32 32s14.3 32 32 32l82.7 0L201.4 265.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L448 109.3l0 82.7c0 17.7 14.3 32 32 32s32-14.3 32-32l0-160c0-17.7-14.3-32-32-32L320 0zM80 32C35.8 32 0 67.8 0 112L0 432c0 44.2 35.8 80 80 80l320 0c44.2 0 80-35.8 80-80l0-112c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 112c0 8.8-7.2 16-16 16L80 448c-8.8 0-16-7.2-16-16l0-320c0-8.8 7.2-16 16-16l112 0c17.7 0 32-14.3 32-32s-14.3-32-32-32L80 32z' fill='blue' /%3E%3C/svg%3E");
vertical-align: middle;
padding-inline-start: .25rem;
}
a.nowrap {
text-wrap: nowrap;
}
a.pre {
white-space: pre;
}
p {
text-wrap: balance;
/* or pretty, which has less support */
}
/* demo only */
div {
resize: both;
overflow: scroll;
border: 1px solid;
width: 28ch;
padding: 1rem;
}
p {
margin: 0;
}
body {
display: flex;
gap: 1rem;
}
<div>
<p>
This is an
<a href="https://placehold.co/100x100">example</a>
with
<a href="https://placehold.co/100x100" class="nowrap">text-wrap</a>
and
<a href="https://placehold.co/100x100" class="pre">white-space</a>!
</p>
</div>
<div>
<p>
This is an
<a href="https://placehold.co/100x100">example</a>
that will wrap the
<a href="https://placehold.co/100x100">exclamation point</a>
!
</p>
</div>