Goran W
Goran W

Reputation: 317

Avoid line wrap between ::before pseudo-element and next word

The problem

I use ::before to generate a pseudo-element to display a small image left of the anchor text of links. However, when re-sizing the browser window's width, the line may become wrapped between the small image and the first word of the link anchor text, which is undesired.

Desired result

I want to keep the small image and the first word of the link anchor text together on the same line.

I keep display: inline on the a-tag because the link anchor text shall be able to wrap line, not as a whole atomic box, but so that its first word(s) fill up the current line and any remaining words continue on the next line.

Also, the text after the link shall continue on the same line as the last word of the link anchor text (provided there is space for its first word of course).

Note 1) If I would use display:inline-block on the a-tag, the entire link anchor text would wrap as a whole, which I do not want.

Note 2) I use display:inline-block on the pseudo-element because I need to set its width and height.

Note 3) I have tried with setting white-space: pre on the pseudo-element, but that did not solve the problem.

Thanks!

The code

The code is at JSFiddle and repeated below for completeness.

My HTML:

<p>
Text text <a class="pre-icon" href="#">FirstWord word2 word3</a> text after link.
</p>

My CSS:

.pre-icon::before {
    content: "";
    display: inline-block;
    width: 6px;
    height: 10px;
    background-color: transparent;
    background-image: url(data:image/gif;base64,R0lGODlhBgAKAJEAADM2Zv///////wAAACH5BAUUAAIALAAAAAAGAAoAAAINBIRimdvHFETOUWglKwA7);
    background-repeat: no-repeat;
    margin-left: .13em;
    margin-right: .25em;
    white-space: nowrap;
}

Upvotes: 8

Views: 6690

Answers (2)

Oriol
Oriol

Reputation: 288650

The problem is that the line break happens between the pseudo-element and the content, so you can't avoid it by setting white-space only to the pseudo-element.

Instead, you can wrap the content of the anchor inside a span, set white-space: nowrap to the entire anchor, and restore the initial white-space: normal in the span.

.pre-icon {
  white-space: nowrap;
}
.pre-icon > span {
  white-space: normal;
}

.pre-icon::before {
  content: "";
  display: inline-block;
  width: 6px;
  height: 10px;
  background-color: transparent;
  background-image: url(data:image/gif;base64,R0lGODlhBgAKAJEAADM2Zv///////wAAACH5BAUUAAIALAAAAAAGAAoAAAINBIRimdvHFETOUWglKwA7);
  background-repeat: no-repeat;
  margin-left: .13em;
  margin-right: .25em;
}
.pre-icon {
  white-space: nowrap;
}
.pre-icon > span {
  white-space: normal;
}
Text text <a class="pre-icon" href="#"><span>FirstWord word2 word3</span></a> text after link.

Upvotes: 11

ryantdecker
ryantdecker

Reputation: 1810

While it would be really cool if we could finally get a :first-word selector (Great post by Chris Coyier about that: https://css-tricks.com/a-call-for-nth-everything/), you probably need an extra span to do this. Here's a fork on your fiddle that looks to be doing what you described:

https://jsfiddle.net/0hrn2Lao/

HTML:

<p>Text text <a class="pre-icon" href="#">
  <span>FirstWord</span> word2 word3</a> text after link.
</p>

CSS:

.pre-icon span {
  display:inline-block;
  text-decoration:underline;}

.pre-icon span::before {
  content:"";
  display:inline-block;
  width:6px;
  height:10px;
  background-color:transparent;
  background-image:url(data:image/gif;base64,R0lGODlhBgAKAJEAADM2Zv///////wAAACH5BAUUAAIALAAAAAAGAAoAAAINBIRimdvHFETOUWglKwA7);
  background-repeat:no-repeat;
  margin-left:.13em;
  margin-right:.25em;
  white-space:nowrap;
}

Basically, put the pseudo element with the image on the span containing the first word, then let the span be inline-block, without having to put the inline-block rule on the <a> element itself.

If you wanted, you could probably use some jQuery to insert the span around the first word of <a class="pre-icon"> throughout the document - but if you're specifically adding that class, maybe it's not a lot of effort to just drop the span in manually too...depends on your pain tolerance, I guess :-)

Upvotes: 2

Related Questions