Knowing how to position things where you want them is one of the most important tools in a web designer’s toolbox. Understanding page flow, understanding everything is a box, understanding floats, etc. Once the basics are learned, a common question for intermediate designers is how to position elements relative to other elements. The standard CSS solution for this is to use the ol’ absolute positioning inside relative positioning trick. In a nutshell, you can use set relative positioning (or really, any positioning that isn’t the default static) on an element and then absolutely position child elements of it within that context. A lot of times, this works wonderfully well, but it’s actually quite limited:
- Forced to use positioning value other than static, even if otherwise unneeded
- Elements trying to be positioned based on the other must be child elements
- If the parent needs and overflow value it can get awkward
jQuery UI now has a position utility function that makes the job of positioning elements relative to other elements deliciously easy! Let’s take a look.
First things first
We’ll be using jQuery and jQuery UI here, so we are assuming you are loading the jQuery and jQuery UI libraries on your site.
<head>
...
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js"></script>
...
<script type="text/javascript">
$(function() {
// do stuff, yay!
});
</script>
</head>
The Basics
One of the sweet things about jQuery and jQuery UI is the almost sentence-like syntax of writing it. One-word function names and parameters that really drive home what is going on. Here is a basic example.
$("#move-me").position({
"my": "right top",
"at": "left bottom",
"of": $("#thing")
});
Maybe a little graphic will help:

The coolest part here is that there are no prerequisites for this to work. The element being positioned doesn’t need any special CSS positioning value (or to be a child element), the element being positioned against doesn’t need any special CSS positioning value (or anything else).
All Options
Here is the full set. Only just a few more options.
$('.positionable').position({
"my": "right top" // Horizontal then vertical, missing values default to center
"at": "left bottom" // Horizontal then vertical, missing values default to center
"of": $('#parent'), // Element to position against
"offset": "20 30" // Pixel values for offset, Horizontal then vertical, negative values OK
"collision": "fit flip" // What to do in case of
"bgiframe": true // Uses the bgiframe plugin if it is loaded and this is true
});
We covered “my”, “of”, and “at” in the basics, but the full set of parameters include setting an offset, using the bgiframe plugin (fixes some IE z-index issues), and collision detection, which I’ll cover later.
Magic Zoom!
I thought I’d throw together a little “real world” example of where this could be useful. Have you ever seen a plugin or other JavaScript effect where you click on an image and it “grows in place”? I’ll call it Magic Zoom because I like giving lame names to things. This is how it might work:
- Have a grid of thumbnail size images (keeps page load size down)
- When a thumbnail is clicked…
- Load the full size image directly over top the thumbnail, scaled down to the exact same size
- Animate the new full size image up to it’s original size
- During the animation, keep the image centered over the thumbnail
- Click to close
HTML of gallery
The gallery is simply anchor tags that link to the large version, and within, image tags of the thumbnails. Without JavaScript, still totally functional.
<div class="gallery">
<a href="http://farm4.static.flickr.com/3329/4556228155_7ce08c45a3.jpg">
<img src="//farm4.static.flickr.com/3329/4556228155_7ce08c45a3_m.jpg" alt="" />
</a>
<!-- More... -->
</div>
jQuery JavaScript
$(function () {
var $el;
$(".gallery a").live("click", function () {
$el = $(this);
$("<img>", {
src: $el.attr("href"),
class: "larger"
}).load(function () {
$(this)
.appendTo("body")
.width($el.find("img").width())
.position({
of: $el.find("img"),
my: "center center",
at: "center center"
})
.animate(
{
width: 500 // width of large image
},
{
duration: 1000, // 1000 = 1 second
easing: "easeOutQuad",
step: function (i) {
$(this).position({
of: $el.find("img"),
my: "center center",
at: "center center",
collision: "fit"
});
}
}
);
});
return false;
});
$(".larger").live("click", function () {
$el = $(this);
$el.fadeOut(400, function () {
$el.remove();
});
});
});
The interesting concept here is the “step” parameter for the animate function. You can give that parameter a function, and that function will run on every single keyframe of the animation. For us, that means we will use the position function to make sure the large image is still centered over its thumbnail.
Yeah… the growing of the images is a little shaky. If anyone has any ideas there, let me know.
Collision detection!
Being able to set elements relative to other elements with such simple syntax and little code is awesome, but what really sets this position utility above and beyond is collision detection.
What if where we tell the element to be ends up being outside the browser window? That could be a problem, depending on the situation. Take our Magic Zoom example. Theoretically the reason people are clicking the images to see a larger version is because they actually are interested in photo and want to see it larger in more detail. It doesn’t help them if the image is along the left edge of the page and gets cut off as the new one grows.
Dealing with this problem is extremely easy with the position function. All we need to do is add the collision parameter with the value “fit” and the position function will ensure that whatever it is positioning is never outside the window.


This is a really useful idea…Thanks For Sharing
Thanks Chris! This could be useful for my site upgrade I’m doing.
Thank you Chris,
I enjoy reading your site, i learn a lot from your posts and screencasts
Thanks for the video. I didn’t really understand what the collision detection was for because my screen resolution is very high.
Resizing the browser window size should work also.
Cool!
jQuery and Chris are awesome!
My basic CSS and jQuery learned from Chris!
This script has an error on IE6 and IE7 but on IE8 works great(the jQuery effect, the style is still bad).
The people I build websites still using IE6 and the viewers to.
So Thanks a Lot!
Really thanks! :) Sorry for my english
have you thought about letting the images collide with each other and maybe shrinking to accommodate each other?? this might be really cool
-James
Although pretty cool, this breaks when you click on another image as one is being animating. I believe why it breaks and starts stacking the images on top of each other is because the click event sets the absolute coordinates. I’m wondering if you wrapped the .live click event in an if statement you would prevent this problem. I could be wrong though.
I would think the reason why it’s jittery when it’s animating is because it’s constantly checking it’s self against the window?
jittery and to slow.Not really an option for an live project but thanks for sharing!:)
Zooming in JavaScript always looks terrible due to the nature of adjusting CSS values in sequence. I don’t know think there is really any way around that, but you can make it less perceptible by adjusting the timer.
Great tutorial, i need to try this when i have time.
Neat example Chris but couldn’t you come up with a more original name?!
Sorry about the name conflict there! I named it that because that’s what this exact effect is called in this eCommerce software I have used.
thanks chris I am leaning css and Jquery tricks from this website
thanks
by randomly clicking the images I could make them disappear.
I think it’s getting jittery because the step function isn’t called every time the image changes size. I added a counter variable to the step function and had it spit out the value after the animation, and the step function only gets called between 10 and 14 times (on my system anyway), and the scaling animation looks a lot smother than I think it would look at 10 keyframes a second.
If I get rid of the box shadows on the large image, the step function gets called up to 40 times, 62 times if I get rid of all the box shadows. At those speeds the jitter was almost non-existent.
I think the only way to eliminate the jitter is to write your own animate function that actually calls position every time the size is changed.
Or ideally one that each step works out all the numbers and then updates the scale and position at the same time, instead of math->scale->math->position->math->scale etc.
Although… that’s not really possible is it? since the browser does the math when the value is changed… oh well, now I’m just thinking aloud and should probably shut up.
Nice research! I think it’s kinda crazy that the addition of box shadows affects how many times a callback function is fired.
I get the impression it just calls the function “when it gets a chance.” Either that or it won’t call the function if the function’s still running.
Either way it seems to depend on the browser’s performance, and shadow’s just seem to affect the browser performance in general. I’ve stopped doing much with changing text-shadows on hover, because if you mouse over a group of links with the effect applied, there’s actually a noticeable delay in the hover effect, on my hardware at least.
I think the deal is it calls the step function on “keyframes”, which probably does mean “once in a while” rather than at every single pixel movement.
Ultimately this probably isn’t the best use for it and might be better served animating the width, top, and left values accordingly and concurrently.
Not really the position utilities fault, that is still kinda awesome =)
I loved the Vimeo video! I am gonna use your piece of code on my blog and this time I am not going to use anybody’s plugin! I will do it everything by myself! :)
Thanks Chris. jQuery UI is awesome.
Can you show us how to do the actual http://www.magictoolbox.com/magiczoom/ next! :-P
Thanks for the great article.
awesome tutorial thanks
Nice plugin, just need some polish, to block the click till the bigger image loads, and show some loading.
If you just keep clicking the image before the bigger image loads, it will load as many as you clicked!
Another pearler Chris! As always, you make something difficult, seem simple to understand ;) Cheers, Steve
Very cool effects. Previously I was just using a hover function to enlarge the pictures.
But this is much better.
Hey Chris:
One thing i noticed. If you click multiple images too fast you not only throw the images all over the page, but you also loose some images on the page.
If i double click on a image, it gets zoomed half way. Then if i click on an image next to it just immediately, that image gets zoomed fully but also gets positioned at the top left corner of the screen. Then if i click on this zoomed in image, it gets deleted from the screen.
T
If i double click on a image, it gets zoomed half way. Then if i click on an image next to it just immediately, that image gets zoomed fully but also gets positioned at the top left corner of the screen. Then if i click on this zoomed in image, it gets deleted from the screen.
That’s my experience trying it out.
Hmm, looks interesting, but dont use JS to often – this is “style vs. userperformance”. Well, you can do postitions with css, use it if you dont need more. kind regards
Thank you! The first site that explained jQuery Dialog Position to me like I’m 5 years old. And I finally got it!