This is a little similar to a previous answer, but I thought that I'd flesh it out and explain it fully.
As soon as you set display: inline-block
, :after
becomes a non-text-binding element. This is why it wraps, and why nowrap has no effect. So leave display
alone.
As it's a text element by default, the content binds to previous text, as long as there's no whitespace between them. So don't add any, but make sure you have content: ""
, or it's the same as display: none
. The only problem is height
and width
are controlled by the content
, which in this case is collapsed. So width
is 0
, and height
is the line height.
Resize the area with padding; left or right, it doesn't matter. Add a little margin
so the icon doesn't touch the text. Keep everything as relative sizes (em
, pt
, etc.), and use background-size: contain
, so that the icon scales with the text, like an emoji or font. Finally position the icon where you want with background-position
.
ul li.completed a:after {
content: "";
background: url('icon.svg');
background-size: contain;
background-repeat: no-repeat;
background-position: center center;
margin-left: 0.2em; /* spacing*/
padding-right: 0.75em; /* sizing */
}
I've used this for my external links (a[href*="://"]:after
), and it's worked fine in Firefox, Chrome, and iOS. And since the icon remains a text element, even direct text after it binds, so any closing punctuation will wrap too.