Sometimes you may want to vertically align a block item, but the CSS-only vertical aligning methods don’t make you feel clean. Personally, I hate having to style items as a table/table cell to get them to vertically align in Internet Explorer.
jQuery to the rescue. Using a jQuery vertical align snippet as my base code, I modified it to be a jQuery plugin that will allow you to use the function in the jQuery chain.
jQuery Vertical Align Plugin Code
Simply copy this code into your website (if you don’t know where, leave a comment):
(function ($) { // VERTICALLY ALIGN FUNCTION $.fn.vAlign = function() { return this.each(function(i){ var ah = $(this).height(); var ph = $(this).parent().height(); var mh = Math.ceil((ph-ah) / 2); $(this).css('margin-top', mh); }); }; })(jQuery);
Now, you can use vAlign
as you wish; ie: $('#example p').vAlign();
.
Did this make your life easier? Was this information worth a buck?
Donate with PayPal (Much appreciated!)
If it’s not working
If it’s not working, it may be because the script applies a margin to the element, which may not work in all situations. Try changing 'margin-top'
to 'padding-top'
and see if that helps.
Any questions or comments?
94 replies on “Simple Vertical Align Plugin for jQuery”
Very usefull love it keep up the good work.
Does it work on multiple instances? So far, I can only get it to vAlign on the first named element.
Thanks.
@Jonas – I’ve not had any issues with multiple instances. You may want to try the
.each()
function and see if that helps.Thanks Zack. I have a sillier question: do you know if there is any way to get it to work if the html section it is applied to is hidden by default on page load and only visible if the user makes it so?
Nevermind. I’ll just fire the .each() for the show and hide. Thanks again.
Thanks for the code! The code however doesn’t run for each element in the selector. I updated it to fix this issues, here it is:
return this.each(function() {
var ah = $(this).height();
var ph = $(this).parent().height();
var mh = (ph – ah) / 2;
$(this).css(‘margin-top’, mh);
});
Hey Ryan,
Sorry about that – I thought it was working properly. I’ve updated the code in the article. Thanks!
Hi,
could you please be so kind to explain me where and how to code / copy-paste this into a working function? I’m totally blind about jQuery (my bad)
nevermind me asking 🙂 got it figured out 🙂
Nice little plugin sir, thanks.
First I stumbled upon the SEO stylesheet, now this? Keep it up, you’re on fire!
@Judd – glad you’ve found them helpful.
Hey, this is great, successfully tested in IE6, Chrome, Opera, Safari, however it surprisingly does not work in Firefox 2 (I’ve got 2.0.0.19). Any ideas how to make it work in FF2?
Hi! Great! Do you know how to center a div in the browser window?
@Jonas – That’s done with CSS. The container div should be
text-align:center
, and the centered div should bemargin:0 auto;
[…] If you want it like function you should check this link. […]
THANK YOU!!!!!!!!!!!!!!!!!!!!!!!!!! THANK YOU THANK YOU, YOU Just saved me another 3 hours or trying to make a classic Jquery method to work with each function. (I’m kinda clueless to javascript in general, still learning the basics).
Thanks again
@Alexandru – Glad I could help 🙂
Anther quick question
If i set it to the container div will it work?
(trying to make a new website and i have to make it vertically aligned to the top and bottom sides) so i am wondering does it work by calculating the window height or I have to make another div (and not set everything to it) and slap my container inside said div.
Thanks 🙂
wow ! awesome. Just tried with an image and works very well. I added a bind on resize window to replace the image on resize
$(window).bind(‘resize’, function() {
$(‘#content img’).vAlign();
});
Thanks for your code
Hey Zack:
Thanks for doing this plugin as a social service:)
Unfortunately, I am a technical idiot.. and dont know – where to exactly copy and paste this code of yours 🙂 -> as you guessed ..
So -> for the technical idiots like me -> would you kindly spill some ink ? and let me know wher to copy and paste : in other words: copy and paste too -> is an art -> you have to know what to copy, where to copy and how much to copy
and yes.. I dont even know THAT MUCH
thanks
ajay mishra
ceo nomolisa.com
Yes, I know this guy, and he’s not kidding about being a technical idiot! 🙂
Nice clean code there, great article again Zack!
I added a way to reposition the stuff when the window is resized.
(I used this for a full screen document with one div that always should be centered).
I’m not a jquery king, so I hope it’s all good;
$(document).ready(function(){
$(“.content”).vAlign();
});
$(window).bind(‘resize’, function(){
$(“.content”).vAlign();
});
BRILLIANT.
The IE demon won’t eat THIS afternoon.
Hi! I seem to be having some trouble with elements that need to be hidden at start. For example if i want to use it as a title that will appear when i hover over an image. It doesnt seem to get “ah” since the element is hidden.
Ah .. i figured out a solution while i was writing this. I used opacity:0 and opacity:1 as hover. The elemnt is there and its height can be read. But its a side road, any better solutions?
[…] strict customer requirements such as IE6 and minimal structural modifications on HTML. Luckily, an example from Katz Web Services came to the rescue. It was the best solution I see so far (with minimal codes). The original […]
Thanks for the excellent post. The vertical align function has already helped me out tremendously!
We had some discussion on Stack Overflow about issues when (probably) some external CSS was not yet loaded. When not yet loaded then the value for “$(this).height()” may yield zero, or some value that does not match the actual height. Placing the code to load your CSS before the code to load jQuery may help, though things seem to be more complex than I would have imagined. Anyway, see http://stackoverflow.com/questions/1324568/is-document-ready-also-css-ready/
If you want the item to be vertically aligned to the window (i.e the parent of the element you want to align vertically is BODY), then change:
$(this).parent().height();
to
$(window).height();
Thats all! (Note that this will make the code only work in this instance though)
Hi Zack,
I have a problem with my website wich is still in developpement, I’m trying to understand all the basis, the problem is that all my subcatergories are not aligned (click on “piscines” to access the differents subcategories, so you will see that the images are aligned but not the titles. Will your tips work?
thanks for you help
Youssef
It should, yep. I believe you’ll want to use the following code:
$("div.ProductImage img").vAlign();
nice function mate.
I changed my code from:
$(this).css(‘margin-top’, mh); to
$(this).css(‘padding-top’, mh);
because I was having some problems with a UL list. My html code is:
Blah Blah Blah
and I use $(“.valign”).vAlign(); on the
Nice plugin. Really saved me a lot of trouble.
I found one similar, although probably a copy/an enhancement based from yours:
http://cool-javascripts.com/jquery/vertical-alignment-of-contents-inside-an-element-using-jquery.html
I am having problems with multiple instances and I’m not that great with jquery. The first element positions but the rest don’t unless I refresh the browser.
Is where the .each ( ) function
would come into play? If so where would it be placed in the code?
Oh my god, this code is delicious!! 😀
But… I changed it.
That makes sense. You could also do
if(mh != 0)
…This work, but maybe you have the margin collapse issue. If this is the case. Put this line before the margin-top line.
$(this).parent().css(‘padding-top’, ‘1px’);
thanks. I’m so glad somebody invented this. I went through numerous plugins, but this is the simplest and most solid one. thumbs up!
This is some beautiful code. Very much what I was looking for. Thanks Zack.
maybe it would be better to use
var ah = $(this).outerHeight();
I wanted to try it and have not figured out how to add this function to my website. Please advice. Sorry about the ignorance.
@Harry Wong: This code uses the jQuery javascript library. I recommend reading this article: Getting Started with jQuery for an introduction to the world of simple and powerful javascript coding!
the code as is, has javaScript errors in it, on the return this.each… line.
using firefox 3.6.6
I’m getting a syntax error using jquery 1.4.2 using the code as shown beginning at the line ‘return this.each(function(i)’
Is this code compatible with 1.4.2?
@Matt and @David – The code was broken because I have been testing a new version of my WordSpinner plugin…Sorry about that!
I’ve fixed the issue, and the code is diplaying properly and will work again.
Thanks man, just what I was looking for, but It’s not working on Chrome, what could that be?
The link titled “jQuery vertical align snippet” in the article seems to be broken.
For this to work do we just need to include JQuery, then include that function and a calll to it? Are there any other base libraries to include also – is that what the link was for?
Cheers
The code is really perfect and it is working smoothly. I just want to know how we can adjust it if I want to vertical-align to the bottom, not the center?
I would do CSS for that: make the container
position:relative;
and the itemposition:absolute;
Snippet does not work for me in Safari 5.0.2. IE, Firefox, Chrome successfully tested. Any ideas? Thanks.
Nice.
very usefull
Facken awesome! Thanks!
I added a few tweaks to the code based off of the comments as well as some things I noticed to fix negative margin issues if the browser height is less than the height of the container div. Here is the final result:
(function ($) {
// VERTICALLY ALIGN FUNCTION
$.fn.vAlign = function() {
return this.each(function(i){
var ah = $(this).height();
var ph = $(window).height();
var mh = (ph – ah) / 2;
if(mh>0) {
$(this).css(‘margin-top’, mh);
} else {
$(this).css(‘margin-top’, 0);
}
});
};
})(jQuery);
Also, I’m using the following to call the function that takes care of both when the page is loaded or the browser is resized:
$(document).ready(function(){
$(“#container”).vAlign();
});
$(window).bind(‘resize’, function(){
$(“#container”).vAlign();
});
This code is geared for a container div that’s a direct child of the body that needs be to vertically centered in the body.
— Jonathan Lahijani
Hi there. I found your code useful as a start base, but there is a little problem with it.
This line:
var mh = (ph – ah) / 2;
Should actually be like this:
Math.ceil((ph-ah) / 2);
This is because margins/padding, when using pixels, has to be an integer number.
Then I could argue about using margin-top exclusively. There are time where paddings (top/bottom) should be used instead.
Thanks SK; I’ve updated the code snippet with your changes.
Awesome, thanks!
its ok
This is a great plugin. Thank you!
However if you’re centering inline images be sure to have the height and width specified in the tag otherwise it will force the browser to redraw the margins in weird ways each time you refresh the page.
its not working properly in chrome!!
Hi, this not work in chrome :(((
It should…could you please link to the page where it doesn’t work?
Also, try replacing margin-top with padding-top and it might work.
Thanks man! Works like a charm 🙂
I found that if there is an element positioned absolutely inside the wrapper div, you have to change the ‘margin-top’ to ‘padding-top’ (just on IE) .
So if you have the follow code:
$(‘#content’).vAlign();
Lorem ipsum
The ‘content’ div goes to the top of the window on ie. To fix it you may use:
$(this).css(‘padding-top’, mh);
instead of:
$(this).css(‘margin-top’, mh);
Then it works very well.
Thanks again for this simple but powerful jquery script.
Great script! Thank you very much
For anyone having issues with Chrome replace:
$(document).ready
with
$(window).load
The $(document).ready code is the correct way to do things in jQuery. If you need to change this part, it’s likely not the real problem.
Very helpful script. But has been mentioned, it only works on elements that have been rendered. Here is one solution for vertically aligning images that are loaded into the DOM and then when all elements are aligned fire the callback plugin/function.
$(document).ready(function(){ createPanels(); var $img = $(“img.product_image”), count = $img.length, statusCount = 0; //wait for images to load and aligned before firing tab script $img.load(function(){ var $this = $(this); statusCount = statusCount + 1; $(this).vAlign(); if(statusCount >= count) { $(“#fpWrap”).idTabs(); } }); });
It is right that for the success for your blog just create interest for the readers and they will take interest in your product. If your readers get knowledge from your blog, they will introduce your blog in their community.
Excellent goods from you, man. I have take note your stuff previous to and you’re just extremely great. I really like what you’ve got here, really like what you are stating and the way in which wherein you are saying it. You make it entertaining and you still care for to stay it smart. I cant wait to learn much more from you. This is actually a tremendous site.
Any Ideas about the Chrome issue? Its working great for me in IE and FireFox, but not in Chrome. The url of the problem page is: http://legendstaxidermy.com/africangallery.aspx
Any ideas are greatly appreciated!
whoah this blog is excellent i love studying your posts. Keep up the good paintings! You know, lots of people are hunting round for this information, you can aid them greatly.
I have plugin-ified this on my GitHub: https://github.com/esqew/jQueryVerticalCenter/
You can now utilize it as you would any jQuery plugin!
Is better with outerHeight().
This include the padding.
Hi! VERY helpful post, thank you! I have to plead ignorance… I’m not sure where to paste in the code, or how to insert the jQuery in Dreamweaver…!! Sorry to be a pain!
Check out this: http://www.w3schools.com/jquery/jquery_intro.asp
Hi,
mine was giving me no data back for the element I needed the hight from (the outer container of my website), tho, I new what the height was and I changed it to this script:
(function ($) {
// VERTICALLY ALIGN FUNCTION
$.fn.vAlign = function() {
return this.each(function(i){
var ah = 660;
var ph = $(window).height();
if(ph > ah) {
var mh = Math.ceil((ph-ah) / 2);
$(this).css(‘margin-top’, mh);
$(‘body’).css(‘background-position’, ‘0px ‘+mh+’px’);
}
});
};
})(jQuery);
In the footer of my webpage I used this script:
$(document).ready(function() {
$(‘#wrapper’).vAlign();
$(window).resize(function() {
$(‘#wrapper’).vAlign();
});
});
My website is being vertically centered and is being replaced if you decide to change the size of your browser screen! In my case the ‘660’ indicates a 660px high website. I added another check (if ph > ah) because otherwise there is the possibility a negative margin is added and thus some text will apear outsite its container.
Hope this might be of any use. I’ve got absolutely no clue why $(this).height() returned 0 pixels, so there’s a good chance it works for anyone else when using $(this).height() instead of a fixed number!
Joshua
Oh right, before I forget 🙂 for this specific website the background continued inside the website. Therefor I needed the background to be replaced as well, which explains the line changing the background-position property for the body!
Hi there – this code is awesome, however it has stopped my image being horizontally center aligned. Previously the image was center aligned by using CSS #div { text-align:center } but after adding in the jquery it is left aligned – thanks in advance for any help!
#div {text-align: center;}
ignore me! it works! THANK YOU!!!!!
It does not work in Safari… any ideeas? Seem to be something wrong in the calculation. My images are not centered..
Nice work ! Worked perfectly.
doesn’t work with chrome, because the way chrome, ie and ff deal with image loads is different. chrome run the code BEFORE the image finishes its load, though, the height, at the moment the reading, is 0, and the code shoudn’t work properly. therefore, it could be used the load() event on the image. but.. the ie doesn’t trigger when the image is loaded.. it DOES LOAD before the code, but it doesn’t like to share it with the world.. so, I created a version of the code, which works with ie, ff AND chrome. it’s based on the assumption that, if the browser loads the image before the code (and, in consequence, has a value for image height() ), it’s because it cares about prevention on dealing with images, so, the load() is unnecessary. if it runs the code BEFORE the load of the image, it should get prepared to respond about when the image load accurs (and, then, the image load() event will trigger). but, as always, there must be a browser who run codes which deal with image without worring with the problems with loading (it means, any time, probably before the image load), AT THE SAME TIME it doesn’t like to report about the load() event. so, it’s not universal.. but, working with ie, chrome AND ff, its kind of.. ps.: paste this code into your js file, and use the class vertical-align-middle in any object you want to vertical-align to middle. 😉
$(function() {
$(‘.vertical-align-middle’).each(function() {
if($(this).height() == 0){
$(this).load(function(){
var ah = $(this).height();
var ph = $(this).parent().height();
var mh = Math.ceil((ph-ah) / 2);
$(this).css(‘margin-top’, mh);
});
}else{
var ah = $(this).height();
var ph = $(this).parent().height();
var mh = Math.ceil((ph-ah) / 2);
$(this).css(‘margin-top’, mh);
}
});
});
additionally, I paste this other code, which lies on the fact that the css vertical-align DO work. but only in respect to text (or, more specificaly, the line of the text). to avoid undesired effects on the container of the element you want to vertical-aligning with, related to other textual content that the container can have, it’s appended to this container a span wrap, and, appended to this wrap, the content you have applied the verticalAlignMiddle class in the first place. it aplies on the wrap span the line-height of the original container, and aply on the element you are vertical-aligning the vertical-align: middle configuration. it’s all you need to have a element vertically aligned, without worrying with browser incompatibilities.
$(function() {
$(“.verticalAlignMiddle”).each(function() {
var spanContainer = $(“”);
$(this).parent().append(spanContainer);
spanContainer.css(“line-height”, $(this).parent().height() + “px”);
spanContainer.append($(this));
$(this).css(“vertical-align”, “middle”);
});
});
there is this 3rd way to vertically align elements, which is pure css. it’s ugly, but it works.
you write, in the HTML:
in CSS:
.verticalAlignMyGrandchild{ //A FIRST WRAP (USE IT IN A SPAN)
position: relative;
display: block;
top: 50%;
margin-top: -100px;
height: 200px;
text-align: center;
line-height: 200px;
}
.verticalAlignMyGrandchild span{ //A SECOND WRAP (SPAN)
line-height: 0;
}
.grandChildVerticalAligned{ //USE IT IN THE ELEMENT YOU WANT, IN FACT, VERTICAL-ALIGN
vertical-align: middle;
}
AND, it’s done. 😉
ps.: to horizontal align, the text-align: center, in any of the containers, should work.
well, what a beatiful thing.. the page erased part of my code.. well, here it is (again!):
AND.. it deleted again.. well.. I will not write it again.. you just put inside the container a span (class=”verticalAlignMyGrandchild”), inside you put other span (no need to classified this, the css selector do the job), and, INSIDE it all, you put what you really want to vertical align (class=”grandChildVerticalAligned”). hope this time it works..
Nice code. Its very useful. What about using position relative instead of margin?
Example:
$(this).css(‘position’, ‘relative’).css(‘top’, mh);
With position relative you dont have the problem of margins or paddings.
Thank you for creating this, I appreciate it.
Is this code ok to use for commercial use? Does it have any kind of open source license?
Yes consider this code GPL 2+.