Pointless One

Expanding blocks

I’ve found it’s not that easy to build expanding blocks.

The idea is to build a layout with a sidebar that spans from top to bottom at all times. That is, when main content is short it fills whole space at the side of the page. But when the content is longer than viewport can fit sidebar should still expand right to the bottom of the page.

The natural choice for this job is to use absolutely positioned sidebar.

Let’s start with markup:

1
2
3
4
5
6
7<!DOCTYPE html>
<html>
  <body>
    <aside></aside>
    <article></article>
  </body>
</html>

That is a bit simplified but exactly what’s needed to demonstrate the technique.

So the aside is the element we want expanded and article is the element that can span past the viewport and thus expand the page.

There was many attempt to do just that. Many trick for similar but not quiet same techniques can be found across the web. Let’s analyze few of them.

This one is quiet simple. Idea is like this: expand body to the full viewport height and let it expand if there’s more content. But most variants of this are flawed.

Here’s a relevant piece code from Compass framework:

1
2
3html, body {
  height: 100%;
}

The problem with this approach is that body actually never expands past viewport. It just overflows. So content is visible. Background applied to body is visible too just because it’s somewhat special element — its background is actually applied to the whole viewport instead of to the actual element. That said, we can not use it for expanding sidebar because it will never expand to the bottom of the page if we have overflown body.

Misunderstood spec

Another popular approach (as you may see by amount of questions about it on StackOverflow) is min-height property. The thing is that most people don’t know how it really works. I myself had somewhat wrong picture of it in my head until very recently.

The basic gist of all those questions is why doesn’t this code work:

1
2
3html, body {
  min-height: 100%;
}

It seem that’s exactly what we want. Make both html & body minimum of viewport height and expand them if necessary. Alas, that’s not what spec says.

I’ve been lucky to find one interesting thread about just this code. Here’s a short transcript of it but I recommend you to go and read it in whole.

min-height is meaningful only if containing block is explicitly specified.

Now try guess what all those people missed while they were reading spec.

Explicit height

In essence, that’s what we need to make it work. In previous code listing there’s no explicit height on html. That meant that body just doesn’t know 100% of what it has and calculated value for body’s min-height becomes 0. But if we set height on html we’ll get nice expanding body for short content and it will still expand past viewport if it has a lot of content.

Here’s working code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16html {
  height: 100%;
}

body {
  min-height: 100%;
  position: relative;
}

aside {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 200px;
}

Let’s recap every line of the code above.

  • Set explicit height for html so that it span viewport.
  • Set min-height for body do that it cover vewport if it has little content and expand past it if it has a lot of content. Also relative position on body is needed to make it positioned ancestor for aside. Default one is html and we don’t want it because html doesn’t get expanded by content.
  • Set absolute position on aside. Make it stick to top, left and bottom edges of the body and give it some width.

That’s it.

I hope this will help some people to solve their problems faster than it took for me.

November 24th, 2011 01:38