Transparent borders in CSS

Three easy ways to create transparent borders

The first time I encountered a transparent border was in a fairly simple PSD conversion project. I was puttering along, adding some styles to my HTML, and I styled my transparent border in the way that you would style anything else in CSS that you wanted to be transparent:

box {
border: 5px solid rgba(0,0,0, 0.3);
}

I flipped back to my live preview and to my dismay, the border wasn’t transparent at all. I deleted the code and rewrote it (the definition of insanity, I know), and still no transparent border.

What’s the deal with this? Well, it has to do with the box model and default border styles. You may have noticed that when you add a border to your element, the border creeps further inside the box, rather than expanding to fill space on the outside. Because your element and the element background still exist behind the border, giving the border an alpha value doesn’t reveal anything that sits behind the box, only the box itself.

A friend figured out an ingenious way to manage the border situation, and I was super happy using her technique…until I was fiddling around and happened upon two completely different and previously-unknown-to-me ways to create the elusive transparent border!

It should come as no surprise that there are a few different ways to make transparent borders in CSS, since there are multiple ways to do pretty much everything in the wild west of the internet, but that doesn’t mean that I’m not thrilled every time I find new ways of doing things behind the scenes. Here are the two techniques that I came across for creating transparent borders, and one that I absolutely did not stumble upon at all.

Technique 1: outline

While border spreads to the inside of your element, outline grows outside. And because the outline isn’t sitting on top of your element background, that means that it is free to be as transparent as it wants. Set your width, set your alpha value, and boom! Note that because this technique will place the transparent border outside of your box, you’ll need to be mindful of your margins and spacing.

Hot tip: if you want the appearance of a double border that doesn’t touch your regular border, use outline-offset to shift your outline away from the outer border edge.

Transparent border using outline. Note that this border extends beyond the edges of the box, so will affect margins and spacing.

Technique 2: background-clip

I’m pretty sure this is the least hacky of all three methods — it definitely seems the fanciest, since this isn’t a property that a lot of people know about. The background-clip property tells the background where to stop. Its default is border-box, so if you don’t make any adjustments the background will go to the edge of (you guessed it) the element’s border box.

But. If you don’t like that and want your border to occupy the space usually reserved for padding, and you’d like your background to stop before the padding starts, just let the background know you’d like it to stop at the edge of the padding box by using the value (wait for it) padding-box. Because there is no longer a background in the padding area, and the border (by default) spreads into the padding area, this will allow the border to be transparent.

Note the difference in the total space that the element occupies between this image and the image above. The above image has the transparent area outside of the box, and the below image has the transparent area inside the box.

Transparent border using background-clip. Note that the border encroaches on the inside of the box, because it starts at the padding edge.

Technique 3: box-shadow

I take no credit for this; Ellen Probst figured out this really cool method of manipulating box-shadow to give it hard edges and transparency. You can read the details of her technique here.


The more I code, the more I’m able to let go of the idea of a “right way” of doing things, and this is a perfect example of why that’s important. Here are three options that produce a very similar effect, and all of them can be right, depending on your desired layout and how you prefer to write your code.