Download these files and edit “style.css” as you go through this tutorial: CSSpositioningTutorial
“style-middle.css” and “style-final.css” are included in case you get lost during the tutorial.
In the html you can see we have a bunch of divs here – a header and footer, a main section (div-1) with 3 divs inside it (div-1a, div-1b, div-1c). In the stylesheet div-1 has a padding of 10px so you can see more clearly that 1a, 1b, and 1c are inside it. All of these are contained inside a container div with a dashed red line to remind you it’s there. The container has auto left+right margins to center it horizontally on the page. The <p> element, which is used for all text on this page, has margins set to 0 and a small padding to create some breathing space around the text.
- Notice the width of the main div (div-1) is 400 pixels, with a padding of 10px. The width property of an element is *only* for the content, its total actual width is the content + padding + border + margin. In this case a padding on all sides of 10px makes the total width 400+10+10 = 420px. Notice the width of the container is 420px for this reason. Make the container width 400px and you’ll see div-1 stick out over the right edge even though its width at first glance seems to be the same, so change it back to 420px.
- Increase the <p> padding to 0.5em (i.e. 50% of the width of an “m” character). Notice the width of the divs do not change. That’s because the <p> is inside the content box of the div, so creating more padding just pushes the text into a smaller area. The height of the divs does change, however, because we have not specified that property, so the divs expand automatically to fit whatever’s inside them. The <p> element has a vertical margin by default because it was designed for paragraphs of text. We are specifying a margin of 0 to overwrite that, but try deleting the margin: 0 property and you can see the gaps appear between all the blocks.
-
POSITIONING
The default positioning for all elements is position: static, which means the element is not positioned and appears wherever the HTML and browser renders it. Normally you don’t specify this unless you need to override some other positioning. I put in this property for div-1, but if you delete it you’ll see nothing changes.
An element with position: fixed is positioned relative to the edges of the browser window, it will not move even if the window is resized or scrolled. The properties top, bottom, left, and right specify how far from those edges to position the element.
-
Add position: fixed and bottom: 10px to the div-footer ID. Note that the color properties are set for both div-header and div-footer at the same time for efficiency, you can specify more properties for div-footer and those color properties are retained (they “cascade”).
#div-header, #div-footer { background-color: grey; color: black; } #div-footer { position: fixed; bottom: 10px; }Now resize and/or scroll the window – the footer block is always fixed in relation to the window, 10 pixels from the bottom. If you shrink the window up a lot you can see it also appears on top of the other divs because it appears after them in the HTML. It doesn’t matter where its style is defined in the css, just the order it’s put on the page by the HTML. (You can control layering order with z-index – http://www.w3schools.com/Css/pr_pos_z-index.asp.)
Notice the div-footer block got a lot smaller when we made its position fixed. This is because it used to be inside the container div, and by default its width is 100% of the element enclosing it. When its position is fixed, its width is only the width of its content (plus padding etc.).
Add width: 420px to the div-footer and it will line up nicely with the container div.
-
Position: relative moves an element from its normal position, but all other elements stay where they are as if nothing was different. Move div-1a over a bit by adding these properties (remember that left: 30px means 30px away from the left):
#div-1a { position: relative; left: 30px; top: 30px; background-color: orange; color: #fff; }You can see the other divs did not move, and a space is left where div-1a would normally be. This type of positioning is rarely used to place elements. However it is often specified as a container for absolutely positioned elements, which we’ll see next.
-
Position: absolute makes an element move to a specific spot in its containing element (its first “parent” element). The containing element must have a position besides static. If there is no such element, the containing block is <html>.
Change div-1a to position: absolute. Even though it is inside div-1, which is inside container, div-1a moves relative to the entire html block – because both div-1 and container have position: static. Also div-1b and div-1c move up to take the space vacated. (This is similar to position: fixed, except fixed means no matter what the position of various enclosing divs, the element will always be absolutely relative to the browser window.) Now change div-1 to position: relative. You should see div-1a positioned relative to div-1.
At this point your CSS should look like “style-middle.css.”
- The terminology is a bit confusing since div-1a is called absolute yet it’s relative to div-1. The structure of a containing div with position: relative and enclosed divs with position: absolute is very common in css layout. To reinforce the concept that a div with position: absolute is relative to its first parent element with non-static position, change div-1 back to position: static, and then make the container div position: relative. You will see div-1a is now relative to container, not to div-1.
-
Let’s make a 2-column layout using these principles. First remove the footer’s fixed position, delete the additional div-footer selector (position, bottom, and width). To fit the columns side by side, set both div-1a and div-1b width to 200px, make both position: absolute, with div-1a 0px from the right, and div-1b 0px from the left.
#div-1a { position: absolute; right: 0px; top: 0px; width: 200px; background-color: orange; color: #fff; } #div-1b { position: absolute; left: 0px; top: 0px; width: 200px; background-color: green; color: #fff; }First of all, note that by using absolute positioning we can move div-1b “before” div-1a if we want to, its order in the HTML doesn’t matter. Second of all note that their position is relative to the entire enclosing div-1, so the div-1 padding is irrelevant. To make the columns line up next to each other and leave space for the padding, change the right, top, and left, top properties to 10px. Now change them all back to 0px and set width: 210px. They are again aligned with div-1 edges, and they fill the padding gap in the middle.
-
What happened to div-1c and the footer? They’re covered up by the other divs. One solution to this is to specify a fixed height for the enclosing div. Add height: 200px to div-1. We can see the footer again, but div-1c is still obscured. Fixed height is usually not good design because we don’t want to have to know exactly how much text will be in each element, or what size the fonts are. Fixed height can be a good solution for image layouts, however, or anything with precisely known dimensions.
Instead we will use float. Float pushes an element as far as possible to the right or left, and allows text to wrap around it. Float is horizontal only, not up or down. An element is floated within its containing element, not the whole page. It’s often used for images but can be used for general layout too. If you place multiple floating elements after each other, they will float next to each other – if there’s enough room. See an image gallery example here: http://www.w3schools.com/Css/tryit.asp?filename=trycss_float_elements.
-
Delete the position properties for both div-1a and div-1b, and delete the fixed width of div-1b. Then set div-1a to float: left.
#div-1a { float: left; width: 200px; background-color: orange; color: #fff; } #div-1b { background-color: green; color: #fff; }Now div-1a is floated as far as possible to the left of its containing div-1, and the text of div-1b wraps around it. (Notice the <p> text padding of 0.5em only applies to edges of div-1b, which haven’t changed even though div-1a is on top of it – only the text is wrapped, so it sits right next to the edge of div-1a.)
-
Set div-1b to float: left and width: 200px. Now we have a 2-column layout again, although div-1c is filling the space below div-1a and to the left of div-1b. The text of div-1c wraps around div-1b but the block itself moves to the open space. Set both div-1a and div-1b to width: 150px and you will see div-1c move to the open space on the same row and shrink to the remaining available width.
We can stop floating using the clear property. Clear specifies on which sides of an element other floating elements are not allowed – left, right, both, or the default none.
Set div-1c to clear: both. It moves below div-1a and div-1b despite their floating properties and fills the available width again. Then set the width of div-1a and div-1b back to 200px. You should have a nice clean layout. Your CSS should now look like “style-final.css.”
- Start playing around! Change this file around and see what you can do. Experiment with your own layouts. Refer to the CSS reference links to control your design more specifically.
Here are a bunch of CSS layouts to study and/or borrow from, including lots of faux column layouts: http://www.code-sucks.com/css%20layouts/.
Comments
Leave a comment Trackback