Log in

View Full Version : Resolved vertical align center with fluid height



james438
08-17-2011, 04:47 AM
This may not be possible with css.

We have the following:


<div style="height:1000px;">
<div style="float:left;width:100%;"><img src="test.jpg"></div>
<div style="float:left;width:100%;padding-top:50%;">test</div>
</div>

As the window size of the browser is altered the image will change size, but the overall height will remain an absolute 1000px. Since the image is changing height and the height of the child divs are not set the top div with image will take up a greater or lesser percentage of the parent div with the lower div with text taking up the remainder of the parent div height.

What I am trying to get is the text to be vertically aligned even as the height of the divs change with the resizing of the browser window.

Is this even possible? I have not seen it anywhere nor have I had any luck in creating this.

Deadweight
08-17-2011, 05:40 AM
Do you have an example somewhere? Like a website or some sort?

james438
08-17-2011, 06:01 AM
I do have a website or three, but I have not seen this anywhere hence the last sentence of my first post ;). Still, it seems that this should be possible even if it is not. Javascript might be able to do this, but I'd rather it be done with css. Javascript is fine though I guess.

For fun here is some better sample code:


<div style="height:700px;width:20%;border: #000000 solid 2px;background-color:green;">
<div style="float:left;width:100%;background-color:red;"><img src="/images/alita1.jpg" style="opacity:0.0;filter:alpha(opacity=0);width:100%;"></div>
<div style="position:relative;float:left;width:100%;">I would like this to be vertically centered.</div>
</div>
With a test page (http://www.animeviews.com/test/sample/test22.php). Try resizing the browser window to see what I am trying to work with.

Deadweight
08-17-2011, 06:46 AM
Yeah i know but its kinda hard to compare something to something that no one has seen =P
I mean y dont you show us something that is close to it

james438
08-17-2011, 07:42 AM
See above.

I updated the code as well as the sample page (http://www.animeviews.com/test/sample/test22.php) and the following comes close:


<div style="height:700px;width:20%;border: #000000 solid 2px;
background-color:green;">
<div style="float:left;width:100%;background-color:red;">
<img src="http://www.animeviews.com/images/alita1.jpg"
style="opacity:0.0;filter:alpha(opacity=0);width:100%;"></div>
<div style="float:left;width:100%;padding:25% 0%;vertical-align:middle;">
Not centered yet.</div>
</div>

jscheuer1
08-17-2011, 08:08 AM
The vertical-align property is for inline content (things like img, input, span, and a tags in their native display mode) and table cells (td & th tags) only.

It varies as to its meaning depending upon whether it's an inline element or a table cell. With inline elements, it's simply a relativistic property. It sets the vertical position of the element in relation to othet inline elements, if any on the same line. If there are none, it has no effect, and it has no effect upon the elements postion within a block level container like a div, or upon a block level element's content. It's this last that you seem to want.

You could do this with a table because with a table cell it actually aligns the vertical position of the content within the table cell. And, in theory at least, you could set the div's display property to table-cell. But I don't think that's very cross browser. And even if it is, probably has other consequences (in at least some browsers) for the layout that you may not want.

You can always forget about vertical-align and use positioning instead. If you know the height of the content you want to vertically center, you may set it to position absolute within a relative positioned container and give it a top property of 50% and a negative margin-top property of half its height.

If you don't know the height, that could be where javascript would come in. It can calculate that for you.

But the simplest method would be to use a table.

james438
08-17-2011, 03:17 PM
If I remove vertical align I get the same result. What is interesting is that setting the padding to 25% appears to set the padding for the text to 25% of the current height (or width?) of the image, so when the window is resized with the mouse by clicking the border of the window and moving it left and right across the screen so as to resize the window the padding is adjusted appropriately. This is good for square images and less so for rectangular images.

I hope the above makes sense.

Using the vertical align in my title is just a way to describe what I am trying to accomplish. I have tried manipulating the actual property of vertical-align by setting line-height to a percentage of the image height, but without much luck. I have also tried setting the the display to table cell, etc, but without much luck.

All in all, it sounds like I need to go with javascript here.

I'm gonna put this aside for now. Thanks for your help.

jscheuer1
08-17-2011, 04:39 PM
This is actually one of the cases where I'd make an exception for the general rule of thumb to avoid tables:


<!DOCTYPE html>
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style type="text/css">
table, td {
height: 400px;
}
td {
vertical-align: middle;
border: 1px solid #000;
}
</style>
</head>
<body>
<table>
<tr>
<td><div>I'm in the middle vertically</div></td>
</tr>
</table>

</body>
</html>

james438
08-17-2011, 10:29 PM
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<table style="width:20%;border: #000000 solid 2px;height: 700px;">

<tr style="width:100%;"><td style="vertical-align:top;background-color:green;">
<img src="/images/alita1.jpg" style="opacity:0.9;filter:alpha(opacity=0);width:100%;"></td></tr>

<tr style="width:100%;"><td style="clear:both;
vertical-align: top;border: 1px solid #000;background-color:red;">
I'm in the middle vertically</td></tr>

</table></body></html>

I am using Opera. It has been a while since I have used HTML. I altered the code you posted to reflect the unknown height of the two cells. The overall height of the table IS known though. For some reason when setting the height of the table the first cell uses all of the height.

jscheuer1
08-18-2011, 01:22 AM
You're not really using vertical-align there. If those were divisions, they would align top, that's what divisions do. So this no longer qualifies as an exception to the best practices rule of avoiding tables when possible.

I played around with it, and - best I can figure for what I think you're after:


<!DOCTYPE html>
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<div style="width: 20%; border: #000 solid 2px; height: 700px;">
<div style="height: 50%; background-color: green;">
<img src="/images/alita1.jpg" style="display: block; opacity: 0.9; filter: alpha(opacity=90); max-width: 100%; max-height: 100%;" alt="">
</div>
<div style="height: 50%; border: 1px solid #000; background-color: red;">
I'm in the middle vertically
</div>
</div>
</body>
</html>

Notes:

The equivalent for opacity 0.9 in alpha opacity is 90, not 0. Using zero for either makes things invisible.

You had a clear in there. That's only for after floats, but there were no floats.

Setting the image's width to 100% is OK, as long as the proportional ratio of the height isn't greater than 350px (half the height (50%) of the outer container). Using max-width and height ensures the image will fit in the layout. But it might not always fill the width of its immediate parent. You could make its margin: 0 auto; to at least center it in those cases.

Making the image display: block; will save on potential problems - like images in their native inline display have added space at the bottom in many DOCTYPES, and don't accept margin, padding, perhaps other styles as expected in some browsers. Since you want it all the way across its parent, the line break this causes is meaningless - it would be there anyway, does nothing if there's no other content in its parent, and acts the same if the display were inline even if there were.

james438
08-18-2011, 03:54 AM
Thanks for explaining. I was trying to make the image invisible. I am not so sure I am explaining what I am looking for well enough though. Looking at my first post with a few small changes we have:


<div style="height:1000px;width20%;">
<div style="float:left;width:100%;"><img src="test.jpg"></div>
<div style="float:left;width:100%;padding-top:50%;">test</div>
</div>
Here the parent div has an overall height of 1000px. The child(?) div contains an image with a width that extends to 20% of the width of the browser. As the browser window shrinks in size the height of the div shrinks, but the overall height of the parent div is rigidly set to 1000px. The next div inside the box floats below the div with the image and takes up the extra space that the above shrinking div leaves behind. The problem is that the bottom div contains text that needs to be centered vertically for a div whose height can change depending on the size of the window. The overall height of the parent div does not. The two inside divs have a fluid height that when added together will always add up to 1000px. The height of the inside divs is determined by the width of the browser window.

The closest I have come to creating this is demonstrated on my sample page (http://www.animeviews.com/test/sample/test22.php).

jscheuer1
08-18-2011, 05:38 AM
I'd have to ask why? And I'd have to question some of your apparent assumptions. This float business - divs don't float beneath other divs. That's their natural behavior. The only reason to float them is to get them beside one another. And you still cannot use vertical-align for a div and hope for it to do anything to the content inside the div, so perhaps we're back to a table for that part. And why use opacity to hide the image? Using visibility: hidden is cross browser and just as effective.

But we still have a problem. The second contained division has no intrinsic height other than it's content's and any top or bottom padding. Using % padding there will only give a fixed amount of padding taken from wherever the browser thinks is best, probably the height of the parent.

We can't give it height because we want it to be the height of whatever's left over from the first contained division. That's where javascript can be used:


<!DOCTYPE html>
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script type="text/javascript">
onload = onresize = function(){
var r = document.getElementById('resizable');
r.style.height = r.parentNode.offsetHeight - r.parentNode.getElementsByTagName('div')[0].offsetHeight + 'px';
};
</script>
<style type="text/css">
#fixed {
height: 700px;
width: 20%;
border: 2px solid #000;
background-color: green;
}
#fixed div {
width: 100%;
background-color: red;
}
#fixed div img {
display: block;
width: 100%;
visibility: hidden;
}
#fixed div#resizable {
background-color: transparent;
}
#resizable table {
height: 100%;
}
#resizeable td {
vertical-align: middle;
}
</style>
</head>
<body>
<div id="fixed">
<div>
<img src="http://www.animeviews.com/images/alita1.jpg" alt="">
</div>
<div id="resizable">
<table>
<tr>
<td>I'm in the middle vertically</td>
</tr>
</table>
</div>
</div>
</body>
</html>

james438
08-18-2011, 06:24 AM
The reason for this little project is I am revising my church's website. Here is the test page (http://www.sovgraceopc.org/test.php). The scripture verse is not perfectly vertically aligned between the logo image and the tabs below. The width of the site needs to be horizontally fluid and fixed vertically.

I am not sure why you say divs can't or shouldn't be made to float beneath other divs. I am sure I am misunderstanding you there. I am not trying to vertically align the div, just the content within one of the divs. I could use vertical-align to center the content if I also adjust the line-height, but then I run into the issue of the height needing to be dynamic.

I was not aware of visibility:hidden. Good to know.

The interesting thing about the padding is that it appears to be dynamically based on the width of the parent div or some aspect of the upper div. I am not sure what it is based on. Not really all that important though. It is not the height of the parent, which is what I would have expected.


We can't give it height because we want it to be the height of whatever's left over from the first contained division.
Yes! I wish I could have phrased it like that earlier. Ah, well.

What you have posted works wonderfully by the way.

I really only dabble in webdesign and I am weakest in javascript. Thank you very much for your help with what I am sure is one of my more frustrating threads.

jscheuer1
08-18-2011, 07:14 AM
You can't use vertical-align with div because it doesn't apply to div in any way. It's sort of like using font-weight: bold for an image. It just doesn't do anything.

You can float the inner divs in my example and it will still work. It's just that float is used to prevent wrapping - the natural behavior of two divs. Here we want wrapping. Wrapping occurs even with a float because the widths of the two contained divs are 100%. They cannot float. There's no room for it. But as I say, since they're going to wrap anyway, no need to float them.

Without any styles, do:


<div>Hi There</div>
<div>I said, "Hello."</div>

The second one goes beneath the first. Now float them:


<div style="float: left;">Hi There</div>
<div style="float: left;">I said, "Hello."</div>

They'll be side by side.

james438
08-19-2011, 04:39 AM
I use floats just by default so that I know where they will be positioned within a page. In my case it looks like they do not need to be floated at all. Just a poor coding practice on my part that I was not aware I was doing.

One thing I do is in line styling. I know that is frowned upon, but I do it while developing a script and afterwards I place it in the head of the page and use classes. I mention it because I thought you might mention it, but you didn't.

I'm off to code some more.

james438
09-08-2011, 03:38 AM
New problem, but related.

In the following site http://www.sovgraceopc.org/contact.php (http://www.sovgraceopc.org/contact.php) the height of the table is effectively 0 while the page fully loads. This is especially noticeable for people with slow connections (not mine). One of the very last things loaded on the page is an embedded google map. For some reason this causes the table to have a height of 0 or very small height. This can be somewhat corrected by setting the height of the containing div to 200px or so, which acts as a placeholder for the height of the resizable div where the fading scripture verse/church logo is located while the iframe loads.

Another possible solution is to load a simple jpg image as opposed to a large iframe.

Is there a way to cause the iframe to load after the javascript becomes active or would it be better to post an image instead?

jscheuer1
09-08-2011, 09:09 AM
There is no iframe. As long as it doesn't interfere with the resizing script, setting the div height is a good idea.

james438
09-08-2011, 11:56 AM
I will set the div height then. I posted the wrong link in my last post. It should be http://www.sovgraceopc.org/map.php (http://www.sovgraceopc.org/map.php). In case you were curious.

jscheuer1
09-08-2011, 02:22 PM
Well, that page does have an iframe, and from the looks of it needs to. If setting the iframe's height works for that page, that's fine.

Or if you mean you want to speed the loading of the page, you could use an image of a map instead of Google Maps. But I don't think you're allowed to make an image from it. You would have to make your own map image. And it wouldn't be interactive.