72

I have the following HTML layout:

<div class="container">
   <div class="column-center">Column center</div>
   <div class="column-left">Column left</div>
   <div class="column-right">Column right</div>
</div>

Any chance to arrange the columns like on the below sample grid without changing HTML using CSS only?

----------------------------------------------------
|              |                   |               |
| Column left  |   Column center   | Column right  |
|              |                   |               |
----------------------------------------------------
easwee
  • 15,757
  • 24
  • 60
  • 83

5 Answers5

156

Something like this should do it:

.column-left{ float: left; width: 33.333%; }
.column-right{ float: right; width: 33.333%; }
.column-center{ display: inline-block; width: 33.333%; }

DEMO

EDIT

To do this with a larger number of columns you could build a very simple grid system. For example, something like this should work for a five column layout:

.column {
    float: left;
    position: relative;
    width: 20%;
  
    /*for demo purposes only */
    background: #f2f2f2;
    border: 1px solid #e6e6e6;
    box-sizing: border-box;
}

.column-offset-1 {
    left: 20%;
}
.column-offset-2 {
    left: 40%;
}
.column-offset-3 {
    left: 60%;
}
.column-offset-4 {
    left: 80%;
}

.column-inset-1 {
    left: -20%;
}
.column-inset-2 {
    left: -40%;
}
.column-inset-3 {
    left: -60%;
}
.column-inset-4 {
    left: -80%;
}
<div class="container">
   <div class="column column-one column-offset-2">Column one</div>
   <div class="column column-two column-inset-1">Column two</div>
   <div class="column column-three column-offset-1">Column three</div>
   <div class="column column-four column-inset-2">Column four</div>
   <div class="column column-five">Column five</div>
</div>

Or, if you are lucky enough to be able to support only modern browsers, you can use flexible boxes:

.container {
    display: flex;
}

.column {
    flex: 1;
    
    /*for demo purposes only */
    background: #f2f2f2;
    border: 1px solid #e6e6e6;
    box-sizing: border-box;
}

.column-one {
    order: 3;
}
.column-two {
    order: 1;
}
.column-three {
    order: 4;
}
.column-four {
    order: 2;
}
.column-five {
    order: 5;
}
<div class="container">
   <div class="column column-one">Column one</div>
   <div class="column column-two">Column two</div>
   <div class="column column-three">Column three</div>
   <div class="column column-four">Column four</div>
   <div class="column column-five">Column five</div>
</div>
Turnip
  • 35,836
  • 15
  • 89
  • 111
  • 1
    This works in all browsers including IE8. IE7 is the only one that does not support inline-block on block elements so it fails, but since I don't have to support it anymore this solves my problem! – easwee Dec 13 '13 at 13:00
  • 1
    What if there is an arbitrary number of columns? Say, from 2 to 5. Is it possible to style them all with the same CSS? – Alexei Sholik Apr 11 '14 at 09:58
  • Add text-align: center; to the container element to actually have it even. – Mustafa Dec 01 '14 at 06:32
  • What about responsiveness, when it gets smaller my middle column is overlaying the right one... – Lion789 Mar 03 '16 at 02:06
  • 1
    .column-center should have a width of 34% so that the cols sum up to 33 + 34 + 33 = 100% width. Or else there will be a slightly wider gap between mid and right col making the 3 cols not perfectly symmetric. – James_ May 28 '16 at 08:17
  • What if I wanna change the width of the columns with the flexible boxes approach? Tried setting `width: 20%;` on the `column-one` but it didn't work. – Bruno Gasparotto Apr 06 '17 at 02:24
  • Is the columns in the flex box example are in the wrong order. Is this deliberate? – E_net4 May 15 '19 at 14:13
  • @E_net4 The question was about reordering columns; so yes, it is deliberate. – Turnip May 15 '19 at 14:52
  • This is a very useful and descriptive answer. Thank you! – Mmm Jul 08 '19 at 18:53
22

This is less for @easwee and more for others that might have the same question:

If you do not require support for IE < 10, you can use Flexbox. It's an exciting CSS3 property that unfortunately was implemented in several different versions,; add in vendor prefixes, and getting good cross-browser support suddenly requires quite a few more properties than it should.

With the current, final standard, you would be done with

.container {
    display: flex;
}

.container div {
    flex: 1;
}

.column_center {
    order: 2;
}

That's it. If you want to support older implementations like iOS 6, Safari < 6, Firefox 19 or IE10, this blossoms into

.container {
    display: -webkit-box;      /* OLD - iOS 6-, Safari 3.1-6 */
    display: -moz-box;         /* OLD - Firefox 19- (buggy but mostly works) */
    display: -ms-flexbox;      /* TWEENER - IE 10 */
    display: -webkit-flex;     /* NEW - Chrome */
    display: flex;             /* NEW, Spec - Opera 12.1, Firefox 20+ */
}

.container div {
    -webkit-box-flex: 1;      /* OLD - iOS 6-, Safari 3.1-6 */
    -moz-box-flex: 1;         /* OLD - Firefox 19- */
    -webkit-flex: 1;          /* Chrome */
    -ms-flex: 1;              /* IE 10 */
    flex: 1;                  /* NEW, Spec - Opera 12.1, Firefox 20+ */
}

.column_center {
    -webkit-box-ordinal-group: 2;   /* OLD - iOS 6-, Safari 3.1-6 */
    -moz-box-ordinal-group: 2;      /* OLD - Firefox 19- */
    -ms-flex-order: 2;              /* TWEENER - IE 10 */
    -webkit-order: 2;               /* NEW - Chrome */
    order: 2;                       /* NEW, Spec - Opera 12.1, Firefox 20+ */
}

jsFiddle demo

Here is an excellent article about Flexbox cross-browser support: Using Flexbox: Mixing Old And New

janfoeh
  • 10,243
  • 2
  • 31
  • 56
  • 2
    +1 To use the simple version, [-prefix-free](http://leaverou.github.io/prefixfree/) could be used. – Oriol Mar 09 '14 at 21:20
5
.container{
height:100px;
width:500px;
border:2px dotted #F00;
border-left:none;
border-right:none;
text-align:center;
}
.container div{
display: inline-block;
border-left: 2px dotted #ccc;
vertical-align: middle;
line-height: 100px;
} 
 .column-left{ float: left; width: 32%;  height:100px;}
.column-right{ float: right; width: 32%;  height:100px; border-right: 2px dotted #ccc;}
.column-center{ display: inline-block; width: 33%; height:100px;}

 <div class="container">
   <div class="column-left">Column left</div>
   <div class="column-center">Column center</div>
   <div class="column-right">Column right</div>
</div> 

See this link http://jsfiddle.net/bipin_kumar/XD8RW/2/

Bipin Kumar Pal
  • 1,009
  • 2
  • 8
  • 16
5

CSS:

.container {
    position: relative;
    width: 500px;
}
.container div {
    height: 300px;
}

.column-left {
    width: 33%;
    left: 0;
    background: #00F;
    position: absolute;
}
.column-center {
    width: 34%;
    background: #933;
    margin-left: 33%;
    position: absolute;
}
.column-right {
    width: 33%;
    right: 0;
    position: absolute;
    background: #999;
}

HTML:

<div class="container">
   <div class="column-center">Column center</div>
   <div class="column-left">Column left</div>
   <div class="column-right">Column right</div>
</div>

Here is the Demo : http://jsfiddle.net/nyitsol/f0dv3q3z/

Rahman
  • 121
  • 1
  • 6
  • 1
    Bonus points for putting the main content DIV first. Better for SEO. – BlueSix Mar 30 '15 at 01:29
  • 1
    I think this answer wins over float when you want a container since floats need clear:both fix (not css-only). When you want full-height column background, it's a clear winner because you can just set column top:0 bottom:0 (and parent height). Relative positioning of nested divs will make you run back to tables. :O) – user982671 May 21 '15 at 04:08
0

CSS:

     .container div{
 width: 33.33%;
 float: left;
 height: 100px ;} 

Clear floats after the columns

 .container:after {
 content: "";
 display: table;
 clear: both;}
Ron Lavit
  • 1,081
  • 10
  • 9