3

Simply put, I am working on a responsive web layout with columns and rows. Each column width is set relevant to a predefined total width:

column width / total width = width %

and the height is fixed.

Now the problem is, I want the content width to be fluid but the margin and padding to be of fixed width as below.

enter image description here

enter image description here

The code looks something like this:

HTML

<body>
   <div id="left">Left</div>
   <div id="middle">Middle</div>
   <div id="right">Right</div>
</body>

CSS

div {
   float: left;
   padding: 0.5em;
   box-sizing: border-box;
   width: 33.3333333333333%; height 5em; line-height: 5em; text-align: center;
}    

#left {
   background-color: red;
}

#middle {
   background-color: green;
}

#right {
   background-color: blue;
}

http://jsfiddle.net/langoon/Zxn8E/2/

I have thought of some solutions but none of them seem to do what I am looking for :

  1. Set 'box-sizing' to 'margin-box'. Not supported in most browsers.
  2. Instead of margins, use borders. I might want that border and style it differently later.
  3. Nest each box in an outer 'div'. I prefer to keep the number of elements for the DOM to process at a minimum.
  4. Set negative margins as suggested here Fluid column layout with fixed pixel margins between them?. Seems to require an wrapping 'div' for each row and that might pose problems for me.
  5. JavaScript. No thanks.

Am I trying to have my cake and eat it at the same time or is there a way to do this without the drawbacks?

Community
  • 1
  • 1
unitario
  • 6,295
  • 4
  • 30
  • 43

3 Answers3

3

With :before / :after

I had fun with :before and :after pseudos, covering half of each gutter with a rectangle: http://jsfiddle.net/PhilippeVay/Zxn8E/11/ (note where the ending tags are, to prevent any whitespace between inline-block elements)

Compatibility: IE8+ as IE7 and lesser don't understand these pseudos.

With Flexible Box Layout Module

This CSS3 module will let you have equal width columns with gutter inside and none outside, exactly what you want to achieve. No fiddle as the syntax changed twice in a few months, I still haven't looked at the new one.
Compatibility on caniuse.com (no IE9-, no Opera)

FelipeAls
  • 21,711
  • 8
  • 54
  • 74
  • I will accept your answers because answered exactly what I asked for. However, I do have some issues (never happy). In your first example, each div comes with an 'position'. What if I decide to throw in more rows underneath just for fun, after all this is fluid design, no div would want to be cornered at the same position. Things move about, fluid! Then your second example is very attractive, yet it is not compatible with IE sub 7 and Opera which calls for separate designs. I just have the feeling there must be something simpler out there. – unitario Aug 20 '12 at 19:49
  • My colleague thought about `border-spacing` with CSS tables (perfect for the white borders between each block as there's no margins in this case and padding will have the same colored background). Still IE8+ though. IE7- : forget about 100% width and go with inline-block. Or HTML tables (there are cases where it's compatibility with buggy browsers or semantics). EDIT: Grid layout is IE10 only (and no other browser for now) – FelipeAls Aug 22 '12 at 15:05
1

I think the best way to solve this is using a negative margin and the box-sizing property. A quick example:

HTML:

<ul>
    <li><div class="red">Red</div></li>
    <li><div class="green">Green</div></li>
    <li><div class="blue">Blue</div></li>
</ul>

CSS:

ul
{
    list-style: none;
    margin: 0 0 0 -15px; /* Note the negative margin */
    padding: 0;
    overflow: hidden;
}

li
{
    float: left;
    width: 33.3333%;
    padding: 0 0 25px 15px;
    box-sizing: border-box;
}

/* Some decorations */
div { padding: 25px 0; color: white; text-align: center; }
div.red { background: red; }
div.green { background: green; }
div.blue { background: blue; }

Result:

enter image description here

Live Demo

If you want to see this in action, I've created a Fiddle.

Jonathan
  • 18,229
  • 10
  • 57
  • 56
0

Try the border route:

http://jsfiddle.net/Zxn8E/3/

div {
    float: left;
    box-sizing: border-box;

    border-top:0.5em solid cyan;
    border-bottom:0.5em solid cyan;
    border-left:0.5em solid cyan;

    width: 33.3333333%; height 5em; line-height: 5em; text-align: center;
}    

div.last{ border-right:0.5em solid cyan; } 


<body>
  <div id="left">Left</div>
  <div id="middle">Middle</div>
  <div id="right" class="last">Right</div>
</body>
Lowkase
  • 5,631
  • 2
  • 30
  • 48
  • If I let borders serve as margins there are two constraints: 1. I have no option to style my own borders if I would like so, and 2. it only works (looks aesthetically presentable) if the background of the 'div' is transparent and the background of 'body' is of one single color. I addressed the border dilemma above. – unitario Aug 20 '12 at 17:55