In CSS, I can do something like this:
But I've no idea how to change that to something like:
Is this possible with CSS?
If yes, how can I do it without explicitly specifying the height (let the content grow)?
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>
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
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.
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;
};
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>
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!
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>
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.
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>
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.
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
Related
I'm not a designer and haven't done anything much with CSS in quite a while. This is the first time I've had to use flexbox layout, and I'm a little lost.
This is the HTML structure I have to work with... I can't change this.
<section class="infobox">
<main class="popup">
<aside class="thumb"><img class="mini" src="image.jpg" /></aside>
<article class="info">
<h1>Heading Text</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Quis ipsum suspendisse ultrices gravida. Risus commodo viverra maecenas accumsan lacus vel facilisis.</p>
</article>
<footer class="infofoot">
<a target="windowid" href="http://example.com">A single line of linked text.</a>
</footer>
</main>
</section>
This is the CSS I currently have:
<style type="text/css">
/* <![CDATA[ */
a {
text-decoration: none;
}
img.mini {
width: 20vw;
height: 20vh;
float:left;
padding: 20px 10px 10px 10px;
}
.infobox {
display: flex;
flex-direction: column;
}
.popup {
width: 50vw;
flex-direction: row;
}
This is how it renders...
I need the footer section to fall below the image in the aside. I've tried various things with align-self and flex-grow (among others) but have not happened upon a working solution. How do I accomplish this?
One approach, as always when dealing with float, is to simply assign clear: both to the element you wish to appear on a new line following the floated element:
a {
text-decoration: none;
}
img.mini {
width: 20vw;
height: 20vh;
float: left;
padding: 20px 10px 10px 10px;
}
.infobox {
display: flex;
flex-direction: column;
}
.popup {
width: 50vw;
flex-direction: row;
}
/* forces the selected element(s) to a new line: */
.infofoot {
clear: both;
}
<section class="infobox">
<main class="popup">
<aside class="thumb"><img class="mini" src="image.jpg" /></aside>
<article class="info">
<h1>Heading Text</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Quis ipsum suspendisse ultrices gravida. Risus commodo viverra maecenas accumsan lacus vel facilisis.</p>
</article>
<footer class="infofoot">
<a target="windowid" href="http://example.com">A single line of linked text.</a>
</footer>
</main>
</section>
JS Fiddle demo.
An alternative is to use CSS grid – instead of flex-box – layout:
a {
text-decoration: none;
}
img.mini {
width: 20vw;
height: 20vh;
float: left;
padding: 20px 10px 10px 10px;
}
.popup {
width: 50vw;
/* using grid layout: */
display: grid;
/* setting a gap between adjacent elements of 0.5em (purely aesthetic,
adjust to your preferences: */
gap: 0.5em;
/* naming the three grid areas; here we define two rows (each quoted
string defines one row) each with two columns, each with named areas.
The first row has an area named 'thumb' and another named 'article',
the second has one area that spans both columns, named 'footer'.
We use the order of the elements in the DOM to place the various
elements appropriately: */
grid-template-areas: "thumb article" "footer footer";
}
.infofoot {
/* in order to see that the .infofoot spans both columns: */
background-color: azure;
/* specifying that the .infofoot element should span two
columns: */
grid-column: span 2;
}
<section class="infobox">
<main class="popup">
<aside class="thumb">
<img class="mini" src="image.jpg">
</aside>
<article class="info">
<h1>Heading Text</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Quis ipsum suspendisse ultrices gravida. Risus commodo viverra maecenas accumsan lacus vel facilisis.</p>
</article>
<footer class="infofoot">
<a target="windowid" href="http://example.com">A single line of linked text.</a>
</footer>
</main>
</section>
JS Fiddle demo.
Further, as a somewhat delayed response, it's entirely possible to use CSS flexbox to lay out these cards, though I prefer to use CSS grid as you're creating a two-dimensional layout (and flex, while responsive and with many use-cases, is typically thought of as a one-dimensional layout). However:
/* a standard, mini, naive reset to reduce browser-default
styles from creating cross-browser layout issues: */
*,
::before,
::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.infobox {
display: flex;
flex-direction: column;
}
.popup {
display: flex;
flex-direction: row;
/* specifying that the content can wrap to new rows: */
flex-wrap: wrap;
/* assigning a gap between adjacent elements: */
gap: 0.5em;
width: 50vw;
}
.thumb {
/* setting the base-size of the .thumb element to 30% of
its parent's width: */
flex-basis: 30%;
}
/* setting the base-size of the element to 65% of its
parent's width: */
.info {
flex-basis: 65%;
}
.mini {
/* width: 100% causes the <img> element to occupy the full width
of its parent; and object-fit: cover causes the <img> to fully
cover the space available, scaling if necessary but maintaining
its aspect-ratio: */
object-fit: cover;
width: 100%;
}
.infofoot {
background-color: azure;
/* forces the size of the element to occupy 100% of the width of
its parent, taking the 'full' row: */
flex-basis: 100%;
}
<section class="infobox">
<main class="popup">
<aside class="thumb">
<img class="mini" src="https://www.fillmurray.com/200/300">
</aside>
<article class="info">
<h1>Heading Text</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Quis ipsum suspendisse ultrices gravida. Risus commodo viverra maecenas accumsan lacus vel facilisis.</p>
</article>
<footer class="infofoot">
<a target="windowid" href="http://example.com">A single line of linked text.</a>
</footer>
</main>
</section>
References:
clear.
display.
flex-basis.
flex-grow.
flex-shrink.
flex-wrap.
float.
gap.
grid-column.
grid-template-areas.
object-fit.
<section class="infobox">
<main class="popup">//make it flex column
<div >//make it flex row
<aside class="thumb"><img class="mini" src="image.jpg" /></aside>
<article class="info">
<h1>Heading Text</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Quis ipsum suspendisse
ultrices gravida. Risus commodo viverra maecenas accumsan lacus vel
facilisis.</p>
</article>
</div>
<footer class="infofoot">
<a target="windowid" href="http://example.com">A single line of linked text.</a>
</footer>
</main>
</section>
I am trying to develop a single-screen, pure css website interface that allows a User to click through a series of choices. The goal is to allow the User to self-select their way to a desired action (signup, contact form, load a new page, etc).
My approach was to put several absolutely positioned divs in a relatively positioned wrapper, then use a combination of z-index and :target to achieve the desired result.
The issue I am encountering is the transition between slides (each slide displays two choices the User can make). In the first test (A/B Slide Choice Test (Working) the transtion works by sliding divs from left to right. The two subsequent slides are absoultely positioned to right:100%, then right:0 using :target
#target2:target {
right: 0;
}
#target3:target {
right: 0;
}
#target1, #target2, #target3 {
transition: all 0.6s ease-out;
}
#target1 {
z-index:1;
}
#target2 {
z-index:2;
right: 100%;
}
#target3 {
z-index:3;
right: 100%;
}
The result is working as desired - when clicking on choice 1A or 1B, the transitions are occuring and the correct slides are displayed.
But in the second test, A/B Slide Choice Test (not working), the two subsequent divs, Slide 2 and 3, are absoultely positioned to left:100%, then left:0 using :target
#target2:target {
left: 0;
}
#target3:target {
left: 0;
}
#target1, #target2, #target3 {
transition: all 0.6s ease-out;
}
#target1 {
z-index:1;
}
#target2 {
z-index:2;
left: 100%;
}
#target3 {
z-index:3;
left: 100%;
}
Several things are happening:
Clicking on decision 1A:
Result: Slide 3 (#target3) moves into position without transition.
Expected: Slide 2 (#target2) slides in from the right side of the screen.
As near as I can tell, clicking on 1A is activating the wrong target and/or Slide 2 and 3 are both moving to the left (with Slide 2 being pushed all the way offscreen to the left). Then if you click choice 3A the transition works properly (slides back to the right, revealing Slide 1 again)
Clicking on decision 1B:
Result: Slide 3 (#target3) suddenly appears, and moves to offscreen (to the left) with transition, revealing Slide 2 (#target2).
Expected: Slide 3 (#target3) slides in from the right side of the screen.
Then if you click choice 2B the transion works properly (the sldie goes back to the right, revealing Slide 1 again)
I have tried this absolutely positioned transition using using top:100% and top:0, and bottom:100% and bottom:0
The same issue occurs: Using absolutely positioned 'top' values works, while 'bottom' values creates the undesired behavior.
I want to be able to use transtions in any direction, the ultimate goal being that 'direction' will be a configurable backend parameter in a Joomla module. The module is actually written, installed, and working properly except for this transition issue.
I don't know if :target is somehow breaking the desired behavior, or if I'm doing something wrong with absolute positioned CSS values, or both. Or if my (limited) understanding of Flexbox is messing things up.
I am completely open to using a different method of getting the desired behavior shown in the working version (ideally using CSS only) if that's what is required.
But so far in my internet searches I haven't found any code snippets or examples of the one-screen A/B interface I am trying to accomplish.
I am extremely grateful for any assistance!
EDIT: I've been playing around with values to see if I can get a better understanding of what's going on.
#target2:target {
left: 100%;
}
#target3:target {
left: 100%;
}
#target1, #target2, #target3 {
transition: all 0.6s ease-out;
}
#target1 {
z-index:1;
}
#target2 {
z-index:2;
left: 100%;
}
#target3 {
z-index:3;
left: 100%;
}
In theory (as far as my understanding goes), with the CSS above, there should be no change as both values are left:100%
But in practice clicking on decision 1A or 1B causes #target2 and #target3 to move onscreen (though without transition).
Then I added multiple slides into the relatively positioned wrapping div, and what I've found is that all the slide IDs are affected (#target2, #target3, #target4, #target5 etc.).
Again my understanding is that clicking on the href="#target2" should only affect #target2:target, but it is affecting all other slide IDs, making me think that position:absolute and :target are conflicting somehow.
(bangs head on desk)
The issue that you are running into is indeed that the position:absolute and the targeting are conflicting. The way they are conflicting is because the browser tries to scroll to the right location because you are using anchor tags. Then the position starts to change which causes the element you want to show up to disappear.
So, your two choices to get it to really work how you want are to prevent the browser from scrolling. e.g. Abandon the anchor tags to prevent the browser from scrolling instead of you (maybe a sprinkle of JS instead?).
Or you can go all in on the scrolling and leave out the change in location from the absolute positioning.
CSS only solution
Since you asked for even alternatives (preferably without JS), here's using CSS scroll snapping (CSS Tricks) to do the heavy lifting of the transitions. All your markup is the same.
Main pieces of this solution that are of note:
the html element is the one that has the scrollbar in this case, so it needs the scroll-snap-type and behavior
html {
scroll-snap-type: x mandatory;
scroll-behavior: smooth;
}
All of the targets need to be snapping points:
#target1,
#target2,
#target3 {
scroll-snap-align: center;
}
Those were the main two things to get this working at a base level, but there were a couple other interesting additions to get it to look a bit nicer.
We need to increase the targets to a larger z-index when they are targeted so they'll always be on top.
#target2:target,
#target3:target {
z-index: 5;
}
Target 1 needs to be fixed position when it's not targeted so it looks like it stays in one location as it's being scrolled off of (unfortunately I couldn't come up with a good way to get the reverse done).
#target1:not(:target) {
position: fixed;
left: 0;
}
There needs to be a transition on the z-index specifically in this case so target2 doesn't immediately go under target 3 when it is transitioning off screen
section:not(:target) {
transition: z-index 2s ease-out;
}
body,
html {
width: 100%;
height: 100%;
margin: 0;
font-family: sans-serif;
}
html {
scroll-snap-type: x mandatory;
scroll-behavior: smooth;
overflow: hidden;
}
.mainwrap {
height: 100%;
position: relative;
}
.flexwrap {
position: relative;
display: flex;
height: 100%;
}
.contentwrap {
display: flex;
flex: 1;
}
figure {
display: flex;
flex-direction: column;
align-items: center;
flex: 1;
padding: 0;
margin: 0;
}
.flexcolumn {
display: flex;
flex-direction: column;
height: 100%;
}
.leftbox,
.rightbox {
padding: 5%;
}
.leftbox {
color: #fff;
}
.rightbox {
color: #574a46;
}
#media screen and (min-width: 993px) {
.contentwrap {
flex-direction: row;
}
figure {
flex-direction: column;
}
.flexcolumn {
justify-content: center;
}
}
#media screen and (max-width: 992px) {
.contentwrap {
flex-direction: column;
}
figure {
flex-direction: row;
}
.flexcolumn {
justify-content: center;
}
}
.drab {
background-color: #676c27;
}
.orange {
background-color: #ff9600;
}
.yellow {
background-color: #ffcc00;
}
.burgundy {
background-color: #83240f;
}
.lime {
background-color: #cccc33;
}
.olive {
background-color: #333300;
}
.navy {
background-color: #000033;
}
a {
color: #ffffff;
}
#target2:target,
#target3:target {
z-index: 5;
}
#target1:not(:target) {
position: fixed;
left: 0;
}
section:not(:target) {
transition: z-index 2s ease-out;
}
#target1,
#target2,
#target3 {
scroll-snap-align: center;
}
#target1 {
z-index: 1;
}
#target2 {
z-index: 2;
left: 100%;
}
#target3 {
z-index: 3;
left: 100%;
}
.start {
position: absolute;
width: 100%;
height: 100%;
}
.reset {
position: absolute;
height: 100%;
width: 100%;
overflow: hidden;
/* left: 0%; */
z-index: -1;
/* transform: translateX(100%); */
}
<div id="decisionTree" class="mainwrap">
<section class="start" id="target1">
<div class="flexwrap">
<div class="contentwrap">
<figure id="tree1" class="fadebox leftbox navy">
<div class="flexcolumn">
<h3>I am Decision #1a</h3>
<figcaption>
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.
</figcaption>
</div>
CLICK
</figure>
<figure id="tree2" class="fadebox rightbox yellow">
<div class="flexcolumn">
<h3>I am Decision #1b</h3>
<figcaption>
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.
</figcaption>
</div>
CLICK
</figure>
</div>
</div>
</section>
<section class="reset" id="target2">
<div class="flexwrap">
<div class="contentwrap">
<figure id="tree1" class="fadebox leftbox olive">
<div class="flexcolumn">
<h3>I am Decision #2a</h3>
<figcaption>
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.
</figcaption>
</div>
CLICK
</figure>
<figure id="tree2" class="fadebox rightbox orange">
<div class="flexcolumn">
<h3>I am Decision #2b</h3>
<figcaption>
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.
</figcaption>
</div>
CLICK
</figure>
</div>
</div>
</section>
<section class="reset" id="target3">
<div class="flexwrap">
<div class="contentwrap">
<figure id="tree1" class="fadebox leftbox burgundy">
<div class="flexcolumn">
<h3>I am Decision #3a</h3>
<figcaption>
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.
</figcaption>
</div>
CLICK
</figure>
<figure id="tree2" class="fadebox rightbox lime">
<div class="flexcolumn">
<h3>I am Decision #3b</h3>
<figcaption>
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.
</figcaption>
</div>
CLICK
</figure>
</div>
</div>
</section>
</div>
Important to note, you won't get the effect of this from the minimized result because it seems to require at least a certain height to work. So you'll have to run the snippet then click full screen.
JavaScript based solution
As was mentioned a JS solution is fine as long as it is explained well / simple enough:
In this case, the JS is as follows. The actual pieces are commented to make them easier to follow. In general, instead of using :target, this solution works by toggling the .selected class in elements instead. The main benefit of this is to get rid of the browser's scrolling events that anchor tags provide.
function clickHandler(target){
// Get the element that should be selected
const elem = document.querySelector(target);
// There were no elements to be selected
if(!elem) return;
// Get the old selected element (if any)
const prevElem = document.querySelector('.selected');
if(prevElem){
// If there was a previously selected element, it isn't anymore
prevElem.classList.remove('selected');
}
// Make the new element selected
elem.classList.add('selected');
}
The CSS changes are also minor:
instead of using :target, we use .selected
#target2.selected,
#target3.selected {
left: 0;
}
The html changes I made were changing the a tags to buttons (to be more semantically correct) and gave them an onClick event handler:
<button onClick="clickHandler('#target3')">CLICK</button>
For the sake of display within stack overflow due to it providing such a short and squat window by default, I set min-height to be 390px (so there is a base size to avoid the weirdnesses from having everything based on % when they don't fit)
html {
min-height: 390px;
overflow-x: hidden;
overflow-y: auto;
}
function clickHandler(target) {
// Get the element that should be selected
const elem = document.querySelector(target);
// There were no elements to be selected
if (!elem) return;
// Get the old selected element (if any)
const prevElem = document.querySelector('.selected');
if (prevElem) {
// If there was a previously selected element, it isn't anymore
prevElem.classList.remove('selected');
}
// Make the new element selected
elem.classList.add('selected');
}
html {
min-height: 390px;
overflow-x: hidden;
overflow-y: auto;
}
body,
html {
width: 100%;
height: 100%;
margin: 0;
font-family: sans-serif;
}
.mainwrap {
height: 100%;
position: relative;
}
.flexwrap {
position: relative;
display: flex;
height: 100%;
}
.contentwrap {
display: flex;
flex: 1;
}
figure {
display: flex;
flex-direction: column;
align-items: center;
flex: 1;
padding: 0;
margin: 0;
}
.flexcolumn {
display: flex;
flex-direction: column;
height: 100%;
}
.leftbox,
.rightbox {
padding: 5%;
}
.leftbox {
color: #fff;
}
.rightbox {
color: #574a46;
}
#media screen and (min-width: 993px) {
.contentwrap {
flex-direction: row;
}
figure {
flex-direction: column;
}
.flexcolumn {
justify-content: center;
}
}
#media screen and (max-width: 992px) {
.contentwrap {
flex-direction: column;
}
figure {
flex-direction: row;
}
.flexcolumn {
justify-content: center;
}
}
.drab {
background-color: #676c27;
}
.orange {
background-color: #ff9600;
}
.yellow {
background-color: #ffcc00;
}
.burgundy {
background-color: #83240f;
}
.lime {
background-color: #cccc33;
}
.olive {
background-color: #333300;
}
.navy {
background-color: #000033;
}
a {
color: #ffffff;
}
#target2.selected,
#target3.selected {
left: 0;
}
#target1,
#target2,
#target3 {
transition: all 0.6s ease-out;
}
#target1 {
z-index: 1;
}
#target2 {
z-index: 2;
left: 100%;
}
#target3 {
z-index: 3;
left: 100%;
}
.start {
position: absolute;
width: 100%;
height: 100%;
}
.reset {
position: absolute;
height: 100%;
width: 100%;
overflow: hidden;
}
<div id="decisionTree" class="mainwrap">
<section class="start" id="target1">
<div class="flexwrap">
<div class="contentwrap">
<figure id="tree1" class="fadebox leftbox navy">
<div class="flexcolumn">
<h3>I am Decision #1a</h3>
<figcaption>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.</figcaption>
</div>
<button onClick="clickHandler('#target2')">CLICK</button>
</figure>
<figure id="tree2" class="fadebox rightbox yellow">
<div class="flexcolumn">
<h3>I am Decision #1b</h3>
<figcaption>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.</figcaption>
</div>
<button onClick="clickHandler('#target3')">CLICK</button>
</figure>
</div>
</div>
</section>
<section class="reset" id="target2">
<div class="flexwrap">
<div class="contentwrap">
<figure id="tree1" class="fadebox leftbox olive">
<div class="flexcolumn">
<h3>I am Decision #2a</h3>
<figcaption>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.</figcaption>
</div>
<button onClick="clickHandler('#target1')">CLICK</button>
</figure>
<figure id="tree2" class="fadebox rightbox orange">
<div class="flexcolumn">
<h3>I am Decision #2b</h3>
<figcaption>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.</figcaption>
</div>
<button onClick="clickHandler('#target1')">CLICK</button>
</figure>
</div>
</div>
</section>
<section class="reset" id="target3">
<div class="flexwrap">
<div class="contentwrap">
<figure id="tree1" class="fadebox leftbox burgundy">
<div class="flexcolumn">
<h3>I am Decision #3a</h3>
<figcaption>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.</figcaption>
</div>
<button onClick="clickHandler('#target1')">CLICK</button>
</figure>
<figure id="tree2" class="fadebox rightbox lime">
<div class="flexcolumn">
<h3>I am Decision #3b</h3>
<figcaption>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.</figcaption>
</div>
<button onClick="clickHandler('#target1')">CLICK</button>
</figure>
</div>
</div>
</section>
</div>
hey man it will be much easier if you made a codepen or a jsfiddle. Its a pretty long explanation and pretty hard to follow through. sorry i dont have the solution but if you make a jsfiddle i will help you with what i can.
This question already has answers here:
Remove space (gaps) between multiple lines of flex items when they wrap
(1 answer)
How does flex-wrap work with align-self, align-items and align-content?
(2 answers)
Closed 5 years ago.
I'm trying to create a header with two columns that will fill to the parent container's height. I'm using display:flex for a responsive layout. When I set the header to have a fixed height, the two other sub-divs have a gap between them and the header.
div#container {
padding:20px;
background:#F1F1F1;
display: flex;
flex-flow:row wrap;
height:540px;
}
.header{width:100%; height:40px; background:#ccc;}
.content {
width:150px;
background:#ddd;
padding:10px;
margin-left: 10px;
}
Fiddle
EDIT
The duplicate question is a nice description of the flex properties, but I'm not seeing an example like this addressed in it.
If the height:40px is removed from the header, the header div will stretch down to the other divs. When the header height is specified, a gap exists.
align-content default value is stretch. Change that to align-content: start; and it should be okay.
.content-wrapper{
display: flex;
flex: 1;
}
div#container {
padding: 20px;
background: #F1F1F1;
display: flex;
flex-flow: column wrap;
align-content: start;
height: 540px;
border: 1px solid red;
box-sizing: border-box;
}
.header{width:100%; height:40px; background:#ccc;}
.content {
width:150px;
background:#ddd;
padding:10px;
margin-left: 10px;
}
<div id="container">
<div class="header">
HEADER
</div>
<div class="content-wrapper">
<div class="content">
<h1>Title 1</h1>
<div>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>
<div class="content">
<h1>Title 2</h1>
<div>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>
</div>
</div>
In CSS, I can do something like this:
But I've no idea how to change that to something like:
Is this possible with CSS?
If yes, how can I do it without explicitly specifying the height (let the content grow)?
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>
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
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.
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;
};
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>
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!
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>
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.
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>
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.
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
In CSS, I can do something like this:
But I've no idea how to change that to something like:
Is this possible with CSS?
If yes, how can I do it without explicitly specifying the height (let the content grow)?
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>
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
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.
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;
};
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>
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!
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>
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.
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>
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.
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