Rounded Corners and Shadows – Dialogs with CSS
- by Rick Strahl
Well, it looks like we’ve finally arrived at a place where at least all of the latest versions of main stream browsers support rounded corners and box shadows. The two CSS properties that make this possible are box-shadow and box-radius. Both of these CSS Properties now supported in all the major browsers as shown in this chart from QuirksMode: In it’s simplest form you can use box-shadow and border radius like this: .boxshadow
{
-moz-box-shadow: 3px 3px 5px #535353;
-webkit-box-shadow: 3px 3px 5px #535353;
box-shadow: 3px 3px 5px #535353;
}
.roundbox
{
-moz-border-radius: 6px 6px 6px 6px;
-webkit-border-radius: 6px;
border-radius: 6px 6px 6px 6px;
}
box-shadow: horizontal-shadow-pixels vertical-shadow-pixels blur-distance shadow-color
box-shadow attributes specify the the horizontal and vertical offset of the shadow, the blur distance (to give the shadow a smooth soft look) and a shadow color. The spec also supports multiple shadows separated by commas using the attributes above but we’re not using that functionality here.
box-radius: top-left-radius top-right-radius bottom-right-radius bottom-left-radius
border-radius takes a pixel size for the radius for each corner going clockwise. CSS 3 also specifies each of the individual corner elements such as border-top-left-radius, but support for these is much less prevalent so I would recommend not using them for now until support improves. Instead use the single box-radius to specify all corners.
Browser specific Support in older Browsers
Notice that there are two variations: The actual CSS 3 properties (box-shadow and box-radius) and the browser specific ones (-moz, –webkit prefixes for FireFox and Chrome/Safari respectively) which work in slightly older versions of modern browsers before official CSS 3 support was added. The goal is to spread support as widely as possible and the prefix versions extend the range slightly more to those browsers that provided early support for these features. Notice that box-shadow and border-radius are used after the browser specific versions to ensure that the latter versions get precedence if the browser supports both (last assignment wins).
Use the .boxshadow and .roundbox Styles in HTML
To use these two styles create a simple rounded box with a shadow you can use HTML like this:
<!-- Simple Box with rounded corners and shadow -->
<div class="roundbox boxshadow" style="width: 550px; border: solid 2px steelblue">
<div class="boxcontenttext">
Simple Rounded Corner Box.
</div>
</div>
which looks like this in the browser:
This works across browsers and it’s pretty sweet and simple.
Watch out for nested Elements!
There are a couple of things to be aware of however when using rounded corners. Specifically, you need to be careful when you nest other non-transparent content into the rounded box. For example check out what happens when I change the inside <div> to have a colored background:
<!-- Simple Box with rounded corners and shadow -->
<div class="roundbox boxshadow" style="width: 550px; border: solid 2px steelblue">
<div class="boxcontenttext" style="background: khaki;">
Simple Rounded Corner Box.
</div>
</div>
which renders like this:
If you look closely you’ll find that the inside <div>’s corners are not rounded and so ‘poke out’ slightly over the rounded corners. It looks like the rounded corners are ‘broken’ up instead of a solid rounded line around the corner, which his pretty ugly. The bigger the radius the more drastic this effect becomes .
To fix this issue the inner <div> also has have rounded corners at the same or slightly smaller radius than the outer <div>. The simple fix for this is to simply also apply the roundbox style to the inner <div> in addition to the boxcontenttext style already applied:
<div class="boxcontenttext roundbox" style="background: khaki;">
The fixed display now looks proper:
Separate Top and Bottom Elements
This gets even a little more tricky if you have an element at the top or bottom only of the rounded box. What if you need to add something like a header or footer <div> that have non-transparent backgrounds which is a pretty common scenario? In those cases you want only the top or bottom corners rounded and not both. To make this work a couple of additional styles to round only the top and bottom corners can be created:
.roundbox-top
{
-moz-border-radius: 4px 4px 0 0;
-webkit-border-radius: 4px 4px 0 0;
border-radius: 4px 4px 0 0;
}
.roundbox-bottom
{
-moz-border-radius: 0 0 4px 4px;
-webkit-border-radius: 0 0 4px 4px;
border-radius: 0 0 4px 4px;
}
Notice that radius used for the ‘inside’ rounding is smaller (4px) than the outside radius (6px). This is so the inner radius fills into the outer border – if you use the same size you may have some white space showing between inner and out rounded corners. Experiment with values to see what works – in my experimenting the behavior across browsers here is consistent (thankfully).
These styles can be applied in addition to other styles to make only the top or bottom portions of an element rounded. For example imagine I have styles like this:
.gridheader, .gridheaderbig, .gridheaderleft, .gridheaderright
{
padding: 4px 4px 4px 4px;
background: #003399 url(images/vertgradient.png) repeat-x;
text-align: center;
font-weight: bold;
text-decoration: none;
color: khaki;
}
.gridheaderleft
{
text-align: left;
}
.gridheaderright
{
text-align: right;
}
.gridheaderbig
{
font-size: 135%;
}
If I just apply say gridheader by itself in HTML like this:
<div class="roundbox boxshadow" style="width: 550px; border: solid 2px steelblue">
<div class="gridheaderleft">Box with a Header</div>
<div class="boxcontenttext" style="background: khaki;">
Simple Rounded Corner Box.
</div>
</div>
This results in a pretty funky display – again due to the fact that the inner elements render square rather than rounded corners:
If you look close again you can see that both the header and the main content have square edges which jumps out at the eye. To fix this you can now apply the roundbox-top and roundbox-bottom to the header and content respectively:
<div class="roundbox boxshadow" style="width: 550px; border: solid 2px steelblue">
<div class="gridheaderleft roundbox-top">Box with a Header</div>
<div class="boxcontenttext roundbox-bottom" style="background: khaki;">
Simple Rounded Corner Box.
</div>
</div>
Which now gives the proper display with rounded corners both on the top and bottom:
All of this is sweet to be supported – at least by the newest browser – without having to resort to images and nasty JavaScripts solutions. While this is still not a mainstream feature yet for the majority of actually installed browsers, the majority of browser users are very likely to have this support as most browsers other than IE are actively pushing users to upgrade to newer versions. Since this is a ‘visual display only feature it degrades reasonably well in non-supporting browsers: You get an uninteresting square and non-shadowed browser box, but the display is still overall functional.
The main sticking point – as always is Internet Explorer versions 8.0 and down as well as older versions of other browsers. With those browsers you get a functional view that is a little less interesting to look at obviously:
but at least it’s still functional. Maybe that’s just one more incentive for people using older browsers to upgrade to a more modern browser :-)
Creating Dialog Related Styles
In a lot of my AJAX based applications I use pop up windows which effectively work like dialogs. Using the simple CSS behaviors above, it’s really easy to create some fairly nice looking overlaid windows with nothing but CSS.
Here’s what a typical ‘dialog’ I use looks like:
The beauty of this is that it’s plain CSS – no plug-ins or images (other than the gradients which are optional) required. Add jQuery-ui draggable (or ww.jquery.js as shown below) and you have a nice simple inline implementation of a dialog represented by a simple <div> tag.
Here’s the HTML for this dialog:
<div id="divDialog" class="dialog boxshadow" style="width: 450px;">
<div class="dialog-header">
<div class="closebox"></div>
User Sign-in
</div>
<div class="dialog-content">
<label>Username:</label>
<input type="text" name="txtUsername" value=" " />
<label>Password</label>
<input type="text" name="txtPassword" value=" " />
<hr />
<input type="button" id="btnLogin" value="Login" />
</div>
<div class="dialog-statusbar">Ready</div>
</div>
Most of this behavior is driven by the ‘dialog’ styles which are fairly basic and easy to understand. They do use a few support images for the gradients which are provided in the sample I’ve provided. Here’s what the CSS looks like:
.dialog
{
background: White;
overflow: hidden;
border: solid 1px steelblue;
-moz-border-radius: 6px 6px 4px 4px;
-webkit-border-radius: 6px 6px 4px 4px;
border-radius: 6px 6px 3px 3px;
}
.dialog-header
{
background-image: url(images/dialogheader.png);
background-repeat: repeat-x;
text-align: left;
color: cornsilk;
padding: 5px;
padding-left: 10px;
font-size: 1.02em;
font-weight: bold;
position: relative;
-moz-border-radius: 4px 4px 0px 0px;
-webkit-border-radius: 4px 4px 0px 0px;
border-radius: 4px 4px 0px 0px;
}
.dialog-top
{
-moz-border-radius: 4px 4px 0px 0px;
-webkit-border-radius: 4px 4px 0px 0px;
border-radius: 4px 4px 0px 0px;
}
.dialog-bottom
{
-moz-border-radius: 0 0 3px 3px;
-webkit-border-radius: 0 0 3px 3px;
border-radius: 0 0 3px 3px;
}
.dialog-content
{
padding: 15px;
}
.dialog-statusbar, .dialog-toolbar
{
background: #eeeeee;
background-image: url(images/dialogstrip.png);
background-repeat: repeat-x;
padding: 5px;
padding-left: 10px;
border-top: solid 1px silver;
border-bottom: solid 1px silver;
font-size: 0.8em;
}
.dialog-statusbar
{
-moz-border-radius: 0 0 3px 3px;
-webkit-border-radius: 0 0 3px 3px;
border-radius: 0 0 3px 3px;
padding-right: 10px;
}
.closebox
{
position: absolute;
right: 2px;
top: 2px;
background-image: url(images/close.gif);
background-repeat: no-repeat;
width: 14px;
height: 14px;
cursor: pointer;
opacity: 0.60;
filter: alpha(opacity="80");
}
.closebox:hover
{
opacity: 1;
filter: alpha(opacity="100");
}
The main style is the dialog class which is the outer box. It has the rounded border that serves as the outline. Note that I didn’t add the box-shadow to this style because in some situations I just want the rounded box in an inline display that doesn’t have a shadow so it’s still applied separately. dialog-header, then has the rounded top corners and displays a typical dialog heading format. dialog-bottom and dialog-top then provide the same functionality as roundbox-top and roundbox-bottom described earlier but are provided mainly in the stylesheet for consistency to match the dialog’s round edges and making it easier to remember and find in Intellisense as it shows up in the same dialog- group.
dialog-statusbar and dialog-toolbar are two elements I use a lot for floating windows – the toolbar serves for buttons and options and filters typically, while the status bar provides information specific to the floating window. Since the the status bar is always on the bottom of the dialog it automatically handles the rounding of the bottom corners.
Finally there’s closebox style which is to be applied to an empty <div> tag in the header typically. What this does is render a close image that is by default low-lighted with a low opacity value, and then highlights when hovered over. All you’d have to do handle the close operation is handle the onclick of the <div>. Note that the <div> right aligns so typically you should specify it before any other content in the header.
Speaking of closable – some time ago I created a closable jQuery plug-in that basically automates this process and can be applied against ANY element in a page, automatically removing or closing the element with some simple script code. Using this you can leave out the <div> tag for closable and just do the following:
To make the above dialog closable (and draggable) which makes it effectively and overlay window, you’d add jQuery.js and ww.jquery.js to the page:
<script type="text/javascript" src="../../scripts/jquery.min.js"></script>
<script type="text/javascript" src="../../scripts/ww.jquery.min.js"></script>
and then simply call:
<script type="text/javascript">
$(document).ready(function () {
$("#divDialog")
.draggable({ handle: ".dialog-header" })
.closable({ handle: ".dialog-header",
closeHandler: function () {
alert("Window about to be closed.");
return true; // true closes - false leaves open
}
});
});
</script>
* ww.jquery.js emulates base features in jQuery-ui’s draggable. If jQuery-ui is loaded its draggable version will be used instead
and voila you have now have a draggable and closable window – here in mid-drag:
The dragging and closable behaviors are of course optional, but it’s the final touch that provides dialog like window behavior.
Relief for older Internet Explorer Versions with CSS Pie
If you want to get these features to work with older versions of Internet Explorer all the way back to version 6 you can check out CSS Pie. CSS Pie provides an Internet Explorer behavior file that attaches to specific CSS rules and simulates these behavior using script code in IE (mostly by implementing filters). You can simply add the behavior to each CSS style that uses box-shadow and border-radius like this:
.boxshadow
{
-moz-box-shadow: 3px 3px 5px #535353;
-webkit-box-shadow: 3px 3px 5px #535353; box-shadow: 3px 3px 5px #535353;
behavior: url(scripts/PIE.htc);
}
.roundbox
{ -moz-border-radius: 6px 6px 6px 6px;
-webkit-border-radius: 6px; border-radius: 6px 6px 6px 6px;
behavior: url(scripts/PIE.htc);
}
CSS Pie requires the PIE.htc on your server and referenced from each CSS style that needs it. Note that the url() for IE behaviors is NOT CSS file relative as other CSS resources, but rather PAGE relative , so if you have more than one folder you probably need to reference the HTC file with a fixed path like this:
behavior: url(/MyApp/scripts/PIE.htc);
in the style. Small price to pay, but a royal pain if you have a common CSS file you use in many applications.
Once the PIE.htc file has been copied and you have applied the behavior to each style that uses these new features Internet Explorer will render rounded corners and box shadows! Yay!
Hurray for box-shadow and border-radius
All of this functionality is very welcome natively in the browser. If you think this is all frivolous visual candy, you might be right :-), but if you take a look on the Web and search for rounded corner solutions that predate these CSS attributes you’ll find a boatload of stuff from image files, to custom drawn content to Javascript solutions that play tricks with a few images. It’s sooooo much easier to have this functionality built in and I for one am glad to see that’s it’s finally becoming standard in the box.
Still remember that when you use these new CSS features, they are not universal, and are not going to be really soon. Legacy browsers, especially old versions of Internet Explorer that can’t be updated will continue to be around and won’t work with this shiny new stuff. I say screw ‘em: Let them get a decent recent browser or see a degraded and ugly UI. We have the luxury with this functionality in that it doesn’t typically affect usability – it just doesn’t look as nice.
Resources
Download the Sample
The sample includes the styles and images and sample page as well as ww.jquery.js for the draggable/closable example.
Online Sample
Check out the sample described in this post online.
Closable and Draggable Documentation
Documentation for the closeable and draggable plug-ins in ww.jquery.js. You can also check out
the full documentation for all the plug-ins contained in ww.jquery.js here.
© Rick Strahl, West Wind Technologies, 2005-2011Posted in HTML CSS