Grow your CSS skills. Land your dream job.

Multi-Line Padded Text

Published by Chris Coyier

This is one of those tricky CSS things that I see come up every few months. I guess what better place to address it than CSS-Tricks eh?

The situation involves ragged-right inline text. Like when a paragraph of text breaks to the next line whenever the next word won't fit (i.e. most text on the internet). You want to add a background behind that text which:

  1. Follows the ragged-right edge
  2. Is padded along both the left and right edge of each line

What you can't do is simply apply a background and padding to, say, the <p> element. Paragraphs are block-level, so the background will simply be a rectangle and not follow the ragged-right-ness.

You also can't simply apply the background and padding to a <span> or an inline element. The left and right padding will only apply to the very first and very last line. On each of the middle lines, the background will butt up immediately next to the text.

Describing this is a bit futile. Here's the problem visually:

What we want is for each line to be padded like the beginning of that first line and end of that last line. We don't want to resort to anything gross like wrapping each line in it's own span (where lines break is to unpredictable). And there is no such thing as :nth-line unfortunately.

There are some solutions though!

Harry Robert's Pseudo Element / white-space Method

The big trick here is using white-space: pre-wrap; That gives us the padding on the ragged-right lines. Then to get the padding along the left, a pseudo element is added along the left edge. Here's the original and then my fork to show the elements at work:

See the Pen BtpGo by Chris Coyier (@chriscoyier) on CodePen

Unfortunately Firefox doesn't dig the way the pseudo element is positioned in that technique. Probably fixable, but, there might be a better way...

Fabien Doiron's box-shadow Method

Turns out you can use zero-spread box-shadow on an inline element on only the x-axis to pad each line. Essentially:

.padded-multi-line {
  display: inline;
  background: orange;
  box-shadow: 10px 0 0 orange, -10px 0 0 orange;
}

Here is the original and then my fork to show how it works:

See the Pen Wrapping Highlighted Text by Chris Coyier (@chriscoyier) on CodePen

Dave Rupert's JavaScript / Unicode Method

Fair warning: Dave says don't use this. I'm including it because I think it's clever and in some weird way actually feels less hacky to me. The idea is to go through the text of each element and replace the spaces with the unicode character \u205f, the MEDIUM MATHEMATICAL SPACE character. This works with the padding better on the right edge for whatever reason. For the left edge, you just use a border-left along the block-level parent element.

Here is the original and my stripped down fork:

See the Pen Wrapping Highlighted Text by Chris Coyier (@chriscoyier) on CodePen

It's a bit tricky to get the line-height just right so the border lines up with the padding, but I'm sure you can figure it out. There is probably even some fancy math to use to make sure it's right.

If JavaScript works for you, there is also a jQuery wraplines plugin in which then you could apply the padding to each individual line. Demo.

Matthew Pennell's Triple Element Method

Turns out you can do this with almost no fancy CSS or JS at all, but using three elements. You need a block-level parent for a border-left. Then an inline element to apply the padding and background to. Then another inline element to nudge the text back to the left to get the padding on the right edges.

<div class="padded-multiline">
  <h1>
    <strong>
      How do I add padding to subsequent lines of an inline text element?
    </strong>
  </h1>
</div>
.padded-multiline { 
  line-height: 1.3; 
  padding: 2px 0; 
  border-left: 20px solid #c0c;
  width: 400px;
  margin: 20px auto;
}
.padded-multiline h1 { 
  background-color: #c0c;
  padding: 4px 0;
  color: #fff; 
  display: inline;
  margin: 0; 
}
.padded-multiline h1 strong { 
  position: relative;
  left: -10px; 
}

The original is in this thread, and my demo:

See the Pen pvBFg by Chris Coyier (@chriscoyier) on CodePen

Adam Campbell's box-decoration-break Method

During a discussion that popped up over this, Adam pointed out there is a new CSS property that is (as I understand it) specifically for this. This removes the need for three elements. Technically you only need one, the inline element, but it's likely you'll be doing this on a header so you'll probably end up with a block-parent anyway, which is best for spacing.

Here is the original and my stripped down demo:

See the Pen hIvFe by Chris Coyier (@chriscoyier) on CodePen

This is working in modern Chrome and Safari, but not Firefox, in my quick tests. Even Chrome and Safari require it to be -webkit-box-decoration-break.

Any more?

That's all I was able to dig up, but I didn't spend an entire day searching or anything. Would love to hear more, particularly ones which require very little code, have good browser support, and don't feel hacky.

Comments

  1. Dave
    Permalink to comment#

    I’ve been looking for a way to do this on text that is centered. It looks like Fabien Doiron’s method or box-decoration-break are the only two techniques that will work with that.

  2. Merri
    Permalink to comment#

    You can use letter-spacing and text-shadow together to get some effect of a padding around the lines. However I went crazy with this and figured out you can also use text-indent and negative margin on inline elements and get some interesting results: http://codepen.io/Merri/pen/tDHsC

  3. Merri
    Permalink to comment#

    Also extra inline element allows for better control over box-shadow so that shadow color does not go on top of text: http://codepen.io/Merri/pen/giuLj

  4. Permalink to comment#

    You can kind of sort of do it with an outline and a single span:

    It’s hard to get it looking good though. Unfortunately, you can’t do individual sides for outlines. But maybe someone can tweak the values to make it look nicer.

    And what’s weird is when you adjust the line-height on the span you get this funky space-ship-dashboard like thing happening!

  5. ChrisB
    Permalink to comment#

    Yeah, I’ve struggled to find solutions for this before already, too.

    Sadly, the only one of the methods above that works when the line height is increased – so that you actually have several ”lines” of text with background and blank space in between the lines – is the box-shadow one. And that only works for colors, but not if you want to have a background image displayed over the whole line background.

    I can‘t believe they have not come up with something in CSS yet that would allow you to specify that you want to have the left and right padding for an inline element that stretches over multiple lines to be applied at the beginning and end of each line :-(

    I ended up with approaches like splitting text into elements containing single “words” with JS, and add side paddings to them, and trying to use word-spacing or negative margins to drag them close enough together again so that between words on one line the spacing looks like being the same as a single “space” again … but those approaches all had various cross-browser issues.

  6. Permalink to comment#

    The problem has been tackled last year on @HteuMeuLeu‘s blog (french)

    Lots of solutions in the comments (mostly in the french article) :
    [en]
    http://www.hteumeuleu.fr/a-css-brain-teaser/
    [fr]
    http://www.hteumeuleu.fr/un-joli-casse-tete-en-integration/

    Mine was this one : http://jsfiddle.net/oilvier/qktGR/

    But the best was probably this one : http://dabblet.com/gist/2994237

  7. Permalink to comment#

    I also find it very difficult to enable border-radius here.

  8. Samih
    Permalink to comment#

    My first reaction was “Who is asking you every few months “Can you please make all my text look hideously ugly?””.

    But by the end of the article it has grown on me. It has kind of a “cutting from the newspaper” feel to it.

  9. Merri
    Permalink to comment#

    @Louis mentioned outlines. Those have wide support in browsers. Unfortunatenaly some browsers (Firefox) also have some rounding errors which can cause one pixel gaps between the outline and the text box. The good news is it can be patched with 1px of box-shadow to left and right.

    Seems like the most cross-browser safe solution, looks great on anything I can test it on starting from IE8.

  10. GreLI
    Permalink to comment#

    The same problem was under discussion in Sergey Chikuyonok’s (Emmet author) blog back in 2010: “Even background under the text” (in russian). There are two solutions proposed: one utilizes ‘outline’ property and another uses nested elements with relative positioning.

  11. I’ve done this on a couple of websites recently.
    Intro text: http://www.jwrihoy.com/
    And the quotes: http://sueco.gg/

    Both needed line between the spaces too, took a while to get it how I wanted but happy with the result. The quotes cheat a bit and use an image, but the first one is pure CSS.

  12. Nice post!! Once I had to do something similar.
    I had an h1 where every word whitin it, was wrapped in a span element. Those span elements are floating and had a padding left/right to create the white-space between the words. Now I see there are a lot of solutions, but ey! it works. Here is my example: http://rehabitare.com/

  13. Michaela
    Permalink to comment#

    This worked best for me

    span {
    color: white;
    background-color: #343132;
    ** box-shadow: 0.5em 0 0 #343132,-0.5em 0 0 #343132;**
    }

    http://stackoverflow.com/questions/12709313/css-background-color-on-multi-line-text

  14. Permalink to comment#

    Needed this for a while! Great work.

  15. Permalink to comment#

    At first, the box-shadow method seems to work best, but when you view it on a high-dpi device, there always seem to be little overlaps or gaps – I can’t recommend it as a complete solution.

    • Vesa Piittinen
      Permalink to comment#

      Looks like there is a bug in iOS WebKit with box-shadow where it clips the shadow out entirely when you zoom in enough. This can be easily seen in my pen on iPad: http://codepen.io/Merri/full/giuLj

      The issue doesn’t replicate on desktop and trying to hack-fix it by forcing GPU drawing (-webkit-transform: translate3d(0, 0, 0);) didn’t do anything.

  16. Fabien’s box-shadow method owns! 2 seconds hack, and it works for me! It needs a little reconfig with paddings, but I love it:) Lifesaver hack:)

  17. Sachin
    Permalink to comment#

    Hi,

    Can any body tell me that how can we add background color to text in html without using css(no inline and no external css)

This comment thread is closed. If you have important information to share, you can always contact me.

*May or may not contain any actual "CSS" or "Tricks".