Video icon 64
Learning to code? Skill up faster with our practical video courses. Start your free trial today.
Advertisement

Quick Tip: Mimic Equal Columns with CSS3 Gradients

by
Student iconAre you a student? Get a yearly Tuts+ subscription for $45 →
This post is part of a series called CSS3 Mastery.
Getting to Work with CSS3 Power Tools
Quick Tip: A Crash-Course in CSS Media Queries

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 a width directly to the body.

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() and to() functions, keep in mind that they're simply helper functions, which direct to color-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?

Advertisement