When people are new to css layouts there’s a tendency to gravitate toward positioning. Positioning seems like an easy concept to grasp. On the surface you specify exactly where you want a block to be located and there it sits. Positioning is a little more complicated than it first appears though. There are a few things that can trip up a newbie and a few things to understand before positioning becomes second nature.
You can do some great things with positioning, once you develop a deeper understanding of how it works.
CSS Box Model and Types of Position
In order to understand positioning you first need to understand the css box model. The link in the previous sentence is a post I wrote for InstantShift about the box model. I’ll point you there for details and offer a quick summary here.
Every element in css is contained by a rectangular box, each with an area defined for the content, padding around that content, a border enclosing both and a margin outside the border that separates one box from the next. You can see it in the following image.
Positioning schemes define where a box will sit in the overall layout and how each box affects the others around it. Positioning schemes include the normal document flow, floats, and several types of positioned elements.
The css position property takes 5 values.
- position: absolute
- position: relative
- position: fixed
- position: static
- position: inherit
I’ll cover the first three in more detail below and just say a couple of quick things about the last two here.
Static positioning is the default. Any element that has position: static applied is in the normal document flow. The rules for where it sits and how it affects other boxes are defined by the box model.
A statically positioned element will ignore any values for the properties, top, right, bottom, and left as well as any z-index declarations. In order to use any of those properties your element must have absolute, relative, or fixed positioning applied.
Inherit as in all css properties is simply that the current element receives the same value as its parent element.
Absolutely positioned elements are completely removed from the normal document flow. As far as the elements around them are concerned the absolutely positioned element doesn’t exist. It’s as though the display property of the element was set to none. If you want to maintain the space so other elements don’t move to fill it you need to account for it in other ways.
You set the location of an absolutely positioned element through the top, right, bottom, and left properties. You’ll usually define only two of these, either top or bottom, and either left or right. By default each will have a value of auto set.
The key to understanding absolute positioning is understanding where the origin is. If top is set to 20px the question you should be asking is 20px from where.
An absolutely positioned element is positioned relative to the first parent element that has a position other than static applied to it. If no parent element up the chain meets that condition the absolutely positioned element is positioned relative to the document window. Huh?
It’s a little confusing with all the talk of relative, especially when there’s relative positioning, which we haven’t yet talked about.
When you set position: absolute on an element css says to look at the parent element and if it also has positioning (other than static) applied, the origin for the absolutely positioned elements is the top, left corner of the parent element.
If the parent doesn’t have positioning applied then go to the parent’s parent and check to see if it has positioning applied. If it does then that element’s top left corner is the origin for our absolutely positioned element. If not then continue up through the DOM until you reach a positioned element or failing that reach the outermost edge of the browser window.
photo credit: kevindooley
Relatively positioned elements are positioned based on the same top, right, bottom, and left properties, but are simply shifted from where they would normally sit. In a sense adding relative positioning is similar to adding a margin with one very important difference. The elements around a relatively positioned element act as though that shift didn’t exist. They ignore it.
Think of it as a ghost image shifted a little out of kilter from the actual image. The relatively positioned element behaves as though it’s the ghost, while all other elements behave as though it’s the original non-ghost image. This allows elements to overlap each other as a relatively positioned element can move into the space occupied by it’s neighboring elements.
The relatively positioned element is taken out of the normal document flow, but still affects the elements around it. Those elements just act as though the positioned element is still in the normal document flow.
We don’t have to ask the question relative to what here. The answer is always the normal document flow. Kind of like adding a margin as far as the element is concerned and kind of like doing nothing as far as neighboring elements are concerned. Margin, yet not margin.
photo credit: Arjun Mehta
Fixed positioning acts similarly to absolute positioning with a couple of differences.
First the fixed positioned element is always positioned relative to the browser window and take the now familiar top, right, bottom, and left properties.. It’s the positioning rebel that ignores it’s parents.
The second difference is inherent in the name. Fixed positioned elements are fixed. They don’t move as the page is scrolled. You tell the element where it should be located and it never moves. Maybe not so rebellious after all.
In a sense fixed positioned elements might be akin to fixed background images where the containing block is always the browser window. If you set a background image on the body it will behave mostly like a fixed positioned element with less precision about where it’s located.
Background images also wouldn’t be able to change where they sit in the third dimension, which brings us to the z-index.
Z-Index, Breaking out of the Plane
The page is a two dimensional plane. It has a width and a height. We live in a 3-dimensional world that also includes depth and z-index is that depth. That extra dimension moves in and out of the page.
Higher z-indexes sit on top of lower z-indexes and move toward the front of the page. Conversely a lower z-index sits behind the higher z-index and recedes toward the back of the page.
Without z-index, positioned elements are somewhat boring. They have their use without that extra dimension, but with z-index applied you can do some creative things and allow one element to sit on top or behind another element. By default all elements have a z-index of 0 and negative numbers are allowed to be assigned.
Z-Index is actually much more complex than I’m describing here, but the details are for another post. For now remember the basic idea of an extra dimension and a stacking order and remember that only positioned elements can use the z-index property.
There are a few common issues you see with positioned elements and each deserves a sentence or two.
1. You can’t apply both the position property and the float property to the same element. Both are conflicting instructions for what positioning scheme to use. If you add both to the same element expect the one that appears last in your css code to be the one that’s used.
2. Margins don’t collapse on absolutely positioned elements. Suppose you have a paragraph with a margin-bottom of 20px applied. Right below the paragraph is an image with a margin-top of 30px applied. The space between the paragraph and the image will not be 50px (20px + 30px), but rather 30px (30px > 20px). This is known as collapsing margins. The two margins combine (or collapse) to become one margin.
Absolutely positioned elements do not have margins that collapse, which might make them act differently than expected
3. IE gets z-index a little wrong. In IE6 the select element always appears at the top of the stack regardless of it’s z-index and the z-index of other elements around it.
IE6 and IE7 have another z-index issue with stacking context. IE looks to the outermost parent with positioning applied to determine which group of elements is at the top of the stack instead of looking at each individual element.
You would expect the paragraph to be at the top of the stack, because it has the highest z-index. However IE6 and IE7 would place the image on top of the paragraph, because it sees two different stacks. One for the div and one for the image. The image has a higher z-index than the div and so will sit on top of everything inside the div.
The position property sets an element to behave according to one of the css positioning schemes. You can set values of absolute, relative, fixed, static (default), and inherit on positioned elements.
Positioning schemes, including css positioned elements, define the rules of where a box sits within a layout and how neighboring elements are affected by the positioned element.
A z-index can only be applied to positioned elements. It adds a 3rd dimension to a page and sets the stack order of elements
The position property seems easy to grasp, but it works a little differently than it looks on the surface. What you might think is relative positioning is more likely absolute positioning. You’ll generally want to use floats when developing a layout and use positioning on specific elements that you want to break out of the layout.
Download a free sample from my book, Design Fundamentals.
Thats a great post, and I will share that with people who are up and coming in webdesign and css techniques.
Thanks Bryan. Did you go through the same thing when you were first starting? Did you reach for positioning before floats? I know I did and I see many other people doing the same.
Actually, I did. At the time, I thought doing positioning was the way to go, it ultimately resulted in more headache, as each piece started moving around as I got further into the project.
That’s exactly how it was for me. Positioning just seems more like it’s going to be what you want and it can be, but floats are so much easier to work with for layouts.
Great article, I see a lot of people doing absolutely positioned layouts. I actually started floats first, I guess I came across good sites to learn from.
There’s one thing I think is wrong in your post though, if you set one of the four properties (let’s say bottom to 10px) then the other ones won’t be automatically set to 0. Otherwise, you would have it be at the corners but instead it moves up from the bottom 10 pixels just as you’d expect. Also depends if the container is in a relative wrapper.
Thanks Sunny. Good for you, approaching it right from the start. There weren’t as many blogs around talking about this stuff when I got started. I read a book or two and then jumped in.
You’re right about the defaults, but I thought that’s what I said. I mentioned only the top and left would get a default of 0 if you didn’t specify anything. I guess I should have mentioned that if you set a bottom then top doesn’t get set, but left will. I believe that’s what would happen. Each axis should get a default of 0 unless one of the properties on that axis is set.
then you can adjust your sidebar on this site 😉
Thanks Pol. Is the sidebar not displaying correctly for you? Works for me in all the browsers I’ve tested, but it’s certainly possible I missed something.
excelent post, I liked the way you explained the z-index.
Thanks Jozef. Hopefully you’ll like the more detailed post I’m planning for this week all about the z-index.
I feel that the proper title of this article would be ““How Well Do Browsers Understand CSS Positioning?”
Why would that be a better title? The focus of the post is on explaining css positioning in general with one section of a couple of browser issues.
The article isn’t really about browsers not getting it right, but rather making sure we all understand how it’s supposed to work.
Here’s some more on the box model: http://helpcss.com/wiki/Box_model
very useful, thank you.
This is a very useful posts, both beginners or advanced coders. Even somebody with my experience I learned some new things I wasn’t aware of e.g collapsing margins.
Thanks Lucien. In a sense collapsing margins were new to me too. I had come across them a few years ago, but never knew what they were called 🙂
Wow, thanks for your detailed explanation. The w3schools html manual isn’t enough.
Glad I could help. 🙂
Great article, love the way you described the absolute positioning. Thanks
Thanks Dayan. I’m glad I could help.
Great Article. I am stuck now as I am trying to position something for printing. I’m trying to position an element in a fixed position for use with pre-pinted stationary always from the the bottom of the page. Do you have any suggestions as to how to manage this type of problem.
I’ve been searching for a couple of days now and haven’t found a good solution for you. My initial thought is to use positioned: fixed, but that doesn’t seem to work since what’s on the screen isn’t necessarily a printed page worth.
I think what you want to use is page-break. You might have to add the the element you want fixed as an image on the element where you break the page, and it will still be up to you to make sure to add the breaks where they’ll break when printing.
Hopefully that helps point the way toward a solution.
Hi, I love your website.
I am a newbie when it comes to designing website and I am just wondering how do you make it so that whenever the user zoom in/out, the website will always tend to stay in the middle like yours?
Thanks Jack. The measurements of the site are relative and all based on the size of the type. Vertical measurements are sized in ’em’s and horizontal measurements are sized in %.
For example the space between paragraphs is 1.5em. If you zoom in and increase the font-size, the space is still 1.5 times the size of the font.
One exception to the horizontal measurements using % is I have a max-width set on the overall container that’s based on ’em’s At the widest it’s 75em, which at the default font-size is 1200px wide. The site can’t get any wider than that. Because I used max-width it can get smaller though so paragraphs reflow.
Here’s a post I wrote awhile back on how to build this kind of flexible layout. This site isn’t built exactly the same way, but it follows the basic idea.
The key is really the relative measurements and the max-widths.
Great article. I’m just getting started and understanding how to work with positioning is tricky at first but your explanations go a long way in making things make more sense. Thanks! Looking forward to digging around more here.
Thanks Kevin. I’m glad the article was helpful. Positioning can be tricky, because there are a few things about it you may not realize at first. If you’re just getting started, keep practicing. Set up some demos for yourself and try different things. See what happens. Then when something isn’t making sense see if you can figure out why and then spend some time researching an answer.
Very nice article Steven. Great comprehensive info on positioning. I might have played up that floats are usually a better choice for page layout elements and why. I know the article isn’t about float, but felt like a tiny footnote and those new to css positioning can pull their hair out for weeks before learning this lesson.
Also I’m not sure that your first statement on common positioning issues is entirely accurate, namely that you can’t apply position and float on the same element. I could be in the wrong, but I have encountered situations where I’ve had to give a floated elements position:relative. One popular example I could site would be Matthew James Taylor’s approach to equal height columns, which I’ve employed a number of times. (http://matthewjamestaylor.com/blog/equal-height-columns-cross-browser-css-no-hacks)
Please tell me if I’m wrong. Either way, I enjoyed reading your article. Thanks for taking the time to write it. Take care.
Thanks Michael. I have an article on floats that I wrote shortly before this one and I have written about preferring floats to positioning for layouts. If you look below in the footer there’s a series on css layouts and they all use floats.
You’re right about having positioning and floats on the same element. I was under the impression you couldn’t when I wrote the article. However you can’t both position and float an element in a layout. One or the other is going to position the element. Adding position: relative is the one time I think it ends up being useful. I’ve done that myself so you aren’t wrong.
Thanks for the link to article. I do know the article and have linked to it myself. I wrote an article with a few methods for equal height columns and that article featured prominently.
Your blog was extremely helpful. Positioning has been surprisingly difficult for me to master, and everywhere else I’ve read about it hasn’t made anything click for me until now. Thank You!
And if I could pester you with one question…If I have 3 images that I want to overlap each other, do I float the parent element and absolutely position the 2 children on top of it? Should I just absolutely pos. all 3? The 1st image is a larger (500x700px) jpeg, the 2nd layer is a smaller animated gif, and the top layer image is the same size as the base image. So basically the two larger images are in the same spot and they sandwich the gif. Thanks very much.
Thanks Rita. I’m glad this article was helpful.
With the 3 images it depends a little on what else is in the design as to how I would approach it. What you’ll want to do first is set position: relative on the container for all 3 images. That way when you position any of the images it will be relative to the container.
The second and third images you do want to position and you would give them different z-indexes so one sits on top of the other. With the first image (the bottom image) it depends on where you want other elements on the page to be located.
By positioning the images you take them out of the document flow, meaning other elements will respond as though the images aren’t on the page. They might position themselves exactly where the images are located, hiding one of the other.
What I’d probably do with the first image is leave it as a normal image without positioning or floating. I’m assuming you can place it where you want without doing either. This way text and other elements will flow around the first image. It’s possible you’ll also need to add some margin to the image to account for the location of the other 2 images.
I hope that makes sense and helps.
Hey, thx for your great article!
However I have one concern:
Position and float do appear to make sense sometimes! I used this technic on my test website http://www.4front-tech.tk (the “extra progressive” one).
Now I do need position:relative for my logo because otherwise the stretches to the whole width. I also need float:left to keep the logo on the left.
How can you explain this?
To test it out just try editing #logo in css on the website I provided a link to.
Sorry I didn’t reply sooner. I’m not sure why you would need both the way you describe. position: relative shouldn’t have anything to do with stretching or not stretching the image.
I’m not sure if you’ve gotten this working between the time you left your comment and now. I tried removing the positioning and seeing what happened, but I didn’t notice a change in the logo.
I do see how removing the positioning affects the hover image. Is that the issue?
Hi, I can’t believe it’s already two years since I asked that question, but only now I saw that you’ve eventually answered. I could swear the notification mail about an followup comment has never reached me…
For the sake of the truth though, I have still made the effort to reproduce my former issue. My investigations might have the potential revolutionize the web, since I have indeed found a use case where the position property and the float property can be used simultaneously (and making total sense!).
Further I accuse your claims as being false, blasphemous and outdated knowledge.
You may take an insight into my results by clicking this link -> https://jsfiddle.net/0kcfgh1r/1/
What do you think of it? 😀
I’m not sure why you didn’t get an update, but somehow you still found your way here.
I don’t remember if it was the case back in 2009, but I know now that you can have both floats and positioning set. It probably was the case in 2009 too and I was incorrect thinking you couldn’t use both.
I do use both at times now too, usually because I need position: relative set for a child element.
Thanks for your response! Glad we could finally clarify the situation! 🙂
Great article! It helped out a lot. Thank you for that!
Thanks Boryana. Glad I could help.
This article might be a few years old, but it’s still very much relevant.
Thank you for clearing up a bit of my confusion 🙂
Thanks Shawn. I’m glad the article was helpful and could clear up some confusion.
Could you please help me as I am working on making a website accessibility.
The task is Absolute CSS positioning can make pages unreadable when style sheets are turned off.
Could you please let me absolute can be changed to relative.
Hi Kalai. Changing things to relative isn’t going to make things more accessible. There’s no reason why absolutely positioned elements can’t be accessible. If you turn your stylesheets off then it shouldn’t make a difference which you use, because neither would be working.
It’s possible some of your elements should be positioned relatively instead of absolutely, but it’s not likely an accessibility thing. It’s hard to tell you what the problem is though, without being able to see the site.
it will be great if you can illustrate where is the size of the box located in your illustrative diagram. Is it the line between padding & border….where you have an arrow point it as “padding edge”.
Just to clarify, the image at the top of this post isn’t mine. It’s from the W3C. The width for the box would be border to border. Everything other than margin is included in the width (or height) That’s how the standard has always set widths.
That’s why when you change padding or border the overall size of box changes. IE uses a different model where width specifically means width of the content box. While technically the wrong model, it’s actually a better model.
If you set box-sizing in your css you can flip things to use the IE model which is a lot easier to work with and just more intuitive. It looks like this
* box-sizing: border-box;
I use it now on every project
Thanks for this!!
Question– I’m new to CSS and just used absolute positioning on several elements on my page… I see you prefer floats to positioning (and hope I can figure this out soon!)– if I have it working correctly in this case, are there other non-obvious reasons why I should re-do the layout to use floats?
Thanks Angela. There’s nothing wrong with using positioning. I use it too. What I was referring to was the overall layout. I think positioning sometimes throws people off a little when used for the overall layout and think a float driven layout tends to be easier to work with.
Especially when you’re first working with them I think people can get confused about what absolute and relative positioning really do.
That doesn’t mean you can’t use positioning for several elements or that you can’t use it for an entire layout. I think you definitely can. If you’ve made it work then I wouldn’t switch because I offered a preference. I simply think positioning can trip people up at first because it doesn’t quite behave as you might initially expect.
You’re explanation is wonderfull! Thanks a lot, it made me learn what I was procrastinating to study for a long time…
Thanks Thiago. Glad I could help and give you a kick in the pants to get you stop procrastinating. 🙂
It helped me to understand positioning better. I was earier having difficulty in understanding this and i came across your site 🙂 thank you 🙂
A really clear and concise explanation. Very helpful.
Thanks heaps for this, I’ve discovered another item for the ‘Positioning Issues’ section.
4. Fixed elements no longer inherit widths
This causes issues with say a fixed subnav that needs to inherit the width and padding of a page (i.e. when max-width is set). Still haven’t figured out a way to do it!
Getting around this requires additional divs. Apply positioning to a wrapper div, then set page width, margins and centring on the inner div. Cheers
Thanks steven. U have helped me a lot.
relative positioning, I can’t believe it’s not margin.