One of the things I have been struggling with in my carreer is finding a good satisfieing way of making usable rounded cornered buttons / tabs, now that Internet Explorer 8 has been released we webdesigners can finally make some more use of the newly become available techniques like CSS 2.1, in this post ill describe a new technique I have been figuring / testing out these past weeks for this purpose.
First things first, so far I have been using the technique described by Douglas Bowman in his post Sliding Doors of CSS in my projects, this technique however isn’t perfect in both a technical and usability point of view but it was the best available so far in my opinion, some of the issues I have with it are:
- The left part of the tab is not clickable without the use of javascript (so user hovers and tries to click but nothing happens);
- You need 1 image that is very long applied to the HTML element a to “fake” a dynamic effect;
- In order to use this technique for buttons you need to add an extra unnecessary HTML element around it like a div or a span.
To see my point you can check out one of his samples here
Now I would like to turn this around and introduce a new technique which follows these target rules:
- The styling must be applieable to 1 HTML element so we don’t need to “clutter” our HTML pages with unnecessary HTML elements saving some data transmission (altough small);
- The button or tab must be fully clickable over the parts the user can see;
- The button or tab must follow the principals of Unobtrusive Javascript (so it must look and be hoverable like a button even when javascript is disabled);
- It must work flawless in all the latest of commonly used W3C compliant browsers (Firefox / IE8 / Opera / Safari / Chrome);
- It must be true dynamic with the use of a maximum of 3 images (forming the left and right corners and the middle part) for each state (normal / hover / active etc..);
- The rounded corners must be able to have a transparent background to overflow nicely into the design behind it (so you don’t have to make alot of buttons with different backgrounds);
Current issues with this technique
It will not work in IE6 or IE7 and some other older browsers, it will however still be usable for your users, but they will look a bit worse. I didn’t had the time to figure out some “nice” “hacks” which you can include by using IE6 / IE7 only stylesheets. Due to some other issues it will also not work in for example FF2 and Opera 8.01, it does work however in all major new browsers.
Outcome of current tests with this technique
So far I tested this technique on the following system / browsers combinations:
The following list is tested and is working 100% and will look like the image below.

Mac OS X:
- Firefox 3.5
- Firefox 3.0.11
- Safari 4
Windows:
- Internet Explorer 8
- Chrome 2.0
- Opera 9.64
Linux:
- Firefox 3.0.11
Tested but not working 100%, see resulting images for the current issues.
Windows:
Firefox 2.0
Opera 8.01
IE 7 / IE 6
The technique
What CSS 2.1 techniques will we use exactly?
We will use the following new techniques available to us:
- The pseudo elements :before and :after;
- Generated content using the content property;
Creating a button
In this article I will only describe the Button from the final example to explain the technique, the tab isn’t that different though and is visible in the final example.
Step 1: The HTML structure
Put down the following HTML structure in your HTML document:
<div class="component-button-container"> <a class="component-button" href="#">Button 1</a> <a class="component-button" href="#">Button 2 slightly longer.</a> </div>
Step 2: The images
The next thing we need is some images, the following is a list of images I quickly created using GIMP with some article on the internet wich I can’t remember anymore
. I needed a total of 6 images for each component wich formed the left middle and right of 2 states.
Button – Normal state:
Button – Hover state:
I am not a designer so they are suppose to look crap and are merely used for the example
. Download these button images and upload them to some dir on your webserver.
Step 3: Doing some CSS
Now it’s time to do some CSS magic, in the example which I provide at the end I have put the most important CSS for clearance into embedded CSS, which means it has been put between the following tags straight in the HTML document served:
<<span class="start-tag">style</span><span class="attribute-name"> type</span>=<span class="attribute-value">"text/css"</span>></style>
So now that we have the HTML in place and uploaded the images we can start by creating the left and right corner of each element that needs it, we gonna start by providing the button some generated content on which we can project the left and right rounded cornered image, the content will be ‘\a0′, which is a hexcode for a non-breaking space, I do this because I want the image to always be shown and this won’t happen in browsers like IE8 and Opera when you only use a non-breaking space like ‘ ‘, when that is put in we will make the generated content show as an inline-block so we will be able to give it a height / width. Give it a width of 7px (the exact same width of the left and right image itself), you don’t need to set the height of the generated content because it will inherit it’s height of the main element:
.component-button:before, .component-button:after {
display: inline-block;
width: 7px;
content: '\a0'; /* Hexcode for non-breaking space */
}Now we don’t see much yet, so we need to give both ends a nice background in it’s normal and hover states and add some spacing between the cornered image and the text, also it is important to provide a minus margin-left / margin-right of exactly the same amount as the left and or right cornered image width (the 7px in the example above) so the image will not render over the middle image, we will do that like this:
.component-button:before {
background: transparent url('samples/img/component-button-normal-left.png') no-repeat top left;
margin-left: -7px;
padding-left: 10px;
}
.component-button:after {
background: transparent url('samples/img/component-button-normal-right.png') no-repeat top right;
margin-right: -7px;
padding-right: 10px;
}
.component-button:hover:before {
background-image: url('samples/img/component-button-hover-left.png');
}
.component-button:hover:after {
background-image: url('samples/img/component-button-hover-right.png');
}Now that that is done, we need to style the main HTML element, provide it with the following CSS:
<pre id="line11">.component-button {
display: block;
float: left;
background: transparent url('samples/img/component-button-normal-middle.png') repeat-x top left;
height: 20px;
line-height: 20px;
margin: 0 7px;
}
<pre id="line11">.component-button:hover {
background-image: url('samples/img/component-button-hover-middle.png');
}
The "display: block" ensures that we can influence the height of the HTML element and the float will make it display nicely next to another button. The "margin: 0 7px;" ensure that other buttons are not rendered above this HTML element.
The final example of this technique can be found here it also contains some added styling to make it look somewhat better and it has styling / example for the tabs asswel.
Your comments
If you found some way to fix the minor issues in the FF2 / Opera 8.01 browsers or have successfully made it work in IE6 and / or IE7, feel free to post your comment and share it with me and the rest
Update 2011-08-12:
Since writing this article the web has moved forward fast, nowadays I would not bother to create rounded effects (altough archievable using some javascript) but create it using CSS3, for a good resource check out Super Awesome Buttons with CSS3 and RGBA by Mark.
