Transparent Borders with background-clip

Avatar of Chris Coyier
Chris Coyier on (Updated on )

UGURUS offers elite coaching and mentorship for agency owners looking to grow. Start with the free Agency Accelerator today.

Have you ever seen an element on a page with transparent borders? I think Facebook originally popularized it giving birth to lightbox plugins like Facebox. I don’t think Facebook sports the look anymore, but it’s still rather neat.

You might think it would be as simple as this:

#lightbox {
   background: white;
   border: 20px solid rgba(0, 0, 0, 0.3);
}

However, setting a transparent border on an element will reveal the elements own background underneath the border.

In the screenshot above, the borders use RGBa to be transparent, but they appear solid gray because they are only revealing the solid white background of itself below.

Fortunately there is a CSS3 property to save us! It’s called background-clip and it’s used specifically to specify which portion of the box model should be utilized to display the background. It does what it sounds like it does, it cuts off the background at the specified portion of the box. There are three values it can have, and vendor prefixes do get involved. Here are the three settings it could have. You wouldn’t use them all at once, this is for convenience of displaying only:

#lightbox {

  -moz-background-clip: border;     /* Firefox 3.6 */
  -webkit-background-clip: border;  /* Safari 4? Chrome 6? */
  background-clip: border-box;      /* Firefox 4, Safari 5, Opera 10, IE 9 */
				
  -moz-background-clip: padding;     /* Firefox 3.6 */
  -webkit-background-clip: padding;  /* Safari 4? Chrome 6? */
  background-clip: padding-box;      /* Firefox 4, Safari 5, Opera 10, IE 9 */
				
  -moz-background-clip: content;     /* Firefox 3.6 */
  -webkit-background-clip: content;  /* Safari 4? Chrome 6? */
  background-clip: content-box;      /* Firefox 4, Safari 5, Opera 10, IE 9 */
				
}

Here are the schematics:

So I’m sure you see where I’m going here… if we set the background-clip to the padding-box, the white background will end before the border and the transparency will lay over other content acheiving the look we are going for!


View Demo

Related: background-origin

In our lightbox example, it’s most likely that the background is a solid color. In that case, background-origin is rather irrelevant, as nobody will ever be able to tell where the color “started” from. However, if the background of the element is an image, it can be quite important where the origin point of the background starts.

This is related to background-clip, because if the background-clip is the padding-box but the background-origin is left at the default border-box, some of the background-image will be cut off, which may or not be desireable.

Here is the schematic:

And a visual example:

Browser Compatibility

Works in: Safari 5, Chrome 7, Firefox 3.6+, Opera 10, IE 9

I only tested these modern browsers and support is good. It may (and likely does) go back a bit further in the non-IE browsers.

If you’d more complete browser compatibility, you can always go with the double-div method.

<div id="lightbox">
   /* Set transparent background with PNG
       add padding to push inside box inward */

   <div id="lightbox-inside">
      /* Set white background in here */
   </div>

</div>

Another advantage to the double-div method is that you could achieve truly rounded borders. Unfortunately with the background-clip method, the outer border is round but the edge of the background stays straight-cornered.

Too bad we don’t have something like background-radius to fix it:

#lightbox
   border-radius: 16px;
   padding: 8px;

   /* NOT REAL */
   background-radius: 8px;
}

Weirdnesses

20px of border was fine, but when I tried 30px, these mini boxes of death showed up in Safari 5.

In Chrome, little diagonal lines were present at any border width up to 20px.

Above 20px border, the corners completely darken.

Without border-radius, darkened corner boxes are always visible.

Thanks

Thanks to Alex Hall for the original idea and help.

Here’s a simple demo showing the different values of background-clip as well:

Check out this Pen!

and background-origin:

Check out this Pen!