How to Create Equal Height Columns in Pure Css

How to create equal height columns in pure CSS

One of the tricky things in modern web design is to create a two (or more) column layout where all the columns are of equal height. I set out on a quest to find a way to do this in pure CSS.

You can easiest accomplish this by using a background image in a wrap-div that holds both of your columns (or the background of the page).

You can also do this by using CSS table cells, but unfortunately the browser support for this is still shady, so it's not a preferred solution. Read on, there is a better way.

I found my inspiration from two pages on the web, although I prefer my solution, since it gives me more freedom to use rounded corners and precise widths or percent layouts, and it is easier to edit, your final layout holding div is not forcing you to do negative number crunching.

== The trick: ==

First you create the background design cols, then you put a full width div that can hold your regular content. The trick is all about floated columns within columns, creating a push effect on all parent columns when the content extends in length, no matter what end column is the longest.

In this example I will use a 2 column grid in a centered wrap-div with rounded corners. I have tried to keep the fluff out for easy copy-paste.

== Step 1 ==

Create your basic web page.

<!DOCTYPE HTML>
<html>
<head>
</head>
<body>
</body>
</html>

== Step 2 ==

Create one floated div inside another floated div. Then apply a negative margin on the inside div to pop it out of its frame visually. I added dotted borders for illustrating purposes. Know that if you float the outside div to the left and give the inside div a negative margin to the left, the inside div will go under the page edge without giving you a scroll bar.

<!DOCTYPE HTML>
<html>
<head>
<style>
#rightsideBG{
float:right;
background:silver;
width:300px;
border: 3px dotted silver; /*temporary css*/
}
#leftsideBG{
float:left;
background:gold;
width:100px;
margin-left:-100px;
border: 3px dotted gold; /*temporary css*/
}
</style>
</head>
<body>
<div id="rightsideBG">
<div id="leftsideBG">
this content obviously only fits the left column for now.
</div>
</div>
</body>
</html>

== Step 3 ==

In the inside div: Create a div without background that has the with of all the columns combined. It will push over the edge of the inside div. I added a dotted border for illustrating purposes.This will be the canvas for your content.

<!DOCTYPE HTML>
<html>
<head>
<style>
#rightsideBG{
float:right;
background:silver;
width:300px;
border: 3px dotted silver; /*temporary css*/
}
#leftsideBG{
float:left;
background:gold;
width:100px;
margin-left:-100px;
border: 3px dotted gold; /*temporary css*/
}
#overbothsides{
float:left;
width:400px;
border: 3px dotted black; /*temporary css*/
}
</style>
</head>
<body>
<div id="rightsideBG">
<div id="leftsideBG">
<div id="overbothsides">
this content spans over both columns now.
</div>
</div>
</div>
</body>
</html>

== Step 4 ==

Add your content. In this example I place two divs that are positioned over the layout. I also took away the dotted borders. Presto, that's it. You can use this code if you like.

<!DOCTYPE HTML>
<html>
<head>
<style>
#rightsideBG{
float:right;
background:silver;
width:300px;
}
#leftsideBG{
float:left;
background:gold;
width:100px;
margin-left:-100px;
}
#overbothsides{
float:left;
width:400px;
}
#leftcol{
float:left;
width:80px;
padding: 10px;
}
#rightcol{
float:left;
width:280px;
padding: 10px;
}
</style>
</head>
<body>
<div id="rightsideBG">
<div id="leftsideBG">
<div id="overbothsides">
<div id="leftcol">left column content</div>
<div id="rightcol">right column content</div>
</div>
</div>
</div>
</body>
</html>

== Step 5 ==

To make it nicer you can centered the whole design in a wrap div and give it rounded corners. The rounded corners wont show in old IE unless you use a special fix for that.

<!DOCTYPE HTML>
<html>
<head>
<style>
#wrap{
position:relative;
width:500px;
margin:20px auto;
-webkit-border-bottom-right-radius: 20px;
-moz-border-radius-bottomright: 20px;
border-bottom-right-radius: 20px;
}
#rightsideBG{
float:right;
background:silver;
width:300px;
}
#leftsideBG{
float:left;
background:gold;
width:100px;
margin-left:-100px;
}
#overbothsides{
float:left;
width:400px;
}
#leftcol{
float:left;
width:80px;
padding: 10px;
}
#rightcol{
float:left;
width:280px;
padding: 10px;
}
</style>
</head>
<body>
<div id="wrap">
<div id="rightsideBG">
<div id="leftsideBG">
<div id="overbothsides">
<div id="leftcol">left column content</div>
<div id="rightcol">right column content</div>
</div>
</div>
</div>
</div>
</body>
</html>

== Inspiration sources ==

  • http://www.pmob.co.uk/pob/equal-columns.htm
  • http://matthewjamestaylor.com/blog/equal-height-columns-2-column.htm

CSS - Equal Height Columns?

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>

Responsive equal height columns in rows with CSS3/HTML5 Only

A solution with flexboxes and media queries:
http://jsfiddle.net/szxmw7ko/4/

#container{
display: flex;

align-items: stretch;
flex-wrap: wrap;
}


@media (max-width: 480px) {
#container div {
max-width: 98%;
}
}
@media (min-width: 480px) and (max-width: 1080px) {
#container div {
max-width: 48%;
}
}
@media (min-width: 1080px) {
#container div {
max-width: 23%;
}
}

align-items: stretch tells to the flex items to fill the avalaible space along the cross axis. This is what allows to have equals height for all items.

flex-wrap: wrap gives the possibility to make a multiline flex flow. Otherwise, all items are jailed into one line.

max-width: XX% by default a block element will fill all avalaible space. Even if items are child of a flex layout, because of the flex-wrap rule which lifts the constraint of piling all the items on one row, they will stretch over the entire width of the container.
So setting a maximum width, which will necessarily raised, gives the control of how many items you want on a row.

@media (max-width: XX%) finally, you have just to adapt the width of an item to define how many columns you want depending on the size of the viewport.

Flexboxes resources:

https://css-tricks.com/snippets/css/a-guide-to-flexbox/

https://css-tricks.com/almanac/properties/f/flex-wrap/

How to set larger column's height equal to small one in pure css?

Here is the trick.

  1. Add position: relative on parent.
  2. Place your dynamic div element (With large height) with position: absolute inside parent.

Following css will be needed for this:

.parent {
position: relative;
}
.large-div {
position: absolute;
overflow: auto;
left: 300px;
bottom: 0;
top: 0;
}

Note: You can change left, bottom and top values as per your needs.

.container {  border: 1px solid #000;  margin-bottom: 20px;  position: relative;  padding: 10px;}
.container div { border: 1px solid #000; padding: 10px; width: 250px;}.container div p { margin: 0;}.large { position: absolute; overflow: auto; bottom: 10px; left: 300px; top: 10px;}
<div class="container">  <div class="small">      Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet...       Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet...   </div>  <div class="large">    <p>      Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet...     </p>  </div></div>
<div class="container"> <div class="small"> Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... </div> <div class="large"> <p> Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet...Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... Lorem ipsum dolor sit amet... </p> </div></div>

How to Make the Content 100% height and equal height columns in this layout?

A solution with full IE6+ support. I'll pull out and explain the relevant bits of code.

Modern support

div.content_columns {
width: 320px;
outline: 1px solid black;
background-color: gold;
text-align: center;
display: table-cell; /* No floats, this instead */
}

So, since modern browsers make this task easy, all we need to do is use display: table-cell to get this to work. It makes the columns equal height, and acts as a table-cell. Easy peasy lemon squeezy.

IE 6 & 7 support

<!--[if lte IE 7]>
<style>
div#content {
overflow: hidden;
}
div.content_columns {
vertical-align: top;
display: inline;
zoom:1;
padding-bottom: 9999px;
margin-bottom: -9999px;
}
</style>
<![endif]-->

Now, for IE 6 and 7 support we're going to use a few tricks. First off, it should be noted that this doesn't have to be done in a conditional comment, but I like it better that way. Cleaner to me. But you can use CSS hacks to get these values to only work in IE.

What we're doing is getting IE 6 & 7 to treat each column as an inline-block element, but since they don't support that (for block level elements at least) we use inline display, and a zoom: 1; fix to trigger IE's hasLayout property. This will treat it like it is an inline-block elmenent. Then, we set them all to be aligned at the top with each other, and use another little trick. We use the padding: 9999px to extend the bottom of the element so far that the other elements are not likely to be longer than it, and we use margin: -9999px; to not change the rendering of the page when we do so. We don't want to extend the page, just the background. 9999px is arbitrary and can be any value as long as it is high enough to be greater than the difference between the longest and shortest columns. And for the final touches, we set overflow: hidden on the container element so that the backgrounds don't extend the page by bleeding out the bottom.

And there you have it, full IE 6+ support for multicolumn fixed width layout using pure CSS 2 (plus MS zoom).

Using CSS to create two equal height layout columns, and inserting three equal height stacked columns inside the right column

Richard Sussans answer is right, but you need to float the columns (both left) in order to make them appear next to eachother. You also need to specify a height for the columns (as well as their parent elements, assuming the height is set in %) for their children to expand vertically. With your markup, the following css should do the trick:

html, body, .container {
height: 100%;
}
.left {
float: left;
height: 100%;
width: 35%;
}

.right {
float: left;
height: 100%;
width: 65%;
}

.col-1-1 {
height: 25%;
}

.col-1-2 {
height: 75%;
}

.col-2-1 {
height: 33%;
}

.col-2-2 {
height: 33%;
}

.col-2-3 {
height: 34%;
}

3 columns layout need to be equal in height

Try the below fiddle.It uses display:table; and display:table-cell;:

CSS

html,body,#container{
width:100%;
height:100%;
}
#container{
display:table;
}
#sidebar,#subsidebar,#content{
border:1px solid black;
display:table-cell;
}
#sidebar{
min-width:40px;
}
#subsidebar{
min-width:200px;
}
#content{
width:100%;
}
  1. Fiddle with all three divs with less contents Fiddle

  2. Fiddle with content div exceeding window height Fiddle

CSS Equal Height Columns - Ugh! Again?

Usually I use pure css/html solution which works in 99% cases:

I have a parent div with background-repeat on 'Y' axe. The general structure is going to be like this :

html:

<div id="container" class="clearfix">

<div class="LeftPane"></div>
<div class="CenterPane"></div>
<div class="RightPane"></div>

</div>

css:

#container{
background:url(imagePath) 0% repeat y;
}

for background image you can apply image for the borders, or everything else what can make users to think that all 3 blocks have the same height



Related Topics



Leave a reply



Submit