What happens when your main content area needs two specific background colors: one for the primary content, and another for the sidebar? If you've ever tried applying the background to each container itself, you'll no doubt have realized that your layout quickly becomes fragmented as soon as, say, the primary content section exceeds the height of the sidebar.
Generally, the solution is to set a background image on the parent element, and set it to repeat vertically. However, if we get clever with CSS3 gradients, we can achieve the same effect with zero images. The irony in this is that we're using CSS3 gradients to create an effect that doesn't contain a gradient! Read on to learn more.
Prefer a Video Tutorial?
Step 1. Construction
Let's begin by building a ridiculously simple layout. That way, we can demonstrate a common layout issue that we've all experienced at one point or another.
Create a new HTML document, and add the following to your body
tag:
<body> <header> <h1> My Header </h1> </header> <div id="main"> <div id="primary">Primary content.</div> <aside> Sidebar </aside> </div> </body>
Don't forget that you can use the
body
element as a wrapper for your layout. Simply set awidth
directly to thebody
.
What we have here is fairly common. A header
element contains a heading tag; and, then we have a main
div, which houses the primary content, as well as the sidebar
.
Step 2. Create the Columns
Next, let's style this layout a bit. As we're using the body
element as our wrapper, of sorts, let's set a width
and background color.
body { width: 700px; margin: auto; background: #e3e3e3; }
Now, we'll float the primary content and the sidebar
to the left and right, respectively. Also, as we're not working with any real content, we'll set a height to each container to present the illusion of content. This itself won't be enough; we must also specify precisely how wide each should be. Otherwise, they'll take up all of the available space, due to their block
nature.
#primary { float: left; width: 75%; height: 500px; background: red; } aside { display: block; /* Because is HTML5 element */ float: right; width: 25%; height: 500px; background: green; }
Step 3. The Rub
So, all this looks just fine -- for now. However, issues arise as soon as the height of the primary content exceeds the height of the sidebar
. Further, this will typically be the case in most situations.
To simulate added content, let's increase the height of the #primary
div
to be 700px
.
Typically, the solution to these types of dilemmas is to apply a background image to the parent (#main
) element. This will usually be a small slice of the background, which will then be vertically repeated.
#main { ... background: url(small/slice/of/background.png) repeat-y; }
Problem solved! Well, not exactly. True, this does work, however, as soon as you decide to change a background color, you're then forced to return to Photoshop to create a new background image. What a drag!
Another common solution is to use JavaScript to dynamically detect the width of each container, and then make them the same height. Keep in mind that this then requires your layout to be dependent upon JS being enabled.
Step 4. The Solution
If we want to be forward thinkers, we can use CSS3 gradients to achieve this effect. What is that you say? "But Jeff, these are solid colors; not gradients!" True, but I'll show you a little trick I learned. If you create two stops at the same location in a CSS3 gradient, you'll end up with two solid colors. That's a bit confusing; let me demonstrate.
Before we continue, if you're working along, return to your project, and remove the background colors. They're no longer needed. Now, we'll add a background gradient to the parent, #main
, container instead.
#main { background: -moz-linear-gradient(left, red, green); }
So, that's probably what you were expecting. But how will that help us? We need a distinct separation between the primary content and the sidebar
.
This time, let's specify that both the red and the green color-stops should be placed at the 75% marker.
#main { background: -moz-linear-gradient(left, red 75%, green 75%); }
Isn't that awesome? Not only are we using a gradient to create solid colors, ironically, but, also, the heights of each child container are now identical.
Keep in mind that this isn't entirely accurate. They have the illusion of being the same height. In truth, though, we're only applying a background to the parent element. The sidebar
is still shorter; you just can't tell.
Step 5. Webkit
The final step is to make Webkit browsers (Safari and Chrome) happy. Unfortunately, they don't quite agree with Mozilla on the correct syntax for creating gradients. Their method isn't quite as succinct as Mozilla's.
#main { background: -moz-linear-gradient(left, red 75%, green 75%); background: -webkit-gradient(linear, left top, right top, from(red), color-stop(.75, red), color-stop(.75, green)); }
If you're used to the
from()
andto()
functions, keep in mind that they're simply helper functions, which direct tocolor-stop()
.
color-stop
accepts two parameters:
- The position to stop
- The desired color
To clarify, color-stop(.75, green)
means, "at 75% of the width of the element, the color should now be green." So yes, the syntax is different, but it only takes a few seconds to convert.
Conclusion
That's all there is to it! Please remember that these are CSS3 techniques, meaning, IE is left out in the cold. Keep in mind, though: "not all websites must look identical in every browser."
What do you think? Will you use this method, knowing that you'll have to provide a fallback color for IE, or resort to using conditional statements to use a fallback image?
Comments