208

Let's say I have this HTML:

<h3>Features</h3>
<ul>
    <li><img src="alphaball.png">Smells Good</li>
    <li><img src="alphaball.png">Tastes Great</li>
    <li><img src="alphaball.png">Delicious</li>
    <li><img src="alphaball.png">Wholesome</li>
    <li><img src="alphaball.png">Eats Children</li>
    <li><img src="alphaball.png">Yo' Mama</li>
</ul>

and this CSS:

li { text-align:center; display:inline-block; padding:0.1em 1em }
img { width:64px; display:block; margin:0 auto }

The result can be seen here: http://jsfiddle.net/YMN7U/1/

Now imagine that I want to break this into three columns, the equivalent of injecting a <br> after the third <li>. (Actually doing that would be semantically and syntactically invalid.)

I know how to select the third <li> in CSS, but how do I force a line break after it? This does not work:

li:nth-child(4):after { content:"xxx"; display:block }

I also know that this particular case is possible by using float instead of inline-block, but I am not interested in solutions using float. I also know that with fixed-width blocks this is possible by setting the width on the parent ul to about 3x that width; I am not interested in this solution. I also know that I could use display:table-cell if I wanted real columns; I am not interested in this solution. I am interested in the possibility of forcing a break inside inline content.

Edit: To be clear, I am interested in 'theory', not the solution to a particular problem. Can CSS inject a line break in the middle of display:inline(-block)? elements, or is it impossible? If you are certain that it is impossible, that is an acceptable answer.

Phrogz
  • 296,393
  • 112
  • 651
  • 745
  • 2
    Put the 1st three and the 2nd three in two different lists? I'm assuming you don't want to do this, but I thought I"d throw it out there. – JakeParis Jan 05 '11 at 21:22
  • Looks like you need to tell us what you are really trying to achieve here so someone can recommend the best method. All the options you excluded exist to solve the problem you have, why is another solution needed? – Jake Jan 05 '11 at 21:22
  • 5
    @Jake I was in fact doing exactly what I stated: using a semantic list of elements and wanting to wrap after particular ones. In practice I set the width of the container, but this only works in my particular case because the items happened to be the same width and I wanted them to wrap at a consistent edge. This might not always be the case. What I am _"really trying to achieve"_ is learn whether or not CSS can force a line break in the middle of inline flow. The confident answer _"This is definitely not possible"_ is acceptable (if correct). – Phrogz Jan 05 '11 at 21:30

9 Answers9

304

I've been able to make it work on inline LI elements. Unfortunately, it does not work if the LI elements are inline-block:

Live demo: http://jsfiddle.net/dWkdp/

Or the cliff notes version:

li { 
     display: inline; 
}
li:nth-child(3):after { 
     content: "\A";
     white-space: pre; 
}
Luca
  • 9,259
  • 5
  • 46
  • 59
Šime Vidas
  • 182,163
  • 62
  • 281
  • 385
  • 2
    Sime, why does the "\A" not get printed out? Everything I've tried with the `:after` always prints as straight text. – JakeParis Jan 05 '11 at 21:44
  • 12
    @JMCCreative That's ASCII 0x0A, AKA a LF (line feed) character. See http://www.w3.org/TR/CSS2/syndata.html#strings – Phrogz Jan 05 '11 at 21:46
  • 5
    @JMC `\A` is the line feed character... it's an escape – Šime Vidas Jan 05 '11 at 21:47
  • This is a very interesting result, thank you. (I'll vote you up when I get more votes in a few hours.) – Phrogz Jan 05 '11 at 21:51
  • Can 1 of you point me in the direction of a chart or something that would show me which of the ASCII characters are possible in the `content:` block? I googled it, but I'm not getting the right stuff. Thanks – JakeParis Jan 05 '11 at 21:57
  • 3
    @JMC Official spec: http://www.w3.org/TR/CSS21/syndata.html#strings Sitepoint: http://reference.sitepoint.com/css/content – Šime Vidas Jan 05 '11 at 22:05
  • How can you break a new line after the last element? – vsync Feb 21 '13 at 17:56
  • Great tip! Unfortunately, this does not work well with the minimizing functionality in MVC ScriptBundle, as the minimizing code actually replaces the ´\A´ with a line break in the resulting CSS code, and makes the css invalid... I don't understand why it does it (spare one byte, but make it buggy...) – awe Feb 25 '13 at 07:42
  • I was looking for a way to add some extra spacing along with the newlines, and found that if you add `font-size: 1.3em; vertical-align: top;` it's the equivalent of a 0.3em margin along with the newline. http://jsfiddle.net/mblase75/SmEnR/ – Blazemonger Jul 08 '13 at 13:52
  • 20
    commenting here as I keep coming back to this question every few months... It won't work on inline-block because you are adding line breaks within something that it acting like a block container within an inline context. If you could break out of the context by inserting the line break between the
  • s it would work. Shame really as this is useful for responsive design breakpoints. I guess most of the time "inline" is just as useful as inline-block for lists
  • – user1010892 Aug 07 '13 at 14:04
  • 2
    @AntonioMax You don't *think*? Have you tested? – Šime Vidas Aug 08 '13 at 00:35
  • I'd avoid :after if possible as it doesn't work for IE7 and has partial support in IE8. If you don't have to support those then go nuts (we do so don't use css content generators) – nbsp Nov 21 '13 at 19:36
  • 1
    You can always have `inline` `li`s and make their only child `inline-block`. That way you can insert a line break wherever you want and still get block behavior inside each `li`. – instanceofnull Mar 10 '15 at 16:33
  • @randombumper And you didn’t make a demo and show it to me because…? :) – Šime Vidas Mar 10 '15 at 16:35
  • @ŠimeVidas Ahh, I have coding to do and bills to pay, but since you asked so nicely and smiled... https://jsfiddle.net/p39L92xn/9/ :) – instanceofnull Mar 11 '15 at 17:11
  • @randombumper Why stop at inline-block? But true blocks in there :) http://jsbin.com/herofe/edit?html,css,output – Šime Vidas Mar 14 '15 at 05:08
  • @ŠimeVidas inline-blocks allow for out-of-the-box automatic width, just what I wanted :) – instanceofnull Mar 14 '15 at 14:12
  • What about the cross-browser compatibility ? Thanks. – Charaf Jan 04 '17 at 03:29
  • @Charaf Works everywhere I’ve checked. – Šime Vidas Jan 04 '17 at 04:47
  • Great, but sadly not working in IE11 + Edge when used with padding. – Markus Zeller Jun 29 '17 at 11:02
  • Thank you! you can go for white-space:pre-line to avoid side effects – Sebastian Rothbucher Jul 26 '17 at 14:00
  • @tatsu Works for me. What Chrome version and operating system do you have? – Šime Vidas Nov 03 '17 at 12:40
  • @ŠimeVidas windows 10 and latest chrome but it's fine I've used Marcus Whybrow's method – tatsu Nov 03 '17 at 13:48