Rounded Corners In Liquid Designs Using CSS

Written by Shawn Thomas

Problem Analysis

The current trends in web design are rich with rounded corners, smooth edges, and soft drop shadows. Ever-curious in how to do it for my own projects, I began researching methods used by others but quickly reached a wall. All of the methods researched had some serious limitations.

Most of the methods are for fixed-width boxes: the box tops and bottoms are nothing more than images placed before and after the box content. This design is not liquid and therefore would require retooling to fit whatever application demands it.

Other methods I found were liquid and would genuinely stretch or shrink to fit, but they were still little more than hidden hackery. The images used were GIFs or PNGs with a transparent corner interior and an opaque corner exterior set the to color of the parent container's background. This would work in a lot of cases and would continue to work if you changed the background color of the content box. However, should you desire to change the background color of the parent container, you'd have to re-render the corner images with the new color. Also, this method will not allow usage of drop shadows or decorative edges without heavy modification. And, god help us, if you decide to use a background image in the container, it will not work because the corners would be difficult to align with the background image and would stick out painfully.

So what I came up with is a variation on the Sliding Doors technique outlined at A List Apart used for making liquid tabs. The method calls on the creative use of margins and descendant block-element backgrounds (read the link for a more thorough analysis). It's a great method and has opened my eyes to design concepts I'd not seen until I read the article some time ago. Its tools have proven a good solution for this problem.

At its most basic, a liquid, drop-shadowed, rounded-corner box can be had with six images in a 3 × 2 grid: top-left corner, top edge with right corner, left edge, right edge with content background, bottom-left corner, and bottom edge with right corner. This would work for most situations, but with display resolutions and window widths getting bigger, and the accidental use of large content sizes, it's an arms race to prevent interruption and tiling of the background images to reveal the design's shortcomings. The designer must be diligent to ensure that the center and edge images are long enough for every situation.

The plan I chose eliminates this problem by taking the sliding doors method and recursing it one step further, requiring eight images in a 3 × 3 grid to guarantee complete coverage of the backgrounds regardless of rendering sizes. That's four corners and four tiling edges; the center, where the content resides, can have a solid color instead of an image.

NW
N
NE
W
Box Content
E
SW
S
SE

This isn't an end-all be-all method; there are a few disadvantages. Changing the background color of the rounded box itself requires re-rendering the images. The markup of the page is further complicated by adding nine extra divs around the content box (this can be mitigated with templates or through using javascript to change the DOM). The CSS namespace is also dirtied by the addition of 10 extra class selectors. But these problems are minor. The method works.

Examples

Here it is in its full-width glory:

Hey there, this is a test!

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Cras metus. Maecenas justo elit, lacinia sit amet, cursus ut, sagittis sed, eros. Suspendisse potenti. Maecenas nec nisi. Donec vestibulum sollicitudin tellus. Sed consequat pellentesque ante. Vestibulum turpis quam, vulputate nec, nonummy convallis, ultrices congue, ligula. Ut rutrum leo et orci. Proin pharetra. Nam non sem ut eros fringilla ornare. In ullamcorper lorem eget ipsum. Suspendisse semper enim in arcu cursus consectetuer. Suspendisse potenti. Proin libero eros, adipiscing quis, volutpat in, ultrices ut, lacus.

Nulla facilisi. Vestibulum vel magna in ante lobortis semper. Integer posuere justo et urna. Vestibulum sit amet sapien ut quam tempor fringilla. Fusce a neque a enim mattis dapibus. Ends with a paragraph element!

Overlapping boxes and relative positioning:

Jimmy Beatbox says:
Hi there!

I'm testing this thing with a multiline body to see if this would work well as a comment template.

WOAH YEAH!

Lessons Learned

My lessons learned, this time, are external and ancilliary to my goals. They presented themselves as roadblocks and had to be debugged and worked around to continue progress.

I had an issue with collapsing margins. Certain HTML elements have an inherent amount of vertical margin; headings (H1, H2, etc), paragraphs (P), lists, forms, blockquotes, etc. are among these. The usage of these elements either at the beginning or end of the content div would cause a blank horizontal space, where the page background would show, between the content and the endcap. According to the W3C CSS spec, two adjoining elements with vertical margin are supposed to collapse the space between them to the largest of the two. Every browser seems to believe that this also applies to margins from elements contained within a box, so the content's margin sticks out outside of the content box. This is unsatisfactory.

A look at this helpful article on CSS autoheight and margin collapsing helped me understand what was happening. The child elements were overriding the parent's undefined margin with their own (because their margins were the larger of the two), causing the blank bar. The trick suggested on this page calls for setting a padding of 1 pixel on the parent box, forcing the margin of the child elements to not merge with the parent's margin. The background stretches to completely contain the descendants and everyone is happy.

Also, it seems IE6-Win automatically stretches a floated block to 100% width of parent container if you explicitly set the height of the block with something like height: 20px. All other browsers shrink the block to the size of the contents. IE6 will still honor explicit width settings, but if you expect automatic shrinking to occur, you're out of luck. The fix is to use padding, instead of height, on the desired box, in this case padding-top: 20px. IE6 will then honor the height and shrink the width. Anything not floated will still render as it normally would and use 100% of the parent container's width, just like all the other browsers.

Since my corner and shadow images are PNGs with alpha transparency, users of Internet Explorer prior to version 7 will notice grey tinting to the images and no transparency. There are fixes to this alpha transparency problem, but that is beyond the scope of this article. Research and usage of these methods is suggested if you wish to do so. Also, use of backgrounds and floating seems to render strange results resembling blocks of unrendered background. This is a bug in the browser.

This final, polished method works on my Windows platform in FireFox 2, Safari 3, Internet Explorer 6, and Opera 9.10. Your mileage may vary. Contact me through appropriate channels if you discover otherwise on your system.