CSS TUTORIAL 14 – POSITIONING PAGE ELEMENTS
This exercise lets you explore a few different ways to use absolute positioning - like creating a three-column layout, positioning items within a banner and adding captions on top of photos.
Enhancing a Page Banner
Firstly, you will make some small but visually important changes to a page banner. You will create styles that refer to HTML tags with IDs or classes already applied to them.
Open the positioning/index.html file in your HTML editor.
This page has a banner, navigation bar, main story area, sidebar links and ads - but there is not much visual structure. There is just normal, static HTML with everything running from top to bottom of the page. You can make it more readable by organizing the contents into columns.
On this CosmoFarmer.com web page, start by repositioning several parts of the banner.
In the <head> region of the HTML, place your cursor between the opening and closing <style> tags.
There is already an external style sheet attached to the page, with some basic formatting. You will add the styles to the internal style sheet.
Start by moving the small CosmoFarmer 2.0 badge to the left side of the banner. To help break up the ‘boxy’ look that is typical of CSS designs, break this graphic out of the banner's borders - so it looks like a ‘slapped-on’ sticker.
Add a new internal style:
<style type="text/css">
#banner #badge {
position: absolute;
left: -18px;
top: -18px;
}
</style>
The graphic is inside a <div> with an ID of banner, and the graphic itself has an ID of badge. This style positions the top left corner of the graphic 18 pixels to the left and 18 pixels above the top of the page.
Preview the page now and you will see a couple of problems. First, the graphic hangs off the edge of the page but you really want it to hang off the edge of the banner area.
You will tackle that problem now.
Add this style above the one you just created:
#banner {
position: relative;
}
It is good practice to place the CSS code for styles that control a general section of a page (like this #banner style) above the code for styles that format just parts of that section. Also, grouping styles for related sections makes it easier to find styles when you need to analyze or edit a page's CSS. In this case, the #banner style goes first in the internal style sheet because it applies to a large chunk of HTML. However, you should keep the #banner #badge style near it as you add more styles to the page.
The #banner style creates a new positioning context for any nested tags. In other words, the relative setting makes any other positioned elements inside this tag place themselves relative to the edges of the banner. This change in positioning shifts the placement of the style you created earlier. Now the graphic is 18 pixels above and to the left of the banner box. The badge still hangs off the page just a little bit, so you will add some margins around the page to accommodate the graphic.
Add a style for the body tag. Place it in the internal style sheet above the other two styles you created:
body {
margin: 20px;
}
This margin adds enough space around the edges of the page so the entire graphic is visible. However, now you have another problem - the CosmoFarmer logo is partially hidden underneath the badge. Overlapping elements is one of the hazards of absolute positioning. In this case, you can fix the problem by adding a little margin to the logo.
Add a new style for the logo to the internal style sheet. Place it below the other styles you have created so far:
#banner #logo {
margin-left: 60px;
}
Like the badge graphic, the logo already has an ID applied to it - logo. This style moves the logo far enough to the left so that it is out of the way of the absolutely positioned graphic. However, a strange thing may happen if you view this in Internet Explorer (including IE 7). When you mouse over the navigation bar, the logo may jump back to where it was before. Fortunately, the problem is easily fixed.
Edit the #banner #logo style you just created by changing its positioning to relative:
#banner #logo {
margin-left: 60px;
position: relative;
}
Adding relative positioning does not actually move the logo. That would happen only if you added a left, top, right or bottom value. This is, of course, another example of an IE ‘bug’.
The two links - Subscribe and About Us - look awkward sandwiched between the logo and the navigation bar. There is plenty of space in the right side of the banner, so you will move them there. The links are actually an unordered list that gets its formatting from the page's external style sheet.
Add this new style to the bottom of the internal style sheet:
#banner ul {
position: absolute;
right: 60px;
bottom: 5px;
}
This style is a descendent selector that targets unordered lists inside the banner. Since the <ul> is absolutely positioned, it is removed from the flow of the page, letting the navigation bar move up just under the banner.
Also, remember this tag is inside the banner, which you earlier set to a relative position. Accordingly, the Subscribe and About Us links are positioned relative to the banner tag. They are placed an exact amount from the right and bottom edges of the banner.
However, IE 6 has problems positioning elements using the bottom coordinates of relatively positioned elements (like this banner). It ends up using the bottom coordinates of the entire page. Luckily, the fix is easy.
Add an IE-only style below the #banner style you created earlier:
* html #banner {
height: 1px;
}
This style uses the * html hack to create a style that only Internet Explorer 6 and earlier pay attention to. It is really just nonsense code - but in IE 6, it fixes the problem.
Preview the page in a web browser.
This exercise is a good example of using absolute positioning to achieve small, subtle changes that add a lot to a page's visual appeal.
Adding a Caption to a Photo
Earlier you learned one way to add a caption to a photo. In that example the captions were positioned underneath the photos - which is what you want most of the time. However, you may want to add a caption directly onto a photo.
Open the positioning/index.html file in your HTML editor.
Notice the graphic of the original CosmoFarmer home page. Currently it is aligned to the right using the align attribute of the <img> tag. You will align it using CSS instead, but first you need to edit the HTML.
Locate the <img> tag that inserts the graphic old_home.jpg, and then delete the HTML code align="right".
Here is what the entire tag looks like. You want to remove the part that is bold:
<img src="images/old_home.jpg" alt="The Original Cosmo Home Page" width="200" height="186" align="right" />
Now, you need to create a container (a <div> tag) in order to be able to implement CSS for both the image and its caption.
Immediately before the <img> tag, add <div class="figure">. After the closing </p> of the caption, add the closing </div>. The HTML should look like this:
<div class="figure">
<img src="images/old_home.jpg" alt="The Original Cosmo Home Page" width="200" height="186"/>
<p>The Original CosmoFarmer Home Page</p>
</div>
Create a style to format the newly added <div>:
#main .figure {
float: right;
width: 200px;
margin-bottom: 2px;
margin-left: 10px;
}
This style aligns the box to the right edge of the page, and the bottom and left margins add a little space between the photo box and the text that wraps around it.
The plan is to move the caption paragraph out of the normal flow of the page and place it on top of the photo. To do so, you will position the caption relative to the edges of the photo. (However, since the <img> tag is self-closing (meaning it does not have both an opening and closing tag), you must position the caption relative to another element.) Here is another use of the figure <div> - to provide the positioning context for the caption.
Add position: relative to the style you just created:
#main .figure {
float: right;
width: 200px;
margin-bottom: 2px;
margin-left: 10px;
position: relative;
}
Now you can position the caption relative to the <div>, which for all intents and purposes is the same as positioning it relative to the photo.
Add a new style after the #main.figure style you created in the last step:
#main .figure p {
position: absolute;
width: 168px;
left: 10px;
bottom: 10px;
background-color: #FFF;
}
This new style positions the paragraph 10 pixels from the bottom and 10 pixels from the left edge of the <div> tag. The width property constrains the paragraph so it does not span across the entire photo, and background-color makes the text legible.
All that is left are a few formatting details to improve the look of the caption.
Edit the style you just created, so that it looks like this:
#main .figure p {
position: absolute;
width: 168px;
left: 10px;
bottom: 10px;
background-color: #FFF;
border: 1px dashed #666666;
font-size: 1.1em;
font-weight: bold;
text-align: center;
padding: 5px;
margin: 0;
}
You need to attend to one small detail. It is something you may never notice, but some browsers position the caption just a few pixels lower than other browsers. To see for yourself, check the page in IE and then in Firefox. Browsers position inline elements (like images) differently relative to the baseline of other elements around them. At any rate, the fix is simple. Using CSS, force the image to display as a block-level element.
Add one more style to the internal style sheet:
#main .figure img {
display: block;
}
Preview the page in your web browser. The caption should appear centered across the lower portion of the photo.
Laying Out the Page
Now it is time to turn your attention to the structure of this page. As it is now, you need to scroll down the page to read the latest news in the sidebar, and scroll even farther to see the ads. In this section, you will use absolute positioning to create a three-column flexible layout that brings all content up to the top of the page.
Before you get started, you should examine the overall structure of the page. Each section of the page is wrapped in its own <div> tag, with an appropriate ID applied. The page's main contents, sidebar, ads and copyright notice are also enclosed in a <div> with the ID contentWrapper. All of the tags in the page's body are wrapped in a <div> with an ID of wrapper. That may seem like a lot of <div> tags, but they each serve an important purpose.
Your mission is to arrange the three <divs> (sidebar, main and adverts) into three columns. You need to use absolute positioning on only two elements - the sidebar and the advertising section. You will take them out of the normal flow of the page (where they appear near the bottom) and position them at the left and right edges of the page just below the banner. Absolute positioning also causes those elements to float above the page, and on top of the main content area. To make room for the sidebars, you have to add a little margin to the left and right of the main area.
Create a style for the <div> tag that encloses the main contents of the page. Add it as the last style in the internal style sheet:
#contentWrapper {
clear: both;
position: relative;
}
The clear property helps the #contentWrapper clear the navigation bar, which was created using a left float. You should always clear elements that need to appear under a float.
The position property comes in handy for placing the sidebars. Setting its value to relative lets you position both sidebars relative to the four edges of the content wrapper, not the four edges of the browser window.
Create a style for the left sidebar, placing the CSS code under the style you have just created:
#sidebar {
position: absolute;
}
This style takes the sidebar out of the normal flow of the page, but it does not yet position it anywhere. It is still near the bottom of the page, but if you view it in a browser, you will see it is floating on top of the advertisements. To position it, use the top and left properties.
Add top and left properties to the style you just created by:
#sidebar {
position: absolute;
top: 15px;
left: 0;
}
Since this sidebar is positioned relative to the content wrapper <div>, a left position of 0 places it flush with the left edge. The top value is determined by trial and error. A top value of 0 would make the sidebar touch the bottom of the navigation bar - the 15 pixels of space bring the sidebar's top more in line with the story headline.
One thing is missing! Most of the time when you position something, you also want to give it a width. That is true in this case, since at this point the sidebar spreads almost across the entire page, covering nearly all of the content.
Add a width to the #sidebar style.
#sidebar {
position: absolute;
top: 15px;
left: 0;
width: 170px;
}