CSS Roadblock

Jan 16 2012 Published by under JavaScript, Uncategorized

Send to Kindle

Generally I like to use my blog for dispensing knowledge, advice, opinions, thoughts, musings, and of course, FACTS. But occasionally I get stuck on a point and all my research leads me to a dead end, and I’ll write a post that asks for help. I figure the answers just might help someone else down the line anyway, so it’s not purely selfish.

OK, so I’ve learned to stop worrying and love JavaScript. HTML I can tolerate. But CSS is gonna kick my ass.

Here’s what I want:

Two divs, floated side by side, varying amounts of text in them, but that text needs to be bottom aligned. Here’s what I came up with after a few Google searches:

<style type="text/css">
	.header { 
		position: relative; 
		float: left;
		width: 200px;
		margin: 10px;
		height: 100px;
		background-color: #ffcccc;
	}
	.header-content { 
		position: absolute; 
		bottom: 0; 
		left: 0; 
		width: 100%;
	}
</style>
<div class="header">
	<div class="header-content">Some content that will wrap lorem ipsum and all that crap just to make a long lon long div</div>
</div>
<div class="header">
	<div class="header-content">other stuff</div>
</div>

And here’s what it looks like:

But I have one more need. I’m hard coding the height of the header class to be 100px. I want it to be the exact height of the tallest content. So that it looks like this:

The thing is, that because the header-content div is absolute positioned, then the header div’s height will be 0 unless explicitly set. So the bottom of header is the same as the top of header and header-content goes off the top of the page.

The only way I’ve managed to do this is via JavaScript something like this:

var contents = document.getElementsByClassName( "header-content" );
var h = 0;
for( var i = 0; i < contents.length; i++ ) {
	var content = contents[ i ];
	h = Math.max( h, content.offsetHeight );
}
var headers = document.getElementsByClassName( "header" );
for( var i = 0; i < headers.length; i++ ) {
	var header = headers[ i ];
	header.style.height = h + "px";
}

This loops through the header-content divs, finding the tallest one. Then with that value, sets the height of both header divs. Works just fine.

In Flash, I'd have no problem using code for layout. But I'd love to know if there is some pure CSS way to accomplish this.

Send to Kindle

20 responses so far. Comments will be closed after post is one year old.

  • Jon B says:

    Look up ‘display:table’ and ‘display:table-cell’ and then use ‘vertical-align:bottom’ maybe…

  • keith says:

    thanks. I did try that without much success. Also heard it’s not very cross-browser friendly.

  • It’s not very flexible but what do you think about Matthew James Taylor’s take on Equal Height Columns (2008)?

    Chris Coyer also talked about this issue a couple times

    • keith says:

      That’s great. Not sure if any of those will work, but lots of concepts to look over there. Thanks.

  • Jon B says:

    This also sort of works, although the columns won’t be the same height.

    http://jsfiddle.net/aytvB/7/

  • Jon says:

    Remember the tag? Vastly underrated, and often better than traversing the document from JavaScript. And at least it doesn’t need CSS-hack-spaghetti.

    • keith says:

      I’m guessing that was the table tag. Didn’t make it through in the comment. Believe me, I considered it.

  • You probably want inline-block for this. It doesn’t work properly in IE6/7 by default, but there is a very simple CSS hack to fix it in those browsers. See this Fiddle for an example: http://jsfiddle.net/G8c8F/4/

  • I had a similar issue trying to bottom align semi complex (though not unreasonable) columns on an old blog layout. After a lot of research I found a few articles saying basically what I wanted wasn’t possible with CSS. I ended up using tables and it took about 10 minutes.

    My takeaway from many similar struggles is don’t fight css/html/declarativeUI or JS libraries. If they don’t easily do something you want, the sane option is to just want something else. They are written as multiple (often conflicting) algorithms as the starting point, so the end result is then by definition the desired behaviour. To ‘get around’ limitations requires reverse engineering the algorithms, and leaves you very vulnerable to changes in the future.

    I always tell clients upfront that I will let them know when the spec doesn’t fit within limitations of standard implementations. They can then change the spec or add time/budget – usually they choose the former.

    I do find it frustrating.

  • Cédric says:

    Hi Keith,

    I somehow managed to work something around that without javascript, in brief :
    1 – the two header-content are moved in a single header div
    2 – header-content are set as inline block with a bottom align
    3 – the colored box for each content is done with the header-content’s before selector and, as only the header div is set with position:relative, the before box will refer to it for height and top.

    For the details :
    http://jsfiddle.net/mznCq/

  • You probably want display: inline-block. It doesn’t work properly in IE 6/7 by default, but you can fix that with a simple CSS hack. I created a JS Fiddle example of how to do it with this CSS style: http://jsfiddle.net/G8c8F/

  • Øyvind Nordhagen says:

    Here, my friend, you have hit upon the holy grail of HTML/CSS. From what I read you have also hit the same rock bottom of the probem as every one else. You will ne in denial for a day or two and then you will resort to JS, absolute positioning, display:table-cell or simply . There is no safe, cross-browser solution to this problem (yet) and you will probanly be forced to live with that. Sorry :-)

    • keith says:

      Yeah. I really feel like saying how much I think CSS sucks, compared to any other layout system I’ve used. But I keep thinking it’s just because I don’t know it enough. But learning more seems to be enforcing my gut feeling. Unfortunately, I think JS takes a lot of the bad rap for the DOM and CSS problems. Not that JS is perfect, mind you.

  • Cay says:

    As Jon said, I would try with something like this (it should be quite cross-browser):
    http://jsfiddle.net/s9vTA/
    Notice that the space between the two columns is a white border. If you need it transparent I think you would need to resort to a few little hacks (inner container, or maybe an extra separation row).

  • Thomas says:

    There will be a nice way of doing it with the flexible box layout model. It already works with current Webkit and Mozilla browsers:
    http://jsfiddle.net/meyertee/8aGhX/

    Unfortunately the specification for this seems to be in flux and display:box will be replaced with display:flex-box.. so not quite cross-browser, but eventually there will be a standard way.

    More details: https://developer.mozilla.org/en/CSS/box-orient
    Specs: http://www.w3.org/TR/css3-flexbox/

  • Tim says:

    Slam it in a table. It will work cross browser and you won’t have to deal with CSS hacks to get it all to work. It will also take minutes vs hours.

  • Thomas says:

    There will be a nice way of doing it with the flexible box layout model. It already works with current Webkit and Mozilla browsers:
    http://jsfiddle.net/meyertee/8aGhX/

    Unfortunately the specification for this seems to be in flux and display:box will be replaced with display:flex-box.. so not quite cross-browser, but eventually there will be a standard way. So don’t give up on CSS just yet ;)

    More details: https://developer.mozilla.org/en/CSS/box-orient
    Specs: http://www.w3.org/TR/css3-flexbox/

  • longoria says:

    Have you checked out the FlexBox CSS stuff? – http://www.w3.org/TR/css3-flexbox/

  • longoria says:

    There is a JavaScript library to provide flexbox support for legacy browsers:
    https://github.com/doctyper/flexie

    And some lazy CSS classes to mimic hbox, vbox, and flex attributes:
    https://github.com/longoria/boxie.css

  • René says:

    Is there any particular reason you chosse to have separate .header DIVs? From CSS´ perspective they’re hanging in thin air and there’s nothing a loose element can inherit from let alone lean onto or align with.
    The fiddle provided by Jon B as well as using display:table for the .header and display:table-cell for the inner DIVs ought to work, unless you added some other CSS stuff that could break it.
    Note that margins won’t work with table-cell, but by essentially turning them into a table’ish thing you can apply (any?) of the table specific properties to them; just like vertical-align.
    Just give it another try and make sure there’s no conflicting rule elsewhere.

    R.