A good[ish] website
Web development blog, loads of UI and JavaScript topics
Here’s a selection of pure CSS solution to some common layout issues. All of these work in IE 8.
When flexbox
is supported more widely, it’s gonna be a big mind-shift for developers. But for now, we don't have flexbox
, we have to muggle along with floats and other means available to us.
Almost exceptionally you want the content to be fluid and the sidebar fixed width. Why? Sidebar may have fixed width elements, i.e. Facebook like box, and it's super ugly when navigation list items start to wrap when the sidebar width decreases.
This example is stripped to its most basic form. See 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:
Here’s a same thing on how it might be in the real world.
Let’s use the above mentioned technique as a base here.
We can’t do height: 100%;
. What we can do is: use display: table;
method, but we're not gonna (more on that later on). We'll try to solve this first without the table method. We'll use a small "hack". I posted a little bit about this earlier, also. But I think the following example is more refined.
How does it works:
position: fixed;
to place them under each column.The HTML is the same as for the before mentioned example, 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 complexity quit a bit, this is where flexbox
is going to be really handy! But nonetheless, no images, works down to IE 8 and doesn’t use JavaScrip.
Limitations:
See what I mean (code below the demo):
The HTML is the same as above, only one sidebar more:
<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 start 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.
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.
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:
You can easily add as many columns as needed. Check the code from the demo:
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:
absolute
or fixed
positioned, because ofSee 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.
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
. Atm of writing this, Flexbox has a 77.51% support, yay!
But for now, I guess it’s safe to say:
display: table
method for 100% height columns. It’s simple.Comments would go here, but the commenting system isn’t ready yet, sorry.