Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

Fixing Horizontal Overflow in a div-based Grid Layout

4.88/5 (5 votes)
25 Jan 2016CPOL3 min read 14K   31  
How Bootstrap tackles this issue and what you can learn from this about the HTML property box-sizing

Introduction

Content grid container

We stumbled across this problem when setting up a base layout for a web page. The requirement was rather simple: Arrange the content in two, three or four equal columns on the page and stretch them over the available width. The total available width on the page is fix, but will be subject to change during the project.

Using the Code

Eventually, the requirement reminds you of the Bootstrap grid concept. Therefore we had a look at the Bootstrap col and container style definitions. Nevertheless, including the complete Bootstrap styling framework was not a favorite way to go.

Setting Up a Container and Several Columns

In our first approach, we defined a container div containing e.g. four columns as div elements.

HTML
<!-- index.html -->
<div class="container">
    <div class="column-25">
        Col 0
    </div>
    <div class="column-25">
        Col 1
    </div>
    <div class="column-25">
        Col 2
    </div>
    <div class="column-25">
        Col 3
    </div>
</div>

The container style contains with a fixed but changeable width (e.g. 20cm).

CSS
// style in index.html
.container {
    width: 25cm;
}

The columns style defines a relative width for the columns (e.g. 25%). To give the cells' content some space around, added a padding.

CSS
// style in index.html
.column-25 {
    float: left;
    padding: 20px;
    position: relative;
    width: 25%;
}

The result was not exactly what we were looking for. The last column word wrapped to the next row. Apparently, the columns' width in sum was greater than the available width in the container. Double checking our math (25% * 4 = 100%) proofed, the "error" must be located in the CSS/HTML code.

Horizontal overflow

The HTML Box Model

In HTML, every box element has a content area surrounded by three layers: Padding, border and margin (This link gives a good explanation).

By default, the width attribute of a box element defines the width of the content area. Padding, border and margin add their own areas around. So, the total demanded horizontal space of the box element is not only the content width, but the sum of content width, horizontal padding and margin and border width.

So, our columns have a width of 25% of the available width plus 40px padding (left and right). With four columns, we exceed the container width by eight times the padding value. This causes the horizontal overflow.

Bootstrap Solution

In the Bootstrap style sheet, this problem is tackled by the following definition:

CSS
// style in index.html
*, *:before, *:after {
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
}

Changing the box-sizing attribute from content-box to border-box, places content, padding and border within the box width (Read this). Vendor prefixed attributes -webkit-box-sizing and -moz-box-sizing only are added for backward compatibility concerning older browser versions. Marie Mosly wrote an article, which explains this topic.

For further details on available box-sizing modes, see this link.

With the selector *, the style definition gets applied to every HTML tag. This solves our problem for now, but may lead to some restrictions in the future.

Inherited box-sizing

Chris Coyer discusses this topic even further in this article. By defining box-sizing for any element at the root level, we force this attribute value on every element in the HTML DOM and potentially override the style of some components. By defining inherited box-sizing, we allow components to setup a box-sizing environment in the DOM without specifying the attribute for every child element.

CSS
// style in index.html
html {
    box-sizing: border-box;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
}
*, *:before, *:after {
    box-sizing: inherit;
    -webkit-box-sizing: inherit;
    -moz-box-sizing: inherit;
}

Changing the box-sizing model in the example solves this issue. To try it yourself, the example code is attached below.

No horizontal overflow

Example Code

Here is a short code example containing the mentioned style definitions. To "break" the columns, just remove lines 4 to 13.

HTML
<html>
    <head>
        <style>
            html {
                -webkit-box-sizing: border-box;
                -moz-box-sizing: border-box;
                box-sizing: border-box;
            }
            *, *, *:before, *:after {
                -webkit-box-sizing: inherit;
                -moz-box-sizing: inherit;
                box-sizing: inherit;
            }
            .container {
                width: 25cm;
                background-color: red;
            }
            .column-25 {
                background-color: blue;
                float: left;
                padding: 20px;
                position: relative;
                width: 25%;
            }
        </style>
    </head>
    <body>
        <div class="container">
            <div class="column-25">
                Col 0
            </div>
            <div class="column-25">
                Col 1
            </div>
            <div class="column-25">
                Col 2
            </div>
            <div class="column-25">
                Col 3
            </div>
        </div>
    </body>
</html>

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)