- A Common Approach
- Why It's Not Bulletproof
- A Bulletproof Approach
- Why It's Bulletproof
- Another Example of Expanding
- Summary
A Bulletproof Approach
To bulletproof the design of the rows, we first have to settle on a markup structure. We then add color, positioning, and background images. In the end, we have a flexible end product, capable of accommodating any text size or amount of content. We begin with the markup, reducing that code bloat we mentioned earlier.
THE MARKUP STRUCTURE
To structure these two rows, we must look at the content within them. What elements would make best sense for this scenario? What elements would be the most meaningful? When writing markup from scratch, I like to answer these questions first, and then apply the best structure for the job. There may very well be more than one answer, but it's important to ask yourself these questions before you type your first character.
In this case, we'll need two containing elements, one for each row. For the top row, I see the two bits of text at each end as items of a list, while on the second row, there's just one paragraph of text.
That said, let's write out the complete markup structure we'll need to make this design happen:
<ul> <li>Not registered? <a href="/register/">Register</a> now!</li> <li><a href="/find/">Find a store</a></li> </ul> <div> <p><strong>Special this week:</strong> $2 shipping on all orders! <a href="/special /">LEARN MORE</a></p> </div>
So, we have a list of two items for the top row, and a containing <div> wrapped around a single paragraph for the second. Nice and simple, very lean markup—and best of all we've already tossed out the code bloat associated with the nested-table approach.
In addition, we've achieved our goal of increased accessibility to the content. Regardless of the device or software reading it, these two rows of information will always be interpreted as a list followed by paragraph. And that's exactly what they are.
IDENTIFYING THE PIECES
Our next step is to uniquely identify all the elements that we need to assign styles to. Assigning a few ids will enable us to apply positioning, color, and images to turn this simple markup into the finished design.
<ul id="register"> <li id="reg">Not registered? <a href="/register/">Register</a> now!</li> <li id="find"><a href="/find/">Find a store</a></li> </ul> <div id="message"> <p><strong>Special this week:</strong> $2 shipping on all orders! <a href="/special /">LEARN MORE</a></p> </div>
We've just added unique ids to the list and each of its items, as well as the second row's containing <div>. These style hooks will be important in just a moment.
SANS STYLE
Figure 3.4 is what our markup structure looks like in a browser, with just some basic font styling applied (The Best Store Ever uses the Arial typeface throughout).
Figure 3.4 This is an unstyled view of our bulletproof markup; it's easily read and understood by any device that happens to access it.
On the <body> element we've also assigned a base font size using the keyword value of small.
body { font-family: Arial, sans-serif; font-size: small; }
A phone, PDA, or browser that doesn't support CSS would render the rows this way. The result is still very readable and easily understood by any device accessing it. Now it's time to start applying style.
ADDING BACKGROUND
To begin adding style, let's first add the background color to each row. This step will help us define the dimensions.
#register { background: #BDDB62; } #message { background: #92B91C; }
The results of adding the correct background color to each row are revealed in Figure 3.5.
Figure 3.5 Adding background colors first helps us visually define the rows as we add the rest of the pieces.
POSITIONING THE CONTENT
Next, let's position the content, placing the two list items of the top row at either end and the $2 shipping message in the center of the bottom row. Figure 3.6 shows the results of applying the following CSS:
#register { margin: 0; padding: 0; list-style: none; background: #BDDB62; } #reg { float: left; margin: 0; padding: 8px 14px; } #find { float: right; margin: 0; padding: 8px 14px; } #message { clear: both; text-align: center; background: #92B91C; }
Figure 3.6 We've positioned each list item on either end of the top row.
From top to bottom, we've eliminated default margins and padding from the #register list. Also, we've prevented bullets from appearing by using the list-style: none; rule.
Next, we've used the opposing floats method for positioning the two list items at either end of the row. The first list item is floated left (#reg), while the second item is floated right (#find). Doing this enables us to align each item at an equal horizontal location yet at opposing ends of the row (Figure 3.7).
Figure 3.7 The "opposing floats" method is a handy way of aligning content on either side of a container.
This method of floating elements against each other is a handy way of placing content at opposite ends of a containing element.
Looking again at the new styles we've added, in addition to floating each list element we've added some padding on all sides of each item. There will also be enough space to drop in the magnifying glass icon on the left of the "Find a store" link a bit later.
As for the bottom row, we've added a clear: both; rule, which clears the floats we've added to the row above it. And, to center the text, we're using the text-align: center; rule.
MISSING BACKGROUND
Where did the background color on the top row go? You may recall that we ran into a similar problem in Chapter 2. When we float inner elements (in this case the two <li>s), we're taking them out of the normal flow of the document. So, for the <ul> that wraps around them, it's as if the list items don't really exist. As a result, the <ul> doesn't know how tall and wide to stretch the background color behind itself.
To fix this problem, let's float the <ul> along with the list items (just as we did with the tabs in Chapter 2). In addition, we need to assign a width to make sure the row flows across the entire, intended width. It seems that most browsers have interpreted the CSS2.0 spec quite literally in that "a floated box must have an explicit width" (www.w3.org/TR/REC-CSS2/visuren.html#floats). If we don't specify a width here, the row will only be as wide as the contents force it to be (in this case, the two lines of text).
#register { float: left; width: 100%; margin: 0; padding: 0; list-style: none; background: #BDDB62; } #reg { float: left; margin: 0; padding: 8px 14px; } #find { float: right; margin: 0; padding: 8px 14px; } #message { clear: both; text-align: center; background: #92B91C; }
Figure 3.8 shows the rows so far, with the background color of the top row now restored.
Figure 3.8 When floating items inside a container that is filling in the background, restore that background by floating the container as well.
ADDING THE DETAILS
We're now left with adding the details that complete the design of these rows. Let's start with the top row and fill in the rounded corners that appear at the bottom edges of each end (Figure 3.9).
Figure 3.9 The rounded corner is really a few white pixels in a step pattern, attached to each corner of the row.
You'll notice that the rounded corner is nothing more than a few white pixels placed in a step pattern. When viewed at a normal distance (rather than zoomed, as it is in Figure 3.9), it creates the illusion that the row is rounded off at each end.
Chopping off pixels to create this rounded illusion is a great trick—and one that's easy to implement using a combination of the smallest image possible with a background color specified in the CSS.
We'll start by creating the image in Photoshop (or your favorite image editor). Because we're dealing with a fixed-width (768 pixels), we can create a single image that contains both the left and right corners. We can then reference this image as a background in our CSS.
Figure 3.10 shows a close-up view of the image we created. What you're seeing here is the left end of an image that is 768 pixels wide (the same width that our rows will be). For each end, we created this step pattern with the Pencil tool set to 1px using the color white (the same color as the page background). The rest of the image is transparent (shown by the checkerboard pattern in Photoshop). The white portions of this image will be laid on top of the background color that we've already specified in our CSS. This will create the illusion that the row's ends have been rounded off a few pixels.
Figure 3.10 This is one end of the 768-pixel-wide GIF (zoomed at 1600%).
Looking back at our declaration for #register (the containing <ul>), we add the following rule:
#register { float: left; width: 100%; margin: 0; padding: 0; list-style: none; background: #BDDB62 url(img/reg_bottom.gif) no-repeat bottom left; }
We've just specified a background color and then set the image on top of it, set it to not repeat, and aligning it at the bottom and left. Transparent portions of the image will let the background color show through, while the white corners will obscure it. Aligning the image at the bottom ensures that no matter how tall the row needs to be (due to varying text sizes or amounts of content) the corners will always be in the right place (Figure 3.11).
Figure 3.11 A 3D view of the stacking order.
Figure 3.12 shows the results, with the rounded corners now showing at the bottom of the top row.
Figure 3.12 The background color and the white and transparent portions of the image work together to create the illusion of rounded corners.
FOUR ROUNDED CORNERS
For the second row, we need a way to apply rounded corners on both the top and bottom, all the while keeping the row vertically expandable. To accomplish this, we'll use two background images. One of them will be the same image we used for the bottom of the top row; the other (for the top edge) will be the same image again but turned upside-down. Because we need two background images, we also need two elements to assign them to. (Oh, how I wish we could assign more than one background image to a single element. One can dream.)
Lucky for us, we do have two elements to take advantage of. Notice that in the markup for the second row we have a containing <div> with a <p> inside for the content within:
<div id="message"> <p><strong>Special this week:</strong> $2 shipping on all orders! <a href="/special/">LEARN MORE</a></p> </div>
Let's now assign each of our background images to each of these elements. The inverted version of our white corner graphic will be assigned to #message, while an identical image used in the top row will be assigned to the bottom of the <p>:
#message { clear: both; text-align: center; background: #CE6500 url(img/mess_top.gif) no-repeat top left; } #message p { margin: 0; padding: 8px 14px; background: url(img/reg_bottom.gif) no-repeat bottom left; }
By assigning the top corners to #message (the outer <div>) and the bottom corners to the bottom edge of the <p> (Figure 3.13), we're ensuring that all four corners will stay positioned correctly no matter how large or small the text is within the paragraph. If we incorporate a larger text size or amount of text, the top corners will always be aligned top, and the bottom corners will always stay at the bottom of the paragraph (as we'll see in just a minute).
Figure 3.13 For the bottom row, we use two images, letting the green background show through the transparent areas of the GIF.
Figure 3.14 shows the results of these declarations. As we did with the top row, we're using the transparent images that let the background color show through, with white corners masking only those four areas.
Figure 3.14 With backgrounds added, the rows are starting to take shape.
TEXT AND LINK DETAILS
We have just a few more styles to add to complete the design: link and text colors. We also need to add back in the arrow graphics that flank the "Find a store" and "LEARN MORE" links. Let's get to it.
First, let's define link and text colors for each row, adding the necessary rules to all of the styles we've declared thus far:
#register { float: left; width: 100%; margin: 0; padding: 0; list-style: none; color: #690; background: #BDDB62 url(img/reg_bottom.gif) no-repeat bottom left; } #register a { text-decoration: none; color: #360; } #reg { float: left; margin: 0; padding: 8px 14px; } #find { float: right; margin: 0; padding: 8px 14px; } #message { clear: both; font-weight: bold; font-size: 110%; color: #fff; text-align: center; background: #92B91C url(img/mess_top.gif) no-repeat top left; } #message p { margin: 0; padding: 8px 14px; background: url(img/reg_bottom.gif) no-repeat bottom left; } #message strong { text-transform: uppercase; } #message a { margin: 0 0 0 6px; padding: 2px 15px; text-decoration: none; font-weight: normal; color: #fff; }
We've set link colors for each of the items in the #register row, as well as default font-size and color for the text and link in the #message row (Figure 3.15).
Figure 3.15 The rows, with link and text color styles added. Notice the space allotted for the small icons that will sit to the left of "Find a store" and "LEARN MORE."
Previously, we had emphasized the "Special this week:" text using the <strong> element. We took advantage of that by using the text- transform property to change that portion of the message to uppercase.
THE FINAL STEP
Our last step in bulletproofing the rows is to add the graphics that flank the "Find a store" and "LEARN MORE" links. We could add these images to the markup, but to make things easier to update later, and to keep nonessential images out of the document structure, we can easily add them as background images in the CSS.
First let's add the magnifying glass icon to the list in the top row, aligning it 0
50%, which will position it left and 50% from the top (centering it vertically):
#find { float: right; margin: 0; padding: 8px 14px; background: url(img/mag-glass.gif) no-repeat 0 50%; }
Figure 3.16 shows the results of adding the icon to the "Find a store" list item in the top row.
Figure 3.16 The background image sits to the left of the list item, where padding was previously specified.
And finally, let's add the arrow graphic that sits just in front of the "LEARN MORE" link in the second row. Once again, we'll position it 0 50%, or all the way left and halfway down (to center vertically):
#message a { margin: 0 0 0 6px; padding: 2px 15px; text-decoration: none; font-weight: normal; color: #fff; background: url(img/arrow.gif) no-repeat 0 50%; }
Figure 3.17 shows the results of adding the arrow icon to the left of the "LEARN MORE" link by targeting the <a> element that lives within the message row.
Figure 3.17 As we did with the top row, we added the arrow to the left of the "LEARN MORE" text, this time attaching it to the <a> element.
Figure 3.18 shows the final results with all the pieces in place. Visually, we're left with a set of rows almost identical to those found at The Best Store Ever, but the underlying markup structure, along with the measures we've taken to strategically place backgrounds and text, makes it bulletproof. Let's find out why.
Figure 3.18 This is the final, bulletproof version of the rows.