Here’s a selection of pure CSS solutions to some common layout issues. All of these work in IE 8.
When flexbox is supported more widely, it’s going to be a big shift for
developers. But for now, we don't have flexbox, so we have to make do with
floats and other means available to us.
Set of requirements
- Have to work in IE 8 (no flexbox or other fancy stuff)
- No background image hacks
- No JavaScript hacks
- Must be fluid
Fixed width sidebar and fluid width content
Almost always, you want the content to be fluid and the sidebar to have a fixed width. Why? The sidebar may have fixed-width elements, such as a Facebook Like box, and it's ugly when navigation list items start to wrap as the sidebar width decreases.
Bare bones example
This example is stripped to its most basic form. See a more styled version below.
Normal, non surprising HTML:
<section class="article-wrap">
<article>
<p>Some content here</p>
</article>
</section>
<aside class="sidebar">
<h2>Sidebar</h2>
<ul>
<li>Navigation</li>
<li>List etc.</li>
</ul>
</aside>And also not so surprising CSS:
// Vars
$sidebar-width: 200px;
// The thing
.article-wrap {
margin-right: $sidebar-width;
}
article,
.sidebar {
float: left;
}
.sidebar {
box-sizing: border-box;
padding-left: 20px;
width: $sidebar-width;
}We’re giving the .article-wrap a right margin of the sidebar width, and that
somehow enables us to float the fixed width sidebar along the main content.
Here’s a demo:
Moar style
Here’s the same thing as it might appear in the real world.
100% height columns using pseudo elements
Let’s use the above-mentioned technique as a base here.
We can’t use height: 100%. We could use the display: table method, but we'll
save that for later. First, we'll try to solve this without tables using a small
"hack." I wrote a
little bit about this earlier,
about it earlier, too. I think the following example is more refined.
How does it work?
- We’ll make one pseudo element for each column,
- and give them an absurdly large height, such as 5000px, bigger than the largest possible screen,
- and use
position: fixed;to place them under each column.
The HTML is the same as in the example mentioned above, and here's the CSS (pay
attention to the :after elements):
// Variables
$sidebarWidth: 220px;
$color-green: Aquamarine;
$globalPadding: 20px;
// The important stuff starts here
.article-wrap {
margin-right: $sidebarWidth;
}
.article-content,
.sidebar {
box-sizing: border-box;
background: $color-green;
float: left;
padding: $globalPadding;
}
.sidebar:after,
.article-content:after {
background: shade($color-green, 3%);
content: ''; // Needed
display: block; // Needed
height: 5000px; // Very large value
position: fixed;
top: 0; // Needed
}
.article-content {
border-color: white;
border-style: solid;
border-width: $globalPadding 0 0 $globalPadding;
width: 100%;
&:after {
left: $globalPadding; // Positioning
width: 100%;
z-index: -1;
}
}
.sidebar,
.sidebar:after {
// These borders are rather important
// Put them in blue or red to see how it works
border-color: white;
border-style: solid;
border-width: $globalPadding $globalPadding 0 $globalPadding;
box-sizing: border-box;
width: $sidebarWidth;
z-index: -1;
}
.sidebar:after {
right: 0;
}Here’s a demo of it.
Argh! We've increased the complexity quite a bit. This is where flexbox is
going to be really handy! Nonetheless, this uses no images, works down to IE 8,
and doesn’t use JavaScript.
Limitations:
- Can’t be displayed against multi color background e.g. an image.
- Tad complex.
- The pseudo elements can't be animated.
The holy grail layout with the same technique
See what I mean (code below the demo):
The HTML is the same as above, with one more sidebar:
<aside class="sidebar sidebar--left">
<h2>Sidebar</h2>
<ul>
<li>Lorem.</li>
<li>Natus.</li>
</ul>
</aside>
<section class="article-wrap">
<article class="article-content">
<h1>Header</h1>
<p>Content here...</p>
</article>
</section>
<aside class="sidebar sidebar--right">
<h2>Sidebar</h2>
<ul>
<li>Lorem.</li>
<li>Natus.</li>
</ul>
</aside>And the CSS is thus:
// Variables
$sidebarWidth: 220px;
$color-green: Aquamarine;
$globalPadding: 20px;
// The actual thing starts here
.article-wrap {
margin: 0 $sidebarWidth;
}
.article-content,
.sidebar {
box-sizing: border-box;
background: $color-green;
float: left;
padding: $globalPadding;
}
.sidebar:after,
.article-content:after {
background: shade($color-green, 3%);
content: ''; // Needed
display: block; // Needed
height: 5000px; // Very large value
position: fixed;
top: 0; // Needed
}
.article-content {
border-top: $globalPadding solid white;
width: 100%;
&:after {
left: $sidebarWidth;
width: 100%;
z-index: -10; // Below sidebars
}
}
.sidebar,
.sidebar:after {
// These borders are rather important
// Put them in blue or red to see how it works
border-color: white;
border-style: solid;
border-width: $globalPadding $globalPadding 0 $globalPadding;
box-sizing: border-box;
width: $sidebarWidth;
z-index: -1;
}
.sidebar--right:after {
right: 0;
}
.sidebar--left:after {
left: 0;
}That’s a lot of even more complicated code. But again, more elegant and easy than using background images I think.
The display: table; thing supersedes this by being simpler.
display: table; method
Tables love being 100% height! But doing layouts with tables is like sucking Satans butt hole, and you’ll be shunned from the web dev community for eternity. But, using CSS tables is just fine.
Two column layout
We'll use the following HTML:
<div class="container">
<div class="row">
<div class="center">
<p>Some content here...</p>
</div>
<div class="right">
<ul>
<li>Sidebar</li>
<li>Deleniti</li>
<li>...</li>
</ul>
</div>
</div>
</div>And CSS:
.container {
display: table; // Needed
height: 100%; // Needed
}
.row {
display: table-row; // Needed
}
.right,
.center {
display: table-cell; // Needed
padding: 20px;
}
.right {
width: 160px;
background: Aquamarine;
}
.center {
background: Pink;
border-right: solid 20px white;
}Much prettier :) See a demo:
The holy grail layout
You can easily add as many columns as needed. Check the code from the demo:
One more thing: a more specific layout scenario
This is oddly specific, but whatever. It uses a simple hack that may come handy on other places also.
I needed to do something like this:
- The sidebar needed to have a height, i.e. not be
absoluteorfixedpositioned, because of - if the sidebar has more content than the other columns, it should push the pink container box taller and
- if it had less content, the sidebar should still be 100% height and
- the sidebar should be fixed width, and the columns should be fluid
See the fullscreen pen and change your window size and you'll get the point. Also, see a real world example.
It doesn’t use pseudo elements. Here's the essentials of the code:
section {
// Overflow needs to be hidden in the wrapping element
overflow: hidden;
}
.sidebar {
// Sidebar is floated, not positioned absolutely
float: right;
// This trick makes the sidebar 100% in height
margin-bottom: -5000px;
padding-bottom: 5000px;
// Define width in normal fashion
width: $sidebar-width;
}Check the full code from the demo.
Conclusion
If we can code CSS layouts that are not using images or JS, and are very semantic in all possible ways; is then automatically a good thing? Some of these techniques are quit complex, you can bend over backwards under the protective umbrella of semantics and pseudo elements, and still end up with an increasingly complex codebase. If you can do something, still doesn't mean you should.
This site →
Solved by Flexbox, shows
examples of common layout problems that are solved really beautifully and
elegantly with flexbox. At the moment of writing this, Flexbox has a 77.51%
support.

But for now, I guess it’s safe to say:
- Use the
display: tablemethod for 100% height columns. It’s simple. - Sit home and wait for flexbox.