Wide content breaks my layout
Georges Trottier
October 3rd 2014

In exceptional circumstances, when a snippet of code is comprised of a long paragraph and when this snippet is contained in a DIV/CSS HTML "liquid" structure, my code highlighter breaks the layout of the page by overflowing the whole page to the right of the screen and generating a horizontal scroll bar. Using CSS like overflow:auto;, white-space: pre-wrap; and word-wrap: break-word; is no cure. A jQuery/CSS solution is presented that cures the problem but its causality is not known.

When writing HTML, I often find it handy to use <pre> tags whenever I want to include snippets of source code. <pre> tags are great, because they tell the browser to preserve all whitespace, including indentation, and not to do line wrapping. I use jQuery Chili to do the highlighting: it requires that I use a <code> tag inside the <pre> tag to process and highlight the snippet.

It was almost an accident! After the completion of a test program, I copied its source code on one page of this site: is was comprised of a title, a paragraph and a highlighted source listing:

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.js"></script>
    <script type="text/javascript" src="http://code.jquery.com/jquery-migrate-1.1.1.js"></script>
    <script type="text/javascript" src="/include/jquery.chili-2.2.js"></script>
    <script type="text/javascript" src="/include/recipes.js"></script>

    <style type="text/css">
      body { max-width:100% !important;} /* <-- solution */
      h1 {text-align: center; }
      p { font-family: verdana, sans-serif; font-size: 13pt; }
      pre { width: 95%; border: 5px double red; background-color: yellow;
        overflow: hidden; position: relative; }
    </style>

    <title>Test Chili printing</title>
  </head>

  <body>
    <h1>Test page for Chili printing with line-numbering "on"</h1>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est eleifend mi, non fermentum diam nisl sit amet erat. Duis semper. Duis arcu massa, scelerisque vitae, consequat in, pretium a, enim. Pellentesque congue.</p>
    <pre class="ln-"><code class="css">p.notebox {
      display:block;
      background: #eee;
      padding: 15px 45px 15px 60px;
      margin: 0 auto;
      position: relative;  
      /*Font*/
      font-size: 1.0em;
      line-height: 1.2;
      color: #000;
      text-align: justify;
    }</code></pre>
  </body>
</html>

A simple piece of code that would have been unnoticed save for the existence of line 23: a HTML paragraph, the source code of which is a string surrounded by the standard <p> tags. To my surprise, the layout went awry!

Find out how bad it is!
Click on the "Break layout" button to see how bad it is.

My layout was broken! Why? My site was originally structured with nested HTML tables. Three years ago, I re-created it and structured it with DIV/CSS in a liquid layout [Liquid layouts the easy way] which mimic HTML tables. I had never encountered any break of the layout until then.

What is it that makes this code snippet so different? There is a long paragraph in one of the lines of code:

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est eleifend mi, non fermentum diam nisl sit amet erat. Duis semper. Duis arcu massa, scelerisque vitae, consequat in, pretium a, enim. Pellentesque congue.</p>

The code highlighter processed it as HTML. It consists in reading each line of code, detecting each key element of the language using regexes and highlighting them with <span> tags with proper highlighting classes and popped out

<span class="html__tag_start">&lt;p</span><span class="html__tag_start">&gt;</span>Lorem&nbsp;ipsum&nbsp;dolor&nbsp;sit&nbsp;amet,&nbsp;consectetur&nbsp;adipiscing&nbsp;elit.&nbsp;Sed&nbsp;non&nbsp;risus.&nbsp;Suspendisse&nbsp;lectus&nbsp;tortor,&nbsp;dignissim&nbsp;sit&nbsp;amet,&nbsp;adipiscing&nbsp;nec,&nbsp;ultricies&nbsp;sed,&nbsp;dolor.&nbsp;Cras&nbsp;elementum&nbsp;ultrices&nbsp;diam.&nbsp;Maecenas&nbsp;ligula&nbsp;massa,&nbsp;varius&nbsp;a,&nbsp;semper&nbsp;congue,&nbsp;euismod&nbsp;non,&nbsp;mi.&nbsp;Proin&nbsp;porttitor,&nbsp;orci&nbsp;nec&nbsp;nonummy&nbsp;molestie,&nbsp;enim&nbsp;est&nbsp;eleifend&nbsp;mi,&nbsp;non&nbsp;fermentum&nbsp;diam&nbsp;nisl&nbsp;sit&nbsp;amet&nbsp;erat.&nbsp;Duis&nbsp;semper.&nbsp;Duis&nbsp;arcu&nbsp;massa,&nbsp;scelerisque&nbsp;vitae,&nbsp;consequat&nbsp;in,&nbsp;pretium&nbsp;a,&nbsp;enim.&nbsp;Pellentesque&nbsp;congue.<span class="html__tag_end">&lt;/p&gt;</span>

What was a standard paragraph with normal spaces had been transformed into a line containing live leading and trailing <span> tags with the equivalent of a very long word (the normal spaces have been replaced by non-breaking spaces) in between. It is really wide content!

Early investigations revealed that

What could I do next? Develop a test page with the code to be highlighted located in the <body> (with the proper links to the jQuery library) without any other structure. Surprise! The layout was intact.

Next, I wrapped this snippet in a DIV: same result. Then I styled this DIV with its display attribute set to table: Bang! the layout exploded. View this jsFiddle to visualize what is happening.

At this point, I knew the cause of the break-out but I did not yet know why it happened nor how to repair it.

A jQuery solution

In the CSS code, <pre> was styled with its max-width attribute set to 100%. I changed it to 1000px and the layout came out right. This means that I can avoid the break-out setting the display to a fixed number of pixels. Which one should I select? I don't know the particularities of the client screen and I need to adapt. Since the CSS code cannot (yet) contain variables, I turned to Javascript (jQuery) because, on DOM load, it will be able to set the max-width property to a proper value derived from reading live data on the client. Though I'm not a fan of applying CSS through JavaScript, here is what I have used:

$("pre").css('max-width', $("body").width());

and the layout no longer breaks up (both on the test case and on my web site). Why ask for more? Problem solved!

Differences between HTML and CSS Tables

The problem was behind me and I could have rested. No! I knew of a case where CSS looses control of the layout and I needed to know why. To this end, I had to find what makes display:table different from display:block reminding that display:table causes its DIV to mimic HTML tables. Would it be possible that the mimicking is not perfect?

HTML tables are block by default. In the CSS Table Model, the structuring CSS/DIVs have their attributes set to table, table-row and table-cell. In this model, the CSS/DIVs are supposed to have all the characteristics of tables.

Not quite so: tables have attributes attached to them and CSS/DIVs don't. Tables don't need external style sheets whereas CSS/DIVs do. Tables don't break when their content is too wide. It may not be so for the CSS/DIVs

I went a bit beyond that, I searched the W3C specifications and found this about the display property and its values:

block
This value causes an element to generate a block box.
inline-block
This value causes an element to generate an inline-level block container. The inside of an inline-block is formatted as a block box, and the element itself is formatted as an atomic inline-level box.
inline
This value causes an element to generate one or more inline boxes.
list-item
This value causes an element (e.g., LI in HTML) to generate a principal block box and a marker box. For information about lists and examples of list formatting, please consult the section on lists.
none
This value causes an element to not appear in the formatting structure (i.e., in visual media the element generates no boxes and has no effect on layout). Descendant elements do not generate any boxes either; the element and its content are removed from the formatting structure entirely. This behavior cannot be overridden by setting the 'display' property on the descendants.

Please note that a display of 'none' does not create an invisible box; it creates no box at all. CSS includes mechanisms that enable an element to generate boxes in the formatting structure that affect formatting but are not visible themselves. Please consult the section on visibility for details.

table, inline-table, table-row-group, table-column, table-column-group, table-header-group, table-footer-group, table-row, table-cell, and table-caption
These values cause an element to behave like a table element (subject to restrictions described in the chapter on tables).
Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification — W3C Recommendation 07 June 2011 9 — Visual formatting model — 9.2.4 The 'display' property

Note the « subject to restrictions described in the chapter on tables ». This lnk provides the following information:

table (In HTML: TABLE)
Specifies that an element defines a block-level table: it is a rectangular block that participates in a block formatting context.
inline-table (In HTML: TABLE)
Specifies that an element defines an inline-level table: it is a rectangular block that participates in an inline formatting context).
table-row (In HTML: TR)
Specifies that an element is a row of cells.
table-row-group (In HTML: TBODY)
Specifies that an element groups one or more rows.
table-header-group (In HTML: THEAD)
Like 'table-row-group', but for visual formatting, the row group is always displayed before all other rows and row groups and after any top captions. Print user agents may repeat header rows on each page spanned by a table. If a table contains multiple elements with 'display: table-header-group', only the first is rendered as a header; the others are treated as if they had 'display: table-row-group'.
table-footer-group (In HTML: TFOOT)
Like 'table-row-group', but for visual formatting, the row group is always displayed after all other rows and row groups and before any bottom captions. Print user agents may repeat footer rows on each page spanned by a table. If a table contains multiple elements with 'display: table-footer-group', only the first is rendered as a footer; the others are treated as if they had 'display: table-row-group'.
table-column (In HTML: COL)
Specifies that an element describes a column of cells.
table-column-group (In HTML: COLGROUP)
Specifies that an element groups one or more columns.
table-cell (In HTML: TD, TH)
Specifies that an element represents a table cell.
table-caption (In HTML: CAPTION)
Specifies a caption for the table. All elements with 'display: table-caption' must be rendered, as described in section 17.4.
Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification — W3C Recommendation 07 June 2011 — 17 Tables — 17.2 The CSS table model

All this to say that the block and table values of the display property look identical but differ slightly in their W3C definition.

Conclusion

I watched something exceptional happening: a condition has arisen that broke CSS control over the layout of a Web page! Its probability of occurrence is of the same order of magnitude as that of winning millions at the lottery. It happened to me (not the millions)!

I found a jQuery trick that allowed me to solve and forget the problem. Why bother! No! I am still intrigued since it shows that the mimicking of HTML tables by CSS tables is not perfect.


Questions or comments?
E-Mail
Last modified: October 11th 2014 13:26:11. []