By Søren Madsen

In a recently published and controversial article, it was claimed that "Full CSS Site[s] TEND to be very BOXY look'n and sharp edges ....translation: ‘No rounded corners’. This is because it get tedious to place the rounded corners and match them up to the outer box".
We respectfully disagree, and do so by showing how easy it actually is. We'll even take it a step further, and show how customized borders and corners can be applied to fully fluid and flexible layouts with dynamic content, using what we consider to be sound and semantically logical markup.

The markup

Here is what we got:

<h3>Article header</h3>

<p>
A few paragraphs of article text.<br />
A few paragraphs of article text.
</p>

<p>
A few paragraphs of article text.<br />
A few paragraphs of article text.
</p>
	
<p>
A paragraph containing author information
</p> 

The hooks

If we want full control of the layout, we need to make sure we have enough elements we can target with our CSS. Let's call these elements "hooks". Our markup needs just a few more.
First of all, let's wrap the whole article in a containg div, and then wrap each structural section in an element also:


<div class="Article">
 <h3>Article header</h3>
		
 <div class="ArticleBody">
 <p>
 A few paragraphs of article text.<br />
 A few paragraphs of article text.
 </p>
			
 <p>
 A few paragraphs of article text.<br />
 A few paragraphs of article text.
 </p>
 </div>
		
 <div class="ArticleFooter">
 <p>
 A paragraph containing author information
 </p>
 </div>
</div>

This is actually all we need. If we examine the code, we'll see that we have given ourselves at least five"hooks", which is what we need to place customized graphics in each of the four corners (and left side) of our article.

see Step 1 - primary markup

The design

First let's decide on some basic layout parameters. Our graphic designer gave us this mockup for reference:

Graphical sketch "I want the borders and corners to look something like this", he said. He also told us to beware of the fact that all articles may have different width and height, and that he still wasn't sure what kind of background he wanted the articles to have. In fact, he wasn't even sure those were the borders he wanted. "Could you leave that open, or make it so that it's easy to change?", he asked.

Ain't that always the case?

We set out to keep the number of "hooks" as low as possible, so we'll have to pay extra attention when we start to prepare the graphics for our solution, and see if the graphics we need, are suitable to be hooked up to elements we already have in our document. We have a div containing the whole article. That'll do for our top left corner, and top and left sides. Header elements are by default block level elements, and we'll take advantage of their behaviour: they extend to the full width of their parent element. So we'll use the <h3> element for our top right corner.
We'll use our article-footer div for the bottom left corner - and the contained paragraph for our bottom right corner.

step 1.1how we slice up the sketch

Obviously, you could use any element to hook graphics up with. Maybe you are in a (very likely) situation, where you do not have a document structure like the one we're working with here. Maybe you only have a single paragraph of text, you want to apply customized graphics to. You could also very easily do that. As stated above, all you need is at least four structural elements (depending on the height of your element you may need five), and these elements could all very well be div's each with their own class. Just remember that for a div element to be rendered, it needs to have content to manifest its presence.

However — the purpose of this article is to show that if you already have structural elements such as headers, paragraphs etc — you can and should use those.

The styles

We'll go on with that. First let's turn on borders on our elements, and set a relative width for the div that contains the whole article, to see how things behave:

div.Article {
  width:35%;
  border: 1px solid red; }
div.Article h3 {
  border: 1px solid blue; }
div.ArticleBody {
  border: 1px solid black; }
div.ArticleFooter {
  border: 1px solid blue; }
div.ArticleFooter p {
  border: 1px solid magenta; }

See step 2basic element behaviour

Nothing really surprising here. We do however take notice of the gaps appearing before and after our div class="ArticleBody". Partly ignoring that for now, we'll go on and write ourselves a stylesheet:

body {
  background: #cbdea8;
  font:
  0.7em/1.5 Geneva, Arial, sans-serif;
  }
div.Article {
  background: 
  url(images/custom_corners_topleft.gif)
  top left no-repeat;
  width:35%;
  }
div.Article h3 {
  background:
  url(images/custom_corners_topright.gif)
  top right no-repeat;
  }
div.ArticleBody {
  background:
  url(images/custom_corners_rightborder.gif)
  top right repeat-y;
  }
div.ArticleFooter {
  background:
  url(images/custom_corners_bottomleft.gif)
  bottom left no-repeat;
  }
div.ArticleFooter p {
  background:
  url(images/custom_corners_bottomright.gif)
  bottom right no-repeat;
  }

See step 3first attempt

Not bad at all! Actually better than we expected. Obviously we need to add some padding to our respective elements to make it look better - and then there's the gaps. These are caused by the carriage returns inserted by our paragraph (block) elements. We could just avoid using paragraph elements all together, and thereby bypass this "problem", but we insist on keeping our markup nice and structurally clean and logic. It isn't our data's fault that we are lazy stylers.

We assume that a carriage return must equal 1.5em, since that is what we have specified for our line-height, and therefore our first attempt was to add a margin-top:-1.5em to our ArticleBody and ArticleFooter, and that did the job in most standards-compatible browsers — except the ones used by the majority of internet users on this planet. After testing, trial, error, rinse and repeat we found that we would have to use at least a margin-top:-2em to be sure that the elements would "touch" and the gap would close.

div.Article {
  background:
  url(images/custom_corners_topleft.gif)
  top left no-repeat;
  width:35%;

  } 
div.Article h3 {
  background:
  url(images/custom_corners_topright.gif)
  top right no-repeat;
  font-size:1.3em;
  padding:15px;
  margin:0;
  }
div.ArticleBody {
  background:
  url(images/custom_corners_rightborder.gif)
  top right repeat-y;
  margin:0;
  margin-top:-2em;
  padding:15px;
  }
div.ArticleFooter {
  background:
  url(images/custom_corners_bottomleft.gif)
  bottom left no-repeat;
  }
div.ArticleFooter p {
  background:
  url(images/custom_corners_bottomright.gif)
  bottom right no-repeat;
  display:block;
  padding:15px;
  margin:-2em 0 0 0;
  }

See step 4 - looks like we're finally there!

The final notes

If you've been viewing this example in NS 4.x, you've probably noticed that the page shows up blank. We've found no way to get this technique to work acceptably in NS 4.x, so instead we're going to hide the styles that the browser in question cannot render properly. NS 4.x does not understand style-tags with media="all" specified and we've taken advantage of that in the example that follows. We've made two style-tags, one with styles we want all browsers to render, and another we want to hide from NS 4.x. Even though it breaks our heart to do so, we've also changed our font size specification from em's to px's. You wanted backwards compatibility - you got it.

Step 5 - graceful degradation in NS 4.x

The real world

"Yeah - but we want to see real world applications of this, mate", you say - and we anticipated that, and provided an example of the technique applied in a more advanced context. We borrowed an already thoroughly tested layout from Alex Robinson, and applied our styles to it — and we're glad we did! Our first attempt opened a plethora of bugs and quirks in IE6, triggering bugs affecting both z-index stacking level of our elements, elements that disappeared and margins acting like silly little children, but then we learned that a simple position:relative and a well positioned <br /> fixed it all. View the source in the example for further investigation.

Step 6 - our attempt at applying our technique to a full fledged layout with headers, columns and footers

The limitations

If you have been paying attention, you probably already realized that this example only plays well with surrounding solid color backgrounds. With this method we need to cover the graphics from the top left corner with the graphics in the top right corner. If we made the top right corner graphic transparent, the top left graphic beneath it would show. Same goes for the bottom. And that is indeed a limitation, but what a great idea for a part deux of this article that would be, showing how working with ie. gradient backgrounds can be accomplished. This article did however demonstrate a generic method, with backwards-compatibilty and sound markup in mind, and it is our sincere hope that this will inspire alot of offsprings and ideas — perhaps even some that include working with not-solid background colors.

The acknowledgements

Brian Alvey for discussions, insisting on graceful degradation and real world examples, and David Schontzler for helping a danish guy write technical stuff in english.