Language Selection

English

Latest design resources

  • Finger-Friendly Design: Ideal Mobile Touchscreen Target Sizes

    21 Feb 2012 | 4:18 pm

       In darts, hitting the bulls-eye is harder to do than hitting any other part of the dartboard. This is because the bullseye is the smallest target. This same principle can also apply to touch targets on mobile devices. Smaller touch targets[…]

    Read more...
  • Beautiful Covers: An Interview With Chip Kidd

    20 Feb 2012 | 3:00 am

       The work of Chip Kidd spans design, writing and, most recently, rock ’n’ roll. He definitely has the charisma to get ahead in that third field. He is best known for his unconventional book jackets, but he has published[…]

    Read more...
  • Stop Writing Project Proposals

    17 Feb 2012 | 1:00 am

       After several grueling days I had finally finished the proposal. I sent it off and waited for a response. Nothing. After a few weeks, I discovered that they were “just looking”. Despite the urgency and aggressive timeline for the[…]

    Read more...
Home > Technology > Languages > Decoration for fluid html
Decoration for fluid html
Technology - Languages
Written by J.-N. R.   
Monday, 17 May 2010 09:37

A CSS 2 technique for decorating fluid HTML elements (blocks of unknown dimensions).

Adding decorations to fluid HTML elements (blocks that don't have fixed dimensions) is surprisingly very hard to do in CSS 2.1. The situation is much better in CSS 3 with the Backgrounds and Borders module. But if you want to support the currently deployed versions of Internet Explorer (versions 6, 7, and 8 account for 60% of all web traffic as of June 2010), you're stuck with CSS 2.1 and a difficult task. This article explains why decorating fluid elements is hard, and demonstrates a technique to achieve such a goal. No JavaScript hacks here; only pure W3C compliant CSS and HTML, with some images.

1. The basic problem

If you happen to look at current web sites in 2010, most web designers still use images to decorate elements. Let's take the example of a basic, yet very popular visual effect: rounded corners. Since there is no direct support for rounded corners in CSS 2.1 (note that there is in CSS 3), 90% of the sites will use a background image to render this effect. It is quite easy to generate such a background image when the element has a fixed width: you just load GIMP or Photoshop, create a new image with exactly the same size as your HTML element, add the background color you want and then take care of the rounded corners (see this link for a GIMP tutorial; it's easy). Back in CSS, you add the background-image property to your element and you're done with it.

But what if the element does not have a fixed width of 200 pixels, but a fluid width that depend on its content or on the size of the screen? This is extremely common yet makes things a lot harder to deal with. You can no longer use a simple background image, as it would not fit the exact dimensions of the element. To convince yourself, look at the following buttons: the first one has a width of about a hundred pixels . But the second one has a longer text, so the first image we generated does not longer fit . Repeating the background of course does not help [. It is of course extremely painful to generate an image for every different button text that you may have on your site (this would also make the CSS code messy, with probably an ID for each button instead of just using a class). So how can we solve this problem?

2. A generic solution

The following solution is a bit complex, but takes care of even the worst situation, an element with an unknown width and an unknown height. Its main disadvantage is that it requires quite a lot of markup to be added to the original element. But until we really can use CSS 3, better techniques probably don't exist.

We first need to add 9 (yes, 9!) children div to our original element. We need four corner divs, four border divs and a background div. So the final markup will look like:

This is our text


Then we need to put in the correct CSS. The general idea is to position the additional divs absolutely, and since we want to position those relative to the originalElement, it should form a new "containing block". The easiest way to make the originalElement a containing block is to add a position: relative; CSS property to it. Once this is done, here is the CSS code for the other elements:

 

#originalElement .BackgroundDecoration
{
background-color: #4a93de;
top: 8px;
bottom: 8px;
left: 0px;
right: 0px;
position: absolute;
}

#originalElement .TopLeftDecoration
{
top: 0px;
left: 0px;
height: 8px;
width: 8px;
background-repeat: no-repeat;
background-image: url("rounded-corner-top-left.png");
position: absolute;
}

#originalElement .TopRightDecoration
{
top: 0px;
right: 0px;
height: 8px;
width: 8px;
background-repeat: no-repeat;
background-image: url("rounded-corner-top-right.png");
position: absolute;
}

#originalElement .BottomLeftDecoration
{
bottom: 0px;
left: 0px;
height: 8px;
width: 8px;
background-repeat: no-repeat;
background-image: url("rounded-corner-bottom-left.png");
position: absolute;
}

#originalElement .BottomRightDecoration
{
bottom: 0px;
right: 0px;
height: 8px;
width: 8px;
background-repeat: no-repeat;
background-image: url("rounded-corner-bottom-right.png");
position: absolute;
}

#originalElement .TopDecoration
{
background-color: #4a93de;
height: 8px;
left: 8px;
right: 8px;
position: absolute;
}

#originalElement .BottomDecoration
{
background-color: #4a93de;
height: 8px;
left: 8px;
right: 8px;
position: absolute;
}

#originalElement .LeftDecoration
{
background-color: #4a93de;
width: 8px;
top: 8px;
bottom: 8px;
position: absolute;
}

#originalElement .RightDecoration
{
background-color: #4a93de;
width: 8px;
top: 8px;
bottom: 8px;
position: absolute;
}

This example code assumes that we created rounded corners with a 8px radius (the corner divs will have dimensions of 8*8 pixels), with a background color for the element of #4a93de. You will probably also need to add some padding to the original element so that the content looks better (I recommend using the same padding as the radius: 8 pixels). Although the CSS code above is pretty much self-explaining, it may take a bit of time to understand how all the pieces get together.

For instance, you may be wondering why using 4 border divs (left, right, top and bottom) and a background div is necessary. It is indeed mandatory if you use transparent PNGs. If you were to put the background-color property directly on originalElement, you would notice that the rounded corner would disappear, since the background color of the originalElement would appear below the transparent part of the corners. If you just use an image with no transparency (so with the color of the outer parts of the corners set to the background color of the page, usually white), you can get away with using only 4 divs for the corners. I still recommend using 9 divs, since this is much more portable. If you change the background color of the page later, you won't have to change your images.

Some example results. As you see, you can create as many buttons as you want, and the decorations look great whatever is the size of the text.

3. Using this strategy with other effects

What's very powerful is that this technique is easily extended to any decorations or effects. With it, you can add outer shadows to your elements. Or add completely custom borders: there is no limitation. It will work with all the major browsers out there (you may need an ActiveX hack for IE 6 if you use PNGs though). You can combine your images in a single file to reduce the number of HTTP requests, thus eliminating any real drawback compared to the fixed width version with a single background image.

Conclusion

Once you have setup the markup and images correctly, this technique allows for unlimited skinning of elements, without worrying about their dimensions. You can concentrate on the contents of your elements, and be confident that the decorations automatically adjust to them. Surprisingly, I haven't been able to find any tutorial online for this strategy. However, Kameleoon uses an expanded (and more complex) version of this base technique to decorate generic elements - the additional markup is created dynamically via JavaScript. As a final word, this method is futureproof: once CSS 3 is supported by most browsers, migrating to the Background module will be easy for people relying on this technique. It will allow developers to get rid of the ugly markup which is unfortunately necessary in the CSS 2 version.