47

I have a (horizontally) centered outer div containing two elements of unknown width:

<div style='width:800px; margin:0 auto'>
  <div style='float:left'>...</div>
  <div style='float:right'>...</div>
</div>

Both floats are top-aligned by default, and are of varying/unknown and different heights. Is there any way to make them vertically centered?

I eventually made the outer div

display: table

and the inner divs

display: table-cell;
vertical-align: middle;
text-align: left/right;

but I'm just curious if there's a way to do this with the floats.

rishat
  • 8,206
  • 4
  • 44
  • 69
Yang
  • 16,037
  • 15
  • 100
  • 142
  • 13
    vertical align in html/css is beyond ugly, and the primary source of my aching desire to slap the entire W3C around with the rotting corpse of IE6, then feed them that corpse. – Marc B Sep 24 '12 at 01:47
  • 2
    @MarcB You aren't alone, but this is what we have to work with.... – Yang Sep 24 '12 at 01:54

3 Answers3

60

You can't do this directly, because floats are aligned to the top:

If there is a line box, the outer top of the floated box is aligned with the top of the current line box.

The exact rules say (emphasis mine):

  1. A floating box's outer top may not be higher than the top of its containing block.
  2. The outer top of a floating box may not be higher than the outer top of any block or floated box generated by an element earlier in the source document.
  3. The outer top of an element's floating box may not be higher than the top of any line-box containing a box generated by an element earlier in the source document.

  1. A floating box must be placed as high as possible.

That said, you can take advantage of rule #4:

  • Place each float inside inline-level elements that establish a new block formatting context /BFC), e.g. display: inline-block.
  • These wrappers will contain the floats because they establish a BFC, and will be one next to the other because they are inline-level.
  • Use vertical-align to align these wrapper vertically.

Be aware that some space might appear between the inline-block wrappers. See How to remove the space between inline-block elements? to fix it.

.float-left {
  float: left;
}

.float-right {
  float: right;
}

#main {
  border: 1px solid blue;
  margin: 0 auto;
  width: 500px;
}

/* Float wrappers */
#main > div {
  display: inline-block;
  vertical-align: middle;
  width: 50%;
}
<div id="main">
  <div>
    <div class="float-left">
      <p>AAA</p>
    </div>
  </div>
  <div>
    <div class="float-right">
      <p>BBB</p>
      <p>BBB</p>
    </div>
  </div>
</div>
Daniel
  • 3,115
  • 5
  • 28
  • 39
Oriol
  • 274,082
  • 63
  • 437
  • 513
  • 9
    this solution work because you put `width:49%;` even without float div it will work. – Hayi May 29 '14 at 08:47
  • I was looking for solution like this for a long time. Thanks! – Mosh Feu Jul 14 '14 at 08:49
  • 10
    I realize this definitely has applications, but it seems kinda cheating to me. the only thing `float: right` does here is to right justify the BBB content. it's the `display: inline-block` and `vertical-align: middle` that actually does the centering. it's not really vertically centering floated content at all. – Simon_Weaver Jul 28 '14 at 03:28
  • 5
    The float shouldn't even be used here. It serves no purpose other than to justify content right like @Simon_Weaver mentioned. Instead it would be better to use `text-align: right` that way the div height will be a part of the flow of the page w/out using a clearfix. – newms87 Dec 22 '14 at 17:04
  • 3
    @newms87 Probably true. But then there won't be any float, so it wouldn't answer the question. Now I think I answer it, even if I cheat a little. – Oriol Dec 22 '14 at 17:16
  • there's nothing with cheating sometimes (or more than sometimes with CSS) ;-) but it's just important the people don't blindly copy code snippets like this without really understanding them - or they'll end up with unexpected and confusing side effects later on – Simon_Weaver Dec 23 '14 at 21:14
  • 1
    It does not work well for another reason -- the content is vertically centered to itself. If you change the height of the container manually you will see both parts are really on the top of the container. – greenoldman Jan 01 '15 at 12:44
  • 1
    @greenoldman If the parent has an explicit height, you can insert an inline-level pseudo-element with `height: 100%` and `vertical-align: middle` ([centering in the unknown](https://css-tricks.com/centering-in-the-unknown/) technique). – Oriol Apr 02 '16 at 18:23
10

Another approach would be to use flex -- it could be a replacement for a float if you have two parts. One (floating) would be of auto size, and the second would grow to occupy entire container. On the cross axis you pick center and voila, you have the effect of the float and centered elements.

Here is beautiful cheatsheet about flex: http://jonibologna.com/flexbox-cheatsheet/

greenoldman
  • 16,895
  • 26
  • 119
  • 185
3

Nope this is when table cells suddenly seem like a great idea. If it is a fixed height you can use line-height.

Trent Stewart
  • 841
  • 1
  • 9
  • 18
  • And if someone is allergic to using tables for layout, css tables can be also used (even though under the hood those are still tables). – jahu Apr 09 '15 at 10:26
  • Table is not so good if you want responsive layout that will naturally flow to show underneath the left element on narrow viewports. – Joel Coehoorn Feb 25 '16 at 22:46
  • @JoelCoehoorn that is completely untrue if you are using css tables. Just change the table display to a block display when needed, within the right css query. – NoobishPro Sep 09 '16 at 15:35
  • @Babydead the whole table... sure. For individual td elements in the same row, it's weird. – Joel Coehoorn Sep 09 '16 at 15:49
  • @JoelCoehoorn of course. Though, the idea of a table is that all of your data is presented in the same way. I can't think of a situation where you would need elements to behave differently from others responsively, when they are aligned the same in non-responsive form. I've built over 250 responsive websites and never came across anything where this was an issue. I'd love to see an example if you have one, though. Quite curious! – NoobishPro Sep 09 '16 at 15:59