Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vertical alignment with CSS

Yeah, yeah, I know this is yet another question about vertical alignment with CSS and it's been done a million times before. Rest assured that I have come across this problem many times and I've already done the reading about various ways to centre vertically with CSS. I'm asking here because none of those ways do quite what I want to do, and I just want to make sure that my suspicion (that CSS vertical alignment is broken and will not do what I want it to do) is definitely correct.

First up, here's my test case: http://www.game-point.net/misc/testAlign/

Here's the criteria:

  • I want to align the 'centred text' vertically, with respect to the DIV containing the 'TestTestTest...' text.
  • I don't want to specify ANY heights.
  • I want both the 'TestTestTest' and the 'Centred text' DIVs to get their heights dynamically, according to the amount of text they have, and the width limit they have.
  • I don't want to use Javascript.

This seems to be impossible even in CSS3, let alone CSS2. The annoying thing is that I'm almost there; the position:absolute; top:-50%; DIV works to set the top of that DIV to halfway down the container DIV. The problem is that the inner DIV, with style position:relative; top:-50%; doesn't do anything to move the content up by half its height, to centre it fully, because CSS says that an absolutely positioned DIV doesn't have a height and therefore top:-50% is meaningless. As far as I can tell, this is just a fundamental flaw in CSS for no particular reason. An absolutely positioned element does have a height, and I don't know why CSS pretends it doesn't. I just wanted to ask whether anyone had any ideas as to how I could achieve the desired effect, pictured at the bottom, given the criteria I outlined above. Ironically IE6/7/8's 'broken' box model, in quirks mode, gives me this very effect. Shame they're 'fixing' it in IE9 so it won't anymore.

like image 616
Jez Avatar asked Jan 20 '11 10:01

Jez


People also ask

How do I vertically align text in a div using CSS?

The CSS just sizes the div, vertically center aligns the span by setting the div's line-height equal to its height, and makes the span an inline-block with vertical-align: middle. Then it sets the line-height back to normal for the span, so its contents will flow naturally inside the block.


1 Answers

OK, my suspicion was indeed correct and this is not possible (I think it's a flaw in CSS and they should provide a means of vertical alignment within a DIV without specifying inner element heights).

The least bad solution I ended up with was this: specify the height of the 'middle' DIV - that is, the DIV which is displayed using position:absolute and contains the real content. I've added it to the test case page at http://www.game-point.net/misc/testAlign/ under the heading With line-height:100% and hardcoded 'middle' DIV height. This solution means that you must know the height of the content to be vertically centred in advance, which sucks because the browser calculates this and you shouldn't need to specify it, but it's the only way (until CSS gets its act together). I used ems to specify the height too, so that zooming text in and out doesn't ruin the vertical centring. Turns out that for the 2 lines of 'Centred text' I had, this height equates to exactly 2 ems (at least on my machine). If I were to change that content's height, or it were to change dynamically to say 3 lines or 1 line, the parent div's hardcoded em height would also have to change.

So, here's the code I finally ended up with if anyone's interested:

    <div style="border:1px solid black; padding-left:60px; width:250px; position:relative; word-wrap:break-word;">
        TestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTest
        <!-- Unfortunately, must set this DIV's height explicitly or the contained DIV's relative positioning won't work, as this DIV is considered to have NO implicit height -->
        <div style="position:absolute; display:block; top:50%; left:0px; height:2em;">
            <div style="position:relative; top:-50%; background-color:#00aa00; line-height:100%;">
                Centred text<br/>
                Centred text
            </div>
        </div>
    </div>
like image 63
Jez Avatar answered Sep 18 '22 03:09

Jez