81

In CSS, I can do something like this:

enter image description here

But I've no idea how to change that to something like:

enter image description here


Is this possible with CSS?

If yes, how can I do it without explicitly specifying the height (let the content grow)?

AJPerez
  • 3,435
  • 10
  • 61
  • 91
Alix Axel
  • 151,645
  • 95
  • 393
  • 500

11 Answers11

96

Grid

Nowadays, I prefer grid because it allows keeping all layout declarations on parent and gives you equal width columns by default:

.row {
  display: grid;
  grid-auto-flow: column;
  gap: 5%;
}

.col {
  border: solid;
}
<div class="row">
  <div class="col">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</div>
  <div class="col">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam.</div>
  <div class="col">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.</div>
</div>

Flexbox

Use Flexbox if you want children to control column width:

.row {
  display: flex;
  justify-content: space-between;
}

.col {
  flex-basis: 30%;
  box-sizing: border-box;
  border: solid;
}
<div class="row">
  <div class="col">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</div>
  <div class="col">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam.</div>
  <div class="col">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.</div>
</div>
Pavlo
  • 43,301
  • 14
  • 77
  • 113
  • 2
    +1 in addition, check this useful link with a comprehensive list of flexbox features http://css-tricks.com/snippets/css/a-guide-to-flexbox/ – Tivie Feb 25 '14 at 07:47
  • 1
    @Towfiq flexbox does not, table layout does. It's all in the answer. – Pavlo May 26 '14 at 10:45
  • @RokoC.Buljan Nope. At least not in Safari 9. Open up the demo and try this: if I set the width to be 100% the third column become larger than the first two. – Pavlo Oct 28 '15 at 17:23
  • @Pavlo I've seen the issue in Safari(5). Incredible. Makes totally no logical sense why would the second cell be so narrow... Who's building those browsers? Removed my previous comment to prevent noise. Thanks for the response. Up+d. – Roko C. Buljan Oct 28 '15 at 21:58
  • @Pavlo incredible... also setting `table-layout:fixed;` on table does **not** work in Safari(5.1.7). – Roko C. Buljan Oct 28 '15 at 22:04
  • @RokoC.Buljan FYI Safari 5 is *ancient* and shares only 0.18% of the market: http://caniuse.com/usage-table – Pavlo Oct 29 '15 at 11:58
  • 1
    @Pavlo the point was that it seems they did not moved much far since ;) – Roko C. Buljan Oct 29 '15 at 12:43
  • I just wanted to add that the flexbox solution works because `align-items` is set on `stretch` by default, changing that property changes the vertical layout. – Pascal Goldbach Apr 23 '21 at 15:19
16

Give overflow: hidden to the container and large (and equal) negative margin and positive padding to columns. Note that this method has some problems, e.g. anchor links won't work within your layout.

Markup

<div class="container">
    <div class="column"></div>
    <div class="column"></div>
    <div class="column"></div>
</div>

CSS

.container {
    overflow: hidden;
}

.column {
    float: left;    
    margin-bottom: -10000px;
    padding-bottom: 10000px;
}

The Result

CSS equal height columns

Dan Abramov
  • 264,556
  • 84
  • 409
  • 511
  • 2
    I just tested and it seems you can! Pretty cool, the only thing negative I can point out is the blue background, I think I need glasses... The text is just so fuzzy. – Alix Axel Jan 20 '12 at 20:53
  • 2
    @Alix: If blue background is horrible for a code sample, you can read full Lorem ipsum [here](http://en.wikisource.org/wiki/Lorem_ipsum) :-) – Dan Abramov Jan 20 '12 at 21:29
  • that doesn't make them equal height. that only makes the BACKGROUND to look like equal height, but the containers aren't.. – vsync Dec 26 '12 at 21:48
  • @vsync: True, but it's often the desired result and is much less hurdle than other methods. – Dan Abramov Dec 26 '12 at 22:16
  • I used to use this technique since 2006 but nowadays layouts require more than just make the background stretch all the way down..I was hoping to find an answer to the OP's question but it seems this issue it very complex if you want to support old IE.. – vsync Dec 27 '12 at 01:59
  • Well, it is always possible that [you're solving the wrong problem](http://www.amazon.com/Are-Your-Lights-Figure-Problem/dp/0932633161/). – Dan Abramov Dec 27 '12 at 02:23
  • 2
    I would really like to know when actually being equal height is the right problem to be solving, because if there was equal content there would be equal height, and putting stuff at the bottom will work with relative positioning to the container element. This answer is what I was looking for when I cam here, so cheers. – Adam Tolley Mar 08 '13 at 20:44
15

Yes.

Here is the completed CSS the article uses. It is well worth reading the entire article, as the author goes step by step into what you need to make this work.

#container3 {
    float:left;
    width:100%;
    background:green;
    overflow:hidden;
    position:relative;
}
#container2 {
    float:left;
    width:100%;
    background:yellow;
    position:relative;
    right:30%;
}
#container1 {
    float:left;
    width:100%;
    background:red;
    position:relative;
    right:40%;
}
#col1 {
    float:left;
    width:26%;
    position:relative;
    left:72%;
    overflow:hidden;
}
#col2 {
    float:left;
    width:36%;
    position:relative;
    left:76%;
    overflow:hidden;
}
#col3 {
    float:left;
    width:26%;
    position:relative;
    left:80%;
    overflow:hidden;
}

This isn't the only method for doing it, but this is probably the most elegant method I've encountered.

There is another site that is done completely in this manner, viewing the source will allow you to see how they did it.

George Stocker
  • 57,289
  • 29
  • 176
  • 237
Joel Etherton
  • 37,325
  • 10
  • 89
  • 104
  • Nice, found it! I think you mean http://matthewjamestaylor.com/blog/equal-height-columns-cross-browser-css-no-hacks – Alix Axel Jan 22 '10 at 03:51
  • none of this makes the height of the columns the same, it's just an Illusion. what i really want to know if how to make them the same height without JS. – vsync Dec 26 '12 at 21:49
  • 1
    @vsync: If you want to make them the same height, make them the same height. For most layouts the "illusion" is sufficient and acceptable. Html/Css is a limited markup language so there is only so much it can do before you have to rely on another tool. – Joel Etherton Dec 26 '12 at 22:29
  • 1
    have you heard about css? "flex-box" or even, display:table..only it's hard to keep support for older IE. but there are ways, always – vsync Dec 27 '12 at 16:21
  • this answer is being discussed at meta: http://meta.stackoverflow.com/questions/275584/isnt-this-answer-link-only – gnat Oct 29 '14 at 12:27
6

You can do this easily with the following JavaScript:

$(window).load(function() {
    var els = $('div.left, div.middle, div.right');
    els.height(getTallestHeight(els));
}); 

function getTallestHeight(elements) {
    var tallest = 0, height;

    for(i; i < elements.length; i++) {
        height = $(elements[i]).height();

        if(height > tallest) 
            tallest = height;
    }

    return tallest;
};
Alex
  • 34,899
  • 5
  • 77
  • 90
4

You could use CSS tables, like so:

<style type='text/css">
    .container { display: table; }
    .container .row { display: table-row; }
    .container .row .panel { display: table-cell; }
</style>
<div class="container">
    <div class="row">
        <div class="panel">...text...</div>
        <div class="panel">...text...</div>
        <div class="panel">...text...</div>
    </div>
</div>
K Prime
  • 5,809
  • 1
  • 25
  • 19
  • 2
    Not supported by a some browsers, though. – Joel Coehoorn Jan 22 '10 at 03:45
  • Seems promising, **/me tries it out**. – Alix Axel Jan 22 '10 at 03:46
  • @Joel Coehoorn: Do you know which ones? It would be useful to know. – Alix Axel Jan 22 '10 at 03:46
  • +1, I would prefer this approach over the one provided by Joel. But it seems to have problems with some browsers (still **I would like to know which ones**). – Alix Axel Jan 22 '10 at 03:54
  • 3
    @Alix - I know for certain that IE6/7 doesn't support `display:table` - others have issues if you don't use explicit table, row, and cells (as in, using anonymous elements (http://www.digital-web.com/articles/everything_you_know_about_CSS_Is_wrong/), etc.) – K Prime Jan 22 '10 at 06:10
  • 2
    @Alix - some reference on cross-browser issues: http://www.quirksmode.org/css/display.html#table – K Prime Jan 22 '10 at 06:12
1

Modern way to do it: CSS Grid.

HTML:

<div class="container">
  <div class="element">{...}</div>
  <div class="element">{...}</div>
  <div class="element">{...}</div>
</div>

CSS:

.container {
  display: grid;
  grid-gap: 10px;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}

.element {
  border: 2px solid #000;
}

Live example is here.

repeat(auto-fit, minmax(200px, 1fr)); part sets columns width. Every column takes 1 fraction of available space, but can't go less than 200px. Instead of shrinking below 200px it wraps below, so it's even responsive. You can also have any number of columns, not just 3. They'll all fit nicely.

If you need exactly 3 columns, use grid-template-columns: repeat(3, 1fr); instead. You can still have more elements, they will wrap, be responsive, but always be placed in 3 column layout.

More on CSS Grid on MDN or css-tricks.

It's clean, readable, maintainable, flexible and also that simple to use!

kamyl
  • 5,938
  • 4
  • 23
  • 29
0

You ca try it... it works for me and all browser compatible...

<div id="main" style="width:800px; display:table">
<div id="left" style="width:300px; border:1px solid #666; display:table-cell;"></div>
<div id="right" style="width:500px; border:1px solid #666; display:table-cell;"></div>
</div>
Sumon
  • 21
  • 1
0

Another option is to use a framework that has this solved. Bootstrap currently doesn't have an equal height option but Foundation by Zurb does, and you can see how it works here: http://foundation.zurb.com/sites/docs/v/5.5.3/components/equalizer.html

Here's an example of how you'd use it:

<div class="row" data-equalizer>
    <div class="large-6 columns panel" data-equalizer-watch>
    </div>
    <div class="large-6 columns panel" data-equalizer-watch>
    </div>
</div>

Basically they use javascript to check for the tallest element and make the others the same height.

So, if you want just css this would add more code, but if you are already using a framework then they have already solved this.

Happy coding.

Maximus
  • 1,417
  • 15
  • 19
0

Use Flexbox to create equal height columns

* {box-sizing: border-box;}

/* Style Row */
.row {
  display: -webkit-flex;
  -webkit-flex-wrap: wrap;
  display: flex;
  flex-wrap: wrap;
}

/* Make the columns stack on top of each other */
.row > .column {
  width: 100%;
  padding-right: 15px;
  padding-left: 15px;
}

/* When Screen width is 400px or more make the columns stack next to each other*/
@media screen and (min-width: 400px) {
  .row > .column {    
    flex: 0 0 33.3333%;
    max-width: 33.3333%;
  }
}
<div class="row">
  <!-- First Column -->
  <div class="column" style="background-color: #dc3545;">
    <h2>Column 1</h2>
    <p>Some Text...</p>
    <p>Some Text...</p>
  </div>
  <!-- Second Column -->
  <div class="column" style="background-color: #ffc107;">
    <h2>Column 2</h2>
    <p>Some Text...</p>
    <p>Some Text...</p>
    <p>Some Text...</p>    
    <p>Some Text...</p>
    <p>Some Text...</p>
    <p>Some Text...</p>
    <p>Some Text...</p>
  </div>
  <!-- Third Column -->
  <div class="column" style="background-color: #007eff;">
    <h2>Column 3</h2>
    <p>Some Text...</p>
    <p>Some Text...</p>
    <p>Some Text...</p>    
  </div>
</div>
Vishal
  • 268
  • 4
  • 3
-1

Responsive answer:

CSS flexbox is cute, but cutting out IE9 users today is a little insane. On our properties as of Aug 1 2015:

3% IE9
2% IE8

Cutting those out is showing 5% a broken page? Crazy.

Using a media query the way Bootstrap does goes back to IE8 as does display: table/table-cell. So:

http://jsfiddle.net/b9chris/bu6Lejw6/

HTML

<div class=box>
    <div class="col col1">Col 1<br/>Col 1</div>
    <div class="col col2">Col 2</div>
</div>

CSS

body {
    font: 10pt Verdana;
    padding: 0;
    margin: 0;
}

div.col {
    padding: 10px;
}

div.col1 {
    background: #8ff;
}
div.col2 {
    background: #8f8;
}

@media (min-width: 400px) {
    div.box {
        display: table;
        width: 100%;
    }
    div.col {
        display: table-cell;
        width: 50%;
    }
}

I used 400px as the switch between columns and a vertical layout in this case, because jsfiddle panes trend pretty small. Mess with the size of that window and you'll see the columns nicely rearrange themselves, including stretching to full height when they need to be columns so their background colors don't get cut off part-way down the page. No crazy padding/margin hacks that crash into later tags on the page, and no tossing of 5% of your visitors to the wolves.

Chris Moschini
  • 36,764
  • 19
  • 160
  • 190
-1

Here is an example I just wrote in SASS with changeable column-gap and column amount (variables):

CSS:

.fauxer * {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box; }

.fauxer {
  overflow: hidden; }

.fauxer > div {
  display: table;
  border-spacing: 20px;
  margin: -20px auto -20px -20px;
  width: -webkit-calc(100% + 40px);
  width: -moz-calc(100% + 40px);
  width: calc(100% + 40px); }

.fauxer > div > div {
  display: table-row; }

.fauxer > div > div > div {
  display: table-cell;
  width: 20%;
  padding: 20px;
  border: thin solid #000; }
<div class="fauxer">
                <div>
                    <div>
                        <div>
                            Lorem column 1
                        </div>
                        <div>
                            Lorem ipsum column 2 dolor sit amet, consetetur sadipscing elitr, 
                            sed diam nonumy eirmod tempor invidunt ut labore et 
                            dolore magna aliquyam erat, sed diam voluptua.
                        </div>
                        <div>
                            Lorem column 3
                        </div>
                        <div>
                            Lorem column 4
                        </div>
                        <div>
                            Lorem column 5
                        </div>
                    </div>
                </div>
            </div>

Note: I only found the time to test it in some new browsers. Please test it well before you will use it :)

The editable example in SCSS you can get here: JSfiddle