Tool

Spanky Corners 1.1 beta

The SitePoint Corners Store

The Basics

  1. The 'div.rounded' gets the bottom-left corner graphic.
  2. All content elements inside our DIV (P, UL, OL, etc) are given the bottom-right corner graphic by default.
  3. They also get a negative margin-bottom which forces the following element to slide up and obscure their corner graphic. Only the final content item within 'div.rounded' is allowed to show it's corner graphic.
  4. The heading gets the top-right corner appended to it's righthand side. This overrides the graphic it automatically inherited in step 'b'.
  5. By switching our heading's display property from 'block' to 'list-item' we can add the top-left corner to the front of our header.

How does it work?

How it works


Line by Line

CSS
body {
  background-color: #ffffff;
  color: #333333;
  font-size:62.5%;             /* Explained @ www.clagnut.com/blog/348/ */
}
The Setup: The enigmatic font-size is thanks to Richard (clagnut.com), and allows simpler conversions between pixels and EMs.
div.rounded {
  background: #849ec4 url(bl_18_849ec4_ffffff.gif) no-repeat bottom left;
  color: #333333;
  position: relative;
  padding-top: 0;
  padding-bottom: 18px;       /* Counteract out the negative margins applied below */
  margin: 1em 10px 0 0 ;      /* optional: just keeps the boxes from touching  */
  height:100%                 /* handles IE guillotine bug */
}
The Container Box: As you may have noticed, the image names generated by Spanky tell you their position (bl = Bottom Left, etc), their radius (18px in this case) and their foreground and background colors. We also need to pad the bottom at least the height of the our corner radius to counteract the negative bottom-margin we will be adding to the elements inside it.
div.rounded * {
  background: #849ec4 url(br_18_849ec4_ffffff.gif) no-repeat bottom right;
  color: #333333;
  padding: 1em 18px 18px 0;    /* Bottom and right padding keeps our text clear of our corner */ 
  margin: 0 0 -18px 18px;      /* Negative margin-bottom creates an overlap with the next item */
  height:100%;                 /* handles a sometime IE guillotine bug */
}
Here we are using the universal selector (*) to apply the bottom-right corner and some very 'tightly tailored' margins to every single element within 'div-rounded'. Don't panic -- we will override some of these rules shortly.
To be truthful, there is no reason why you couldn't simply apply this rule directly to the elements you plan to use inside your DIV (i.e. div.rounded p, div.rounded h5, etc). The universal selector simply 'covers all bases'.
The margins and padding are important here. The negative margin-bottom creates the overlap that obscures all corners -- except the one on the final element within our DIV. We also need a left-margin to prevent any element from blocking out that bottom-left corner in our DIV. Padding-bottom stops our text from disappearing under our overlap section. Padding-right keeps our text off the right side of the box. Padding-top (1em) controls the vertical spacing of our elements.
div.rounded * * {
  padding: 0;                  /* reset */
  margin: 0;                   /* reset */
  background: none;            /* reset */
  color: #333333;
  height:auto
}
You might call this rule the 'universal reset'. We obviously don't want corners and wacky margins on elements two level deep -- for instance, links within paragraphs, or list items within ULs. This rule resets the padding, margins and background of all these items at a stroke. Of course, if you chose not to use the universal selector in the previous rule, you can leave this out.

div.rounded h1, div.rounded h4 {
  color: #ffffff;
  background: #849ec4 url(tr_18_849ec4_ffffff.gif) no-repeat top right;
  display: list-item;           /* Force the header to behave like a list */
  list-style-image: url(tlc_18_849ec4_ffffff.gif);   /*   top left corner */
  list-style-position: inside;  /* move the list-image inside the text box */  
  list-style-type:none;         /* remove the default bullet */
  padding: 0;
  margin: 0;
  position: relative;
}
Witchcraft! We talk the header into cross-dressing as a list (display:list-item), giving it magical access to a second image -- the list-image attribute, which now becomes our top-left corner. We also move our list-image inside our text area (list-style-position: inside), and set it's list-style-type to 'none'. This stops a 'placeholder bullet' from appearing before our image has time to load.
Make no mistake: List-images weren't designed with this in mind, and as such, the control you have over their positioning is less than ideal. In all non-IE browsers the list-image will 'prop open' the textbox, even if it's height or line-height are less than the height of the list-image. The header text will always sit level with the bottom edge of the list-image, so as long as the font-size is a few sizes smaller than the height of the list-image, you should be able to scale the text up 3 or 4 times without breaking the corner.
Unfortunately IE allows the list-image to break out of our textbox, meaning we need to use line-height to control the height of our textbox, and with it, the positioning of our list-image. This makes the font-size/line-height relationship quite critical in Internet Explorer only. It's for this reason that we code those 'touchy' line-heights into 'conditional comments' (below).

div.rounded h1 {
  font-size: 3.2em;
}
div.rounded h4 {
  font-size: 2em;
}
Finally in the CSS, we set up a relative font-size for each of our headers. As mentioned earlier, these sizes are closely tied to line-height settings in IE, so tweaking the font-size will require adjustment to the line-height settings below.
IE Conditional Comments

<!--[if IE]>
	<style type="text/css">

<link type="text/css" rel="stylesheet" href="rounded-ie.css" media="screen" />

	</style>
<![endif]-->
Place this code in the head of your document
IE only CSS

div.rounded h1, div.rounded h4 {
	display: block;
}

div.rounded h1:first-letter ,  div.rounded h4:first-letter  {
	background: transparent url(images/images/tlc_18_849ec4_ffffff.gif) no-repeat top left;
	padding: .3em 0 0 18px;
}
The line-height of these headers are closely linked with their font-sizes in IE. Hence, scaling up the fonts in IE currently causes a gap to appear next in the top-left corner. If you can figure out a workaround to prevent this, glory will be yours!
IE has one more little surprise for us. List-images that are positioned inside their textbox have a 18px wide space reserved for them. This space can not be reset or overridden, meaning graphics smaller than 18px float in the center of this reserved space -- leaving an ugly gap on the left side.
The solution is relatively simple. We use condition comments to move the list-image back to the outside and give it a left margin. The generator does this automatically when you choose a corner radius less than 18px.
We've now altered the conditional comment code to switch the list-image for background using the :first-letter psuedo class. The key benefit of this is scalable text in IE6.
* NOTE: This change does cause the top corners to crop slightly in IE at very large corner radii (25px+). It also gives us less control over padding within the heading. Perhaps a worthwhile trade-off for now.
I originally set out to use :first-letter to place the top-left corner in all browsers. However, after a lot of testing, I decided the support was far too spotty to carry that task. Firefox and Opera can't even agree on things, so don't even mention IE. However, getting :first-letter to work predictably in one browser is a much easier task -- even if it's IE6.
That should cover the nitty gritty. Hope you find it useful. Good luck.

NEW! - March 2006