内联块中的换行文本溢出父<pre> tag

时间:2015-12-10 01:04:56

标签: css word-wrap pre

I'm trying to find a way to add line numbers to text in a <pre> tag, while still allowing the text to wrap. This imposes some challenges:

  • The line numbers cannot be added in a separate column of a table (otherwise word wrapping would prevent them from lining up correctly).
  • Line numbers should not be included in the text body (they should not be copied when copy&pasting the text and wrapped lines should start to the right of the column of line numbers).

This has led me to my current solution which is to augment the text with two <span> elements, one containing the line number and one the text on that line [0]. To prevent the text in the second <span> from wrapping below the first <span>, it is styled as an inline-block:

span {
    display: inline-block;
    white-space: pre-wrap;
}

<pre><span>12345 </span><span>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</span>
</pre>

The problem with this is that the second <span> does indeed allow its content to wrap, but at a position that is past the end of the parent <pre>. It seems like the <span> wraps the text to a with equal to the width of the <pre>, regardless of how far it was moved to the right because of the first <span>.

Here is also a minimal example showing the behavior: http://jsfiddle.net/fgdhyde6/1/

My questions are:

  • Why is this happening? The behavior is equivalent in both Safari 9.0.1 and Firefox 42.0 so it does not look like an implementation bug/quirk.

  • If it is not a bug, how can I prevent it from happening with a general solution (which e.g. does not require me to hard-code the width of the first <span>)?

Update

This behavior does not seem to be limited to <pre> tags and special settings of white-space like pre-wrap, as I initially thought. It also happens with two <span> elements inside a <div>: http://jsfiddle.net/fgdhyde6/2/


[0]: In the end, the line numbers will be added with an appropriate :before { content: counter(...); }, which conveniently prevents the line numbers from ending up the clipboard. The problem with overflowing text appears with both methods.

1 个答案:

答案 0 :(得分:1)

Just use padding on <pre> and position .line-numbers absolute.

Please notice the change in HTML markup. If you are always going to have a line number span followed by a text span, you can use pre>span:nth-child(2n-1) instead of .line-number:

pre {
  border-style: solid;
  padding-left: 3rem;
  vertical-align: top;
  display: inline-block;
  white-space: pre-wrap;
}
pre>span:nth-child(4n+4) {
  background-color: #e5e5e5; /* this is just so you can see the size of it */
}
.line-number {
  position: absolute;
  left: 1rem;
}
<pre><span class="line-number">12345</span><span>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</span>
<span class="line-number">12346</span><span>Yr fap deep v pop-up occupy, pug mixtape lo-fi disrupt butcher. Keffiyeh umami yuccie disrupt cold-pressed migas. Fap offal pinterest, +1 retro squid tilde VHS street art thundercats tacos tote bag. </span>
<span class="line-number">12347</span><span>Cray direct trade photo booth, messenger bag taxidermy chillwave retro pitchfork kickstarter. Franzen echo park meggings photo booth cronut, swag cred chicharrones meh neutra dreamcatcher knausgaard church-key.</span>
<span class="line-number">12348</span><span>Gentrify forage chillwave hammock fashion axe bushwick, fap sartorial viral typewriter seitan squid health goth knausgaard selvage. Post-ironic intelligentsia kale chips blog.</span>
<span class="line-number">12348</span><span>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</span>
</pre>