2008-04-30

Round Cornered Box with One Image

How to save time building round cornered boxes

I have to admit, this is not entirely my own original idea. Ever since images could be included in web pages, people have been using them for more than just their content, since their shape and texture are also useful to augment the web experience. UI features such as buttons, menus, and backgrounds have become expected in modern web apps, and many ingenious techniques have been developed for escaping the bounds of the square-cornered HTML boxes. So I was excited to be able to offer a small contribution to the crowded field of Round Cornered Box implementations on the web.

Neon border
Using just one image to draw round cornered boxes is also not new (see "Simple Rounded Corner CSS Boxes", "Liquid round corners", "CSS Mojo: Adding Visual Polish To Your Pages" and many more at "CSS Rounded Corners 'Roundup'"). 

This can get quite complicated, but I am in favor of simplifying things as much as possible. So let's consider the simple cases first, and go from there.

We can use one image as a background-image along with a background-position which allows us to specify which corner of the image to use in each corner of our Round Cornered Box.  This technique will work with images that are flat rather than gradient filled, though the edges and corners can be anything you like, including gradient edges and shadows.  Let's start with an image such as the "neon" image shown above.

If we only have one size that the box needs to be, then we only need one image. So the goal is to generate several different size boxes with just one image. Somehow, it seems we'll have to specify (at least) four separate elements, one for each corner, each one using a different corner of the one image. If we arrange these four element at the right positions, we can get a total size that is almost twice as large as the original image.

So here is a div element (with a fixed size) that uses the left top corner of the image (which has a grossly long URL here, sorry). 

<div style="height: 100px; width: 100px; 
  background-position: left top; 
  background-image: url(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiA9ERKDNPjRuJkFXwA6spMcpazpqo2lFJZJy8ELG_AU3wayiS8cWBVqf1w8rx86W9__mFUEw-4uIIhABcZ4bJfStnZlUPyRHZSCsBgI97A7YJH2TJqN2xll99MCXJf077pBFaxw-Z8-_n_/s1600/neon.png)"></div>

And this is how div looks.

Similarly, we can build three more divs for the other corners.  But rather than repeat the image reference each time, we can use one CSS class:

.RCB .corner {
  background-image: url(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiA9ERKDNPjRuJkFXwA6spMcpazpqo2lFJZJy8ELG_AU3wayiS8cWBVqf1w8rx86W9__mFUEw-4uIIhABcZ4bJfStnZlUPyRHZSCsBgI97A7YJH2TJqN2xll99MCXJf077pBFaxw-Z8-_n_/s1600/neon.png)
}
Here is how I would like to specify the CSS for the positions for each corner:
.RCB .left {  background-position-x: left; }
.RCB .right {  background-position-x: right; }
.RCB .top {  background-position-y: top; }
.RCB .bottom {  background-position-x: bottom; }
Except, oops, that won't work in Firefox because it doesn't (yet) support the very logical background-position-x and -y properties. (See Background-position-y: Firefox Fails!) OK, so we have to do this more redundantly like so:
.RCB .left.top 
{  background-position: left top; }
.RCB .right.top 
{  background-position: right top; }
.RCB .left.bottom 
{  background-position: left bottom; }
.RCB .right.bottom 
{  background-position: right bottom; }

Here is the simplified div, with a container div to specify the RCB context.



And this is how it looks, same as before.

We can easily define divs for the other corners, but how should they be arranged so they show up in the right places? Maybe they could all be nested, one inside the other. But that's still going to require that we shift the position of the divs by the appropriate amounts, and size the containers appropriately, and then where do we put the contents of this box? People have done all this, but I am looking for an easier way.

This is where tables come in. They are precisely the right element to use because they constrain the positions along horizontal and vertical dimensions exactly as we require. I'll argue the case for tables more thoroughly in another blog, but right now, we'll just use them unapologetically. By the way, I don't expect people to write these table elements each time. Rather, templates should be defined to translate a simple div into all the right elements. Here is how we can simply layout the round cornered box with a table.


And here is how it looks, with no content, and showing the border:

Now, where are we going to put the content of the box? And how can we size the boxes based on the content so we don't have to specify fixed sizes?

Well, the content has to go somewhere in the middle, but there is no middle element when we have a 2x2 table, so we can make it a 3x3 table instead, and make edges for the rounded box using the edges of the image.

Here it is, a fluid round cornered box with one image. (You'll have to look at the source to figure out how I did it, until I add an explanation. It also doesn't work correctly for browsers other than Firefox. Still working on that.)
This is a test. One Two Three... This is a test. One Two Three... This is a test. One Two Three... This is a test. One Two Three... This is a test. One Two Three... This is a test. One Two Three... This is a test. One Two Three... This is a test. One Two Three... This is a test. One Two Three... This is a test. One Two Three... This is a test. One Two Three... This is a test. One Two Three... This is a test. One Two Three... This is a test. One Two Three... This is a test. One Two Three... This is a test. One Two Three... This is a test. One Two Three... This is a test. One Two Three... This is a test. One Two Three... This is a test. One Two Three... This is a test. One Two Three... This is a test. One Two Three... This is a test. One Two Three... This is a test. One Two Three... This is a test. One Two Three... This is a test. One Two Three... This is a test. One Two Three...


We can extend this technique to make round cornered boxes as large as we want, just by repeating the elements for the edges. But however many times we repeat it, we will still be limited by that number. There are a few other techniques that do not require any additional elements, which I will cover in another blog.

So we have successfully achieved the goal of using the parts of just one image for the corners and edges of the rounded box. We are still limited in maximum size based on how large the image is and how many times we repeat the elements. And we have to match the color of the background behind the content with the color in the center of the image, and this must be a single flat color, not a gradient or texture of any kind. So there are limitations that we would probably like to address, in another blog.

No comments: