This markup creates a container that sits on top and to the right side of my template’s splash area. Its designed to allow the site owner to place a headline and some text as an intro to the site visitor…
<div class="featured-home">
<span class="featured-title">Home Header widget Title</span>
<div class="textwidget"><p>The text here comes from the "Home Header Area" widget.</p>
</div>
I’ve fixed the height of “featured-home” to 275 pixels and I would like to have the child elements centered vertically within that space.
The only caveat is that I want a fixed vertical distance (say 15px) between the “featured-title” element and the “textwidget” element.
So what I essentially want is to have an equal amount of top and bottom padding in the container, with 15px separating the two elements and centered vertically.
Here’s the css I’ve used in the past for vertical centering, but its not working in this case, the content is always at the top of the featured-home container…
Can I do this without altering or adding elements to the markup?
Paul might be able to offer advice on this one but have you tried setting a line-height? Only if you have text you want to align. Otherwise try setting the margin-top value.
Hi AtSea, yes but I’m unable to get line-height to do the do in this case.
I’m hoping Paul has some ideas, he always does.
Logically, I would expect the display:table-cell combined with the vertical-align to work, but something is just not right and it has no apparent effect.
Interestingly, even though I have explicitly set the height and even max-height to 275px with !important triggers, applying margin-top:50% or padding-top:50% centers the elements within the entire browser viewport, not the fixed height container.
Thanks Paul, I’m ok with allowing the older browsers to have default alignment. However, since I’m absolutely positioning my container, I think I’m missing the benefits of your solution.
I changed that and put it in flow with [float:right; margin-top:-300px;] and that gets my container div where I want it, but the child elements are top aligned in that case.
Can the elements be vertically centered in an absolutely positioned element? I had to take it out of the flow in this case to get the x/y positioning exactly where I wanted.
If you want to support ie6 and 7 then you have to add a load of markup like this:
Paul, I know your aware of the inline-block trick with the empty element for a height reference.
By setting set a class on elements with inline-block the IE6/7 tripswitch becomes very simple with one rule.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Test Page</title>
<style type="text/css">
body {
margin:0;
padding:0;
font: 100%/1.3 arial,helvetica,sans-serif;
background:#FFF;
}
.featured-home {
width:400px;
height:275px;
float:right;
margin:0 20px 0 0;
/*position:absolute;
top:-326px;
right:0;*/
font-size:1.2em;
color:#000;
/*text-align:right;*/
background:#CDF;
}
.in-blk {
width:398px;
display:inline-block;
vertical-align: middle;
text-align:right;
background:lime;
}
.featured-home h3 {
margin:0;
font:normal 1em/1.2 arial;
background:yellow;
}
.featured-home p {
margin:10px 0 0;
}
span.in-blk {
height:100%;
width:2px;
background:#000;
}
* html .in-blk {display:inline;}/*IE6*/
*+html .in-blk {display:inline;}/*IE7*/
</style>
</head>
<body>
<div class="featured-home">
<div class="in-blk">
<h3>Home Header widget Title</h3>
<p>The text here comes from the "Home Header Area" widget.</p>
</div><span class="in-blk"><!--v-align--></span>
</div>
</body>
</html>
I did actually give an example of that method in my first post except that I only gave it to IE6 and 7 so as not to confuse the original technique in case support wasn’t needed for ie6 and 7 as I remember Scott didn’t seem too worried about them last time.
To be honest I prefer the display:table-cell method as it is much more robust and doesn’t need the extra vertical height element and the whole width can be used. Therefore my preference would be to use the display:table for those that can use it and send ie6 and 7 the separate routines. (I also hate using an inline element next to block elements which is why in my example I used a p with a class hence the need for display:inline and zoom instead of inline-block and inline).
Of course the inline-block method means that the parent could be absolutely positioned without using a wrapper unlike the table-cell method so there are some advantages to it.
As an aside I note that your example is not working in Chrome or Firefox and the width needs to be reduced to make it all fit.
Right, I just noticed that he was not concerned about IE6/7
To be honest I prefer the display:table-cell method as it is much more robust and doesn’t need the extra vertical height element and the whole width can be used. Therefore my preference would be to use the display:table for those that can use it and send ie6 and 7 the separate routines.
Yes I can see the advantages to that, the only downside with that when adding IE6/7 into the mix is the extra load of CSS. It’s either that or an empty element in the markup when using inline-block.
(I also hate using an inline element next to block elements which is why in my example I used a p with a class hence the need for display:inline and zoom instead of inline-block and inline).
Lol, yes I should have known better than to do that. Especially after I just got through making that point myself in a recent thread.
That’s easily fixed by just making the empty element a div and slipping another class on it to distinguish it from the other inline-block div.
Of course the inline-block method means that the parent could be absolutely positioned without using a wrapper unlike the table-cell method so there are some advantages to it.
Yes, I was going to point that out as well. Either method costs us an extra div. You’ll notice that I slipped the h3 and the p tag in the .in-blk div so their parent does the v-align.
As an aside I note that your example is not working in Chrome or Firefox and the width needs to be reduced to make it all fit.
Or you could use the white-space hack that you came up with
Right, I had taken care of that in the markup.
Here is a leanercleaned up version that addresses all of the above
(of course FF2 would need some help if that needed support)
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Test Page</title>
<style type="text/css">
.featured-home {
width:400px;
height:275px;
position:absolute;
top:20px;right:20px;
background:#CDF;
}
.in-blk {
width:100%;
display:inline-block;
vertical-align: middle;
text-align:right;
font-size:1.2em;
background:lime;
}
.featured-home h3 {
margin:0;
font:normal 1em/1.2 arial;
background:yellow;
}
.featured-home p {
margin:10px 0 0;
}
.v-align {
height:100%;
width:0;
}
* html .in-blk {display:inline;}/*IE6*/
*+html .in-blk {display:inline;}/*IE7*/
</style>
</head>
<body>
<div class="featured-home">
<div class="in-blk">
<h3>Home Header widget Title</h3>
<p>The text here comes from the "Home Header Area" widget.</p>
</div><div class="in-blk v-align"></div>
</div>
</body>
</html>
OK, I don’t think its worth changing the markup just for this one alignment issue. I might just deal with the alignment not being as flexible as I’d like.
How about css generated content? What are your thoughts on adding the wrapper div as generated content?
It won’t work. Generated content only applies to the :before and :after pseudo-elements. They are not capable of wrapping around existing elements on the page. The only thing that would do is create an element before or after all the other elements of your featured-home div.
lol - you’re going to think I’m being awkward now but the above runs into the same issue that I noticed in my example in that it doesn’t actually work in IE8.
IE8 needs a width on the extra div or it won’t vertically center. Of course adding a width bumps the next element down to the next line so you have to reduce the other one’s width.
I’m sure there’s a combination in there that will works for all without reducing the width but I couldn’t find one . You may have an extra trick up your sleeve though.
The nearest I can get without changing the mark up is this which isn’t exactly vertically centered but divides the element into two vertical cells of 50% and then aligns one to the bottom and one to the top so that they meet in the middle.
It will be vertically centered if the text is of equal length or at least occupies the same number of lines.
Are you testing with IE8 on Windows 7? If so it may be an OS related difference we’re seeing.
It works without a width for me in IE8 on XP. Though I have always found it strange that it worked without a width on all the browsers I have tested with.
I found the problem and it was that I re-formatted your page (as I always do that when I copy code into my editor so that it looks the way I like it :)).
It doesn’t work in this format:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Test Page</title>
<style type="text/css">
.featured-home {
width:400px;
height:275px;
position:absolute;
top:20px;
right:20px;
background:#CDF;
}
.in-blk {
width:100%;
display:inline-block;
vertical-align: middle;
text-align:right;
font-size:1.2em;
background:lime;
}
.featured-home h3 {
margin:0;
font:normal 1em/1.2 arial;
background:yellow;
}
.featured-home p {
margin:10px 0 0;
}
.v-align {
height:100%;
width:0;
}
* html .in-blk {
display:inline;
}/*IE6*/
*+html .in-blk {
display:inline;
}/*IE7*/
</style>
</head>
<body>
<div class="featured-home">
<div class="in-blk">
<h3>Home Header widget Title</h3>
<p>The text here comes from the "Home Header Area" widget.</p>
</div>
<div class="in-blk v-align"></div>
</div>
</body>
</html>
The above suffers from the white space bug we mentioned earlier but closing the html like you have done fixes it - but is easy to break as I just found out.
</div><div class="in-blk v-align"></div>
I tried the negative margins fixes as that was my first thought also and they don’t fix it I’m afraid. I just tried again with your code in case I made a mistake and still no joy.
The above suffers from the white space bug we mentioned earlier but closing the html lie you have done fixes it - but is easy to break as I just found out.
Okay, so it does work with width:0; on the empty div. You were just getting text nodes while reformatting it.
Leaving IE6 out in the cold for now, here’s one that works without setting any classes on the empty div with protection against white-space nodes.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Fixed Height V-Align</title>
<style type="text/css">
.outer {
width:400px;
height:275px;
position:absolute;
top:20px;right:20px;
background:#AAA;
}
.outer div {
display:inline-block;
vertical-align: middle;
}
*+html .outer div {display:inline;}/*IE7*/
.outer div+div { /*v-align reference*/
width:1px; height:100%;
margin-left:-999em;/*kill white-space nodes and hide offscreen*/
}
.inner {
width:100%;
font:1.2em/1.2 arial;
text-align:right;
background:#EEF;
}
.inner h3,.inner p {
margin:0;
padding:2px 4px;
font-size:1em;
}
.inner p {background:#CDF;}
</style>
</head>
<body>
<div class="outer">
<div class="inner">
<h3>Heading Text</h3>
<p>Paragraph text that relates to topic heading defined above.</p>
</div>
<div></div>
</div>
</body>
</html>
Hold the presses, it looks like Chrome is having trouble with it now.
It’s that same Webkit bug again.
Let me see if I can find a fix for that.
EDIT:
Okay it looks like I can set the width back to “0” on the sandbag and then set a negative right margin on the inner div to soak up white-space nodes.
That gets it working in Webkit and the others (except IE6 which I noted above) as far as I can see for now.
.outer div {
display:inline-block;
vertical-align: middle;
[COLOR=Blue]margin:0 -2em 0 0;[/COLOR]/*soak up white-space nodes*/
}
*+html .outer div {display:inline;}/*IE7*/
.outer div+div { /*v-align reference*/
[COLOR=Blue]width:0;[/COLOR]
height:100%;
}
So if you plug those rules into their respective places on the code above it should be working now.
Still kinda strange how it works with width:0 though. I would think that the 100% height would collapse without a width.