CSS: Vertically align div when no fixed size of the div is known
Asked Answered
D

9

44

How do I align a <div> which contains an image (or flash) vertically with CSS. Height and width are dynamic.

Disservice answered 26/8, 2011 at 14:57 Comment(7)
possible duplicate: #79961Foretopgallant
have you tried anything yet? http://phrogz.net/css/vertical-align/index.htmlStacistacia
yes, I did but they are doing it only for cases when they know height... Also it doesn't work for meDisservice
Are all the heights dynamic and unknown? For the image/flash and for it's container? Must it be absolute positioned or placed near some content, or positioned relative to the viewport?Hummer
I am trying to center content on this page best-games-house.com/play/35/red-riot (for any play full screen on the site)Disservice
@pinouchon The questions are not duplicates. They ask 2 different things, despite the similar wording.Mattern
Vertically align how? Middle align?Nepheline
K
45

This is a pure CSS2 solution for horizontally and vertically centering without known sizes of either container nor child. No hacks are involved. I discovered it for this answer and I also demonstrated it in this answer.

The solution is based on vertical-align: middle in conjunction with line-height: 0, which parent has a fixed line-height.

The HTML:

<span id="center">
    <span id="wrap">
        <img src="http://lorempixum.com/300/250/abstract" alt="" />
    </span>
</span>

And the CSS:

html,
body {
    height: 100%;
    width: 100%;
    padding: 0;
    margin: 0;
    overflow: hidden;
}
#center {
    position: relative;
    display: block;
    top: 50%;
    margin-top: -1000px;
    height: 2000px;
    text-align: center;
    line-height: 2000px;
}    
#wrap {
    line-height: 0;
}
#wrap img {
    vertical-align: middle;
}

Tested on Win7 in IE8, IE9, Opera 11.51, Safari 5.0.5, FF 6.0, Chrome 13.0.

The only caveat is IE7, for which the two innermost elements have to declared at one line, as demonstrated in this fiddle:

<span id="center">
    <span id="wrap"><img src="http://lorempixum.com/300/250/abstract" alt="" /></span>
</span>

Note that the span's are also required for IE7. In every other browser, the span's may be div's.

Knudson answered 1/9, 2011 at 23:21 Comment(8)
Nicely done. This is exactly what many people are looking for, including myself. Definitely the cleanest workaround for people who need to support ie7 [sigh] I edited your fiddle to show another practical example . jsfiddle.net/ryanore/R7szX/2Chenopod
wait how is this an answer.... so basically I get to vertically align, but I lose the ability to scroll my page (overflow: hidden on html,body)Korean
@xckpd7 Of course it doesn't have to be the body; you can use this solution on any container element as shown here.Knudson
Thanks! I made some alterations which (1) make textual content look okay (2) center the content in respect to an element besides the body (3) use classes instead of ids so it's reusable. jsfiddle.net/sparebytes/q9sfQLeoraleos
jsfiddle.net/sparebytes/q9sfQ/1 - Added an animation to show its behaviorLeoraleos
Useless for aligning block elements as pop-ups.Estellaestelle
@Knudson why did you use height and line-height 2000px?Trumpetweed
@Rupam That's an arbitrary value. It would be the "maximum" height a device could display.Knudson
H
12

You can do this by using inline-blocks, one with height: 100% (and same heights for HTML and BODY) and vertical-align: middle.

Example 1: http://jsfiddle.net/kizu/TQX9b/ (a lot of content, so it's full width)

Example 2: http://jsfiddle.net/kizu/TQX9b/2/ (an image with any size)

In this example I use spans, so It would work in IE without hacks, if you'd like to use divs, don't forget to add in Conditional Comments for IE .helper, .content { display: inline; zoom: 1; }, so inline-blocks would work for block elements.

Hummer answered 31/8, 2011 at 11:2 Comment(8)
Quite nice, but when the browser window narrows, the content moves to the "next line". Any idea how to solve that?Knudson
Ah, yeah, since it's inline-blocks, you can use white-space: nowrap to prevent this: jsfiddle.net/kizu/TQX9b/3Hummer
Nice! You can also skip the html and body styles if you use another wrapper with height: 100%; and position: absolute; jsfiddle.net/TQX9b/256 and position: fixed; jsfiddle.net/TQX9b/257, which gives a bit more flexibility on working this into layouts. Tested in FF, IE7-10...Menken
This might actually be the only way to get vertical-align working in a position: absolute element: all my other attempts using table-cell don't pick up the height. Best answer on the page I reckon!Menken
One more note: you can use this with any display:block content in place of the image, and it also all works when nested inside responsive fixed-aspect-ratio elements. Here's an example of both of these that also demonstrates another possible approach to multiple-line wrapped text. Downside: the markup starts to get a bit complicated...Menken
Buddy, you saved my day big time! :) This sounds like the best solution without all those crappy margin hacks.. Great job!Spitz
Hmmm... that helper div seems to be critical. Why is that? PS: This is amazing! So much easier than any other way of doing this.Sicanian
Ahhh... whitespace, damn you. I always forget about inline-block and whitespace.Sicanian
M
9

In addition to the other answers here, the CSS3 flexible box model will, amongst other things, allow you to achieve this.

You only need a single container element. Everything inside it will be laid out according to the flexible box model rules.

<div class="container">
    <img src="/logo.png"/>
</div>

The CSS is pretty simple, actually:

.container { 
    display: box;
    box-orient: horizontal;
    box-pack: center;
    box-align: center;
}

I've omitted vendor-prefixed rules for brevity.

Here's a demo in which the img is always in the centre of the page: http://jsfiddle.net/zn8bm/

Note that Flexbox is a fledgling specification, and is only currently implemented in Safari, Chrome and Firefox 4+.

Mablemabry answered 3/9, 2011 at 8:2 Comment(0)
N
4

I would recommend this solution by Bruno: http://www.brunildo.org/test/img_center.html

However, I ran into a problem w/ his solution w/r/t webkit. It appears that webkit was rendering a small space at the top of the div if the empty span was allowed to be there. So, for my solution I only add the empty span if I detect the browser to be IE (If someone figures out how to get rid of the space, let me know!) So, my solution ends up being:


HTML:

<div class="outerdiv">
    <img src="..." /> 
</div>

CSS:

.outerdiv {
    display: table-cell;
    width: 200px;
    height: 150px;
    text-align: center;
    vertical-align: middle;
}
.ie_vertical_align * {
    vertical-align: middle;
}
.ie_vertical_align span {
    display: inline-block;
    height: 150px;
    width: 0;
}

And if I detect the browser to be IE I add an empty span element before the img tag and a css style so it looks like:

<div class="outerdiv ie_vertical_align">
    <span></span>
    <img src="..." /> 
</div>

Here's a JSFiddle with this code.

Neace answered 30/8, 2011 at 1:22 Comment(2)
I am a bit confused. You're using width: 200px; height: 150px; where these numbers come from? What to do if I don't know the size of the image?Disservice
Well, those numbers are just arbitrary bounds for the outer container. Looking at your site, the numbers would probably be the size of the window, i.e. width: 100%, height: 100%.Neace
S
2

Dušan Janovský, Czech web developer, has published a cross-browser solution for this some time ago. Read http://www.jakpsatweb.cz/css/css-vertical-center-solution.html

Shavonda answered 29/8, 2011 at 15:49 Comment(4)
This either requires IE hacks or multiple nested divs. Which all suck.Mattern
+1 - @Rikudo Sennin, the article was written in 2004 and updated in 2008. I haven't tested it, but I think with IE8/9 those hacks are no longer necessary.Nepheline
Only IE7 and 6 are unfortunately not gone yet, and the OP hasn't stated whether he wanted those or not.Mattern
@Rikudo Sennin The need of nested elements and some CSS hacks for older browsers is, more or less, expected limitation. No simpler code/markup can be used to meet all the OP's requirements. If support for IE6/IE7 is not necessary, the hacks can simply be omitted (just a reminder: it was you who said that the reasonable way should be cross-browser); with the use of conditional comments or so, your CSS can validate. Please think about whether your -1 are legitimate. It's not about that I'm interested in what reputation I have, but you can confuse OP by marking suitable answers as "not useful".Shavonda
M
1

If you don't care about IE7 and below, you don't have to use multiple nested divs. If you have a div that you want to align vertically, that div is within some container (even if the container is your <body>). Therefore, you can specify display: table-cell and vertical-align: middle on the container, and then your div will be vertically centered.

However, if you do care about IE7 and below, you will need an additional container to make it work (yes, via a hack).

Take a look at this fiddle. It displays correctly in IE6-9 and other major browsers. #container2 is present solely for IE7 and below, so if you don't care about them, you can remove it as well as the IE-specific conditional styles.

Minny answered 29/8, 2011 at 20:43 Comment(0)
H
0

Set the image as background of the div and align it center

Hylton answered 1/9, 2011 at 21:49 Comment(0)
F
0

try the 50% padding trick:

<html>

<body style="width:50%; height: 50%;">
<div style="display:block; display:inline-block; layout-grid:line; 
     text-align:center; vertical-align:bottom; 
     padding: 50% 0 50% 0">test</div>
</body>

</html>
Farriery answered 1/9, 2011 at 23:42 Comment(0)
A
-1

This is possible if you know the height of the image or flash object to be centered. You don't need to know the container's height/width, but you do need to know the contained height/width.

It's possible using float, clear and negative margins. Example: www.laurenackley.com homepage.

html

<div id='container'><!-- container can be BODY -->
  <div id='vertical-center'>&nbsp;</div>
  <div id='contained-with-known-height'>
    <p>stuff</p>
  </div>  
</div>

css

#vertical-center{
  height:50%;
  width:1px;
  float:left;
  margin-bottom:-50px;/** 1/2 of inner div's known height **/
}

#contained-with-known-height{
  height:100px;
  clear:left;
  margin:0 auto;/** horizontal center **/
  width:700px;
  text-align:left;
}
#container{/** or body **/
  text-align:center;
  /** width and height unknown **/
}

If you don't know the inner elements width/height. You are out of luck with <div>. BUT -- table cells (<td>) do support vertical-align:middle; If you can't get it done with the div stuff above, go with a table inside the container, and put the div you are centering inside a td with vertical-align middle.

Aspasia answered 29/8, 2011 at 15:50 Comment(7)
Read the question. He doesn't want to align the contents within the div, he wants to align the div itself.Mattern
i did read the question, the "div itself" in this example would be #contained-with-known-height -- assuming that the contents are of known height, and the container is the unknown. the question and comments do not clarify which is the unknown or if its both. which is why i addressed that underneath the example. read my answer.Aspasia
but he stated he doesn't know the width or the height so that solution is practically useless.Mattern
i'd disagree with that. tables serve a purpose, and you don't have to be a purist with divs. how about a table within a div layout?? sounds like that vertical align property might come in handy, no?Aspasia
if he doesn't know the width or the height of the container, this solution is perfect. if he doesn't know the width or height of the contained, then he should use a table, or javascript. as stated above, the unknown was not clarified, even though kizu asked, there was no clarification givenAspasia
tables are there for one thing, to present data that comes in a table, not to layout your code because it's easier. It's not semantic, and it might effect the page's performance and search engine ranking.Mattern
considering he's looking for help on a flash page, i really doubt search engine ranking is relevant, and a single table with 1 cell is hardly going to "effect the page's performance" -- besides, table discussion is hardly relevant anyway, since judging by the example page he gave, he does seem to know the flash object's height/width at page load, and could therefore utilize the 1st CSS soultion i've offered.Aspasia

© 2022 - 2024 — McMap. All rights reserved.