tags:

views:

903

answers:

3

In designing a fluid layout, how do you use borders without ruining the layout.

More specifically, I have a HTML widget which consists of five divs. I would like the five divs to take up all the room in the containing element. I would also like to have a 1px border around each.

I tried: .box { float: left; height: 100%; width: 100%; border: 1px solid red; } This doesn't work: there will be an extra 10px in width causing the boxes to wrap. Reducing the width percentage doesn't work as it will not take up the correct amount of space and for certain page sizes, will still wrap.

Whats the proper way to manage the interaction between these elements?

+1  A: 

Only put width: 100% on the outermost div, and don't put a border on it. If you do this, then the inner boxes will fill the space (assuming you haven't floated them or anything) since they're block elements, and you won't have to worry about borders adding to the total size.

If you really need the appearance of five solid single pixel nested borders, you can do something like this (with properly semantic names, hopefully):

<div class="one">
    <div class="two">
        <div class="three">
        etc.
        </div>
    </div>
</div>

<style>
.one {
    width: 100%;
}
.two {
    border: 1px solid red;
    padding: 1px;
    background: red;
}
.three {
    border: 1px solid red;
    background: white;
}
</style>

As you can see, you can fake the second border using padding and background colors on the second div (might even cut down on the total number of divs by doing this; just remember you can't pad the outmost div without screwing up your width).

One Crayon
I wanted columns, so the markup would be something like:<div class="one"> <div class="two></div> <div class="two"></div> <div class="three"></div></div>And I want the columns to take up exactly the width of the containing box.
Ah, wish you'd specified that in the original post. You can do this with an extra wrapper div for each column. Give the outer-most div the width in percentages, and the inner div the border/padding/whatever.
One Crayon
A: 

This will get you fairly close but not 100% of the way (pun intended). To give an element 100% height it needs to know "100% of what?". All parent elements must also be given 100% height and this includes the body. Or as the W3C put it: "If the height of the containing block is not specified explicitly (i.e., it depends on content height), and this element is not absolutely positioned, the value computes to 'auto'." As you can see we also need to give the body "position: absolute;" for the height to be honored. This example also divides the width into five equal columns with borders (and some padding and margin just for fun):

<style>
body {
width: 100%;
height: 100%;
margin: 0;
position: absolute; 
/* overflow: hidden; */
}
div.section {
float: left;
width: 19.95%;
height: 100%;
}
    div.column {
    height: 100%;
    border: 1px solid blue;
    margin: 1em;
    padding: 2em;
    }
</style>

<div class="section"><div class="column">one</div></div>
<div class="section"><div class="column">two</div></div>
<div class="section"><div class="column">three</div></div>
<div class="section"><div class="column">four</div></div>
<div class="section"><div class="column">five</div></div>

As you can see when you test it we have no problem with the witdh. This is because the "sections" that divide the width have no padding, margin or borders. Thus the width we set will be the width they occupy on screen. Now, this is not strictly true in practice. I have actually set the widths 19.95% and not the expected 20%. Problem is that some browsers (IE for one) have a rounding error when adding up percentages and the more subdivisions to add up the greater the error.

Where this method obviously fails is when it comes to the height. Unlike "width: auto;", which will make the div occupy the available horizontal space, "height: auto;" will only make the div as tall as its content. You have to specify "height: 100%;" to get the div to fill the height of the window but alas, when adding margin, padding and borders, the rendered height of the div becomes greater than the viewport, resulting in a vertical scrollbar.

Here I can only really see two choices; Either 1) accept that the divs don't quite fill the window height and set their height to maybe 80% or 2) Skip the bottom border and set the body to "overflow: hidden;", which will crop off the parts of the divs that protrude beyond the edge of the window.

Finally, of course you could also make use of some simple scripting to achieve what you're after. Shouldn't be very complicated at all - but that's a question with another tag... Happy coding!

Ola Tuvesson
+1  A: 

See this article.

Basically, in the "traditional" CSS box model, the width of a box element only specifies the width of the content of the box, excluding its border (and padding).

In CSS3, you can switch to a different box model as follows:

box-sizing: border-box;

Browser-specific implementations of this are:

-moz-box-sizing: border-box; // for Mozilla
-webkit-box-sizing: border-box; // for WebKit
-ms-box-sizing: border-box; // for IE8

This will cause the box sizes to include the element's border and padding. So you can now specify

.box { 
   box-sizing: border-box;
   -moz-box-sizing: border-box;
   -webkit-box-sizing: border-box;
   -ms-box-sizing: border-box;
   width:20%;
   border:1px solid red;
   float:left
}

and have the five divs take up all the width of the containing element without wrapping.

Note that this is not supported by older browsers. For these, you'll have to wrap each box into a second box, as per other responses on this page.

RegDwight