CSS Borders Guide: Types, Tricks, Transparent, Inner, and Multiple Borders

- Andrés Cruz - ES En español

CSS Borders Guide: Types, Tricks, Transparent, Inner, and Multiple Borders

CSS borders are fundamental properties that you can apply to virtually any HTML element: top, bottom, sides, with different styles and thicknesses. In this comprehensive guide, we cover everything you need to know: from how to use border-width, border-style, and border-color, to advanced techniques like multiple borders with box-shadow, transparent borders with rgba() + background-clip, and inner borders that don't affect the layout. If you want to review how to adjust images with CSS without distorting them, take a look at the object-fit property in CSS.

With the border property, it is possible to define the color, thickness, and style of each of the 4 sides that make up an element's box. Let's look at each sub-property:

border-width

Defines the width of the border. It can be controlled side by side using the following individual properties:

  • border-top-width
  • border-right-width
  • border-bottom-width
  • border-left-width

Each property is self-explanatory: it accepts any valid CSS unit of measurement (px, em, rem, etc.).

If you want to set all borders at once, use the shorthand:

  • border-width

It accepts from one to four values, following the same pattern of top right bottom left as other box properties in CSS:

border-width: 4px 5px 6px 7px;
  • top: top border 4px
  • right: right border 5px
  • bottom: bottom border 6px
  • left: left border 7px
border-width: 4px 5px 6px;
  • top: top border 4px
  • right and left: right and left borders 5px
  • bottom: bottom border 6px
border-width: 4px 5px;
  • top and bottom: top and bottom borders 4px
  • right and left: right and left borders 5px
border-width: 4px;
  • All borders: 4px

border-style

Defines the visual style of the border. The available values are:

  • solid — continuous line, the most used
  • dashed — dashed line
  • dotted — dotted line
  • double — double solid line
  • groove — 3D grooved effect
  • ridge — 3D ridged effect (inverse of groove)
  • inset — border with inset look
  • outset — border with outset look

It is also possible to define them side by side using individual properties:

  • border-top-style
  • border-right-style
  • border-bottom-style
  • border-left-style

Or all together with the shorthand border-style. It works exactly the same as border-width: it accepts one to four values applying the same top right bottom left order.

border-color

Defines the color of the border. Accepts any CSS color format: English color name (red, blue), hexadecimal (#F00000), rgb(), rgba(), or hsl():

#border-color1 {
    border-color: #F00000;
}

You can also define it for each side:

  • border-top-color
  • border-right-color
  • border-bottom-color
  • border-left-color

Its behavior follows the same pattern as border-width.

Examples of border types in CSS

border-style and border-color:

#solid {
    border-color: #F00000;
    border-style: solid;
}
#dashed {
    border-color: #F00000;
    border-style: dashed;
}
#dotted {
    border-color: #F00000;
    border-style: dotted;
}   
#groove {
    border-color: #F00000;
    border-style: groove;
}
#ridge {
    border-color: #F00000;
    border-style: inset;
} 
#outset {
    border-color: #F00000;
    border-style: outset;
}  
#double {
    border-color: #F00000;
    border-style: double;
}

Shorthand border — border-style, border-color, and border-width in a single property:

It is also possible to define all properties at the same time using the shorthand border, which accepts thickness, color, and style in any order:

#border1 {
    border: 2px #F00000 solid;
}
#border2 {
    border-width: 2px;
    border-color: #F00000;
    border-style: solid;
}

Both declarations produce the exact same visual result; the only difference is the amount of code lines. In real projects, I usually prefer the shorthand border when all four sides are equal, and reserve individual properties when I need asymmetric configurations.

Multiple borders in a container with CSS

Multiple borders in a container with CSS

The border property only allows one border per element. If you need to simulate multiple borders, the trick lies in the box-shadow property: it accepts a comma-separated list of shadows, and when configured without offset or blur, they visually act like stacked borders.

Syntax of the box-shadow property

box-shadow: x y blur spread color inset;
ValueDescription
xRequired. Horizontal offset of the shadow.
yRequired. Vertical offset of the shadow.
blurOptional. Blur radius. At zero, the border has a sharp edge.
spreadOptional. Expansion radius (spread). Controls how much the shadow grows outward.
colorOptional. Color of the shadow.
insetOptional. If present, the shadow appears inside the element instead of outside.

 

Creating multiple borders with box-shadow

The key is to use only the spread parameter to control the thickness of each border, leaving x, y, and blur at zero:

box-shadow: x y blur spread color;

With this, we create two borders of 2px each; the first one green and the second one red:

box-shadow: 0 0 0 2px green, 0 0 0 4px red;
 

We can also vary the size of each border independently:

box-shadow: 0 0 0 2px green, 0 0 0 6px red;
 

Or stack as many borders as we want in the same container:

box-shadow: 0 0 0 2px green, 0 0 0 4px red, 0 0 0 6px blue, 0 0 0 8px yellow; 
 

Important considerations

  • The first three values of box-shadow (x, y, and blur) must be set to 0. This keeps the shadow centered and symmetrical relative to the container, and the resulting border is solid — without blur or offset.
  • Each subsequent border must have a larger spread than the previous one; otherwise, the inner border overlaps the outer one. For example, this declaration produces only a green border because both have the same size:

    box-shadow: 0 0 0 3px green, 0 0 0 3px red;
     

    The red border remains hidden underneath the green one because they have the same spread radius. The solution is to increase the value of each successive border so that the multiple borders effect becomes visible.

CSS Trick: transparent borders with rgba() and background-clip

Transparent borders in CSS with rgba and background-clip

If you've ever tried to set a "transparent" border in CSS and discovered that it looked gray or completely opaque, don't worry: it has happened to all of us. The good news is that the trick to achieving truly transparent borders is simple once you know the secret ingredient.
I had to learn it while designing a custom button, the kind where you want the interface to look modern without cluttering it. That's when I discovered that border transparency doesn't depend solely on rgba(), but on how the background behaves underneath.

In this guide, I'll tell you exactly how to do it, why it works, and how to apply useful variations to buttons, cards, and UI components.

What are transparent borders in CSS and what are they used for?

In CSS, a transparent border is simply a border whose color includes an opacity channel. This is achieved with rgba() or hsla().
The beauty is that the container "lets you see" what is underneath: it can be a solid color, an image, or a gradient.

They serve to:

  • Create smoother, more modern components.
  • Buttons with a glassy effect (I use them a lot in minimalist designs).
  • Cards where you want a visible yet subtle border.
  • Glassmorphism style UI effects.

However, for the border to actually look transparent —and not gray or "dirty"— you need to understand a detail of the CSS box model.

We will see a neat trick that allows the borders of our element containers or HTML tags to look transparent.

The main method: rgba() + background-clip

This is the method that works in all cases and the one you will see in any modern project:

.contenedor {
   background-color: white;
   border: 20px solid rgba(0, 0, 0, 0.5);
   background-clip: padding-box;
}

Why does the border look opaque even if you use rgba()?

This happens because, by default, the background extends beneath the border area.
When the background is white, that white blends with the border's transparency and makes it look gray instead of transparent.

This is precisely what I discovered the first time I tried to add transparency to a button: instead of an elegant border, I got an ugly gray. I thought the rgba was wrong… but no: it was the background getting where it shouldn't.

How background-clip: padding-box works

The key property that solves all of this is:

background-clip: padding-box;

In simple terms:

  • border-box (default value): the background extends to the border edge → transparency is ruined.
  • padding-box: the background is clipped before the border → the border looks just as it should.

Simple rule: if you want transparent borders, always use background-clip: padding-box.

Practical examples of transparent borders in CSS

Basic transparent borders with rgba()

.caja {
   background-color: white;
   border: 15px solid rgba(0, 0, 0, 0.5);
   background-clip: padding-box;
   padding: 20px;
}

Semi-transparent borders with rounded corners

.caja-redonda {
   background-color: white;
   border: 10px solid rgba(255, 0, 0, 0.4);
   background-clip: padding-box;
   border-radius: 12px;
   padding: 15px;
}

The trick works exactly the same with border-radius, regardless of the value.

Custom buttons with transparent border

I usually use transparent borders on buttons when I want a lighter look. For example:

.boton-transparente {
   padding: 12px 20px;
   background-color: white;
   border: 2px solid rgba(0, 0, 0, 0.3);
   background-clip: padding-box;
   border-radius: 8px;
   font-weight: bold;
   cursor: pointer;
   transition: 0.3s;
}
.boton-transparente:hover {
  border-color: rgba(0, 0, 0, 0.6);
}

I use it a lot when I want a custom button without resorting to the classic outline style: transparency softens everything and makes it more elegant.

Alternative techniques for achieving transparent borders

These variants allow you to play with more advanced styles or animations.

1. Using box-shadow as a border
.caja-shadow {
   background: white;
   padding: 20px;
   box-shadow: 0 0 0 5px rgba(0,0,0,0.3);
}

Advantages:

  • You can achieve softer or blurred borders.
  • Ideal for glassmorphism effects.
2. Using border-image with gradients
.caja-degradada {
   border: 6px solid transparent;
   border-image: linear-gradient(to right, transparent, rgba(0,0,0,0.4)) 1;
}

Perfect for "glowing" or stylized borders. Keep in mind that border-image is not compatible with border-radius, so use it when you don't need rounded corners.

3. Transparency + hover with animation
.efecto-hover {
   border: 4px solid rgba(0,0,0,0.2);
   background-clip: padding-box;
   transition: border-color 0.3s ease;
}
.efecto-hover:hover {
   border-color: rgba(0,0,0,0.6);
}

I use it on buttons when I want the border to seem to gradually "materialize" on mouse hover.

Transparent borders step by step

This trick is really simple; if we want to have transparent borders like the following in our boxes:

This is a lot of dummy text meant to show what transparent borders look like on a floating container. This is a lot of dummy text meant to show what transparent borders look like on a floating container. This is a lot of dummy text meant to show what transparent borders look like on a floating container. This is a lot of dummy text meant to show what transparent borders look like on a floating container. This is a lot of dummy text meant to show what transparent borders look like on a floating container. This is a lot of dummy text meant to show what transparent borders look like on a floating container. This is a lot of dummy text meant to show what transparent borders look like on a floating container. This is a lot of dummy text meant to show what transparent borders look like on a floating container. This is a lot of dummy text meant to show what transparent borders look like on a floating container. This is a lot of dummy text meant to show what transparent borders look like on a floating container. This is a lot of dummy text meant to show what transparent borders look like on a floating container.

My transparent borders with a bit of CSS.

Two steps to achieve the effect

  • Select a color with an alpha channel using rgba() instead of hex codes or rgb(). The fourth parameter of rgba() controls opacity: 0 is fully transparent and 1 is fully opaque.
  • Apply the property background-clip with the value padding-box. This prevents the background color from extending underneath the border, preserving transparency.

Creating transparent borders

For a black border with 50% transparency, we apply the following rgba value:

rgba(0, 0, 0, 0.5);

And the background-clip property to prevent the background color from ruining the effect:

background-clip: padding-box; 

The complete CSS rule would look like this:

border: 20px solid rgba(0, 0, 0, 0.5);
background-clip: padding-box; 

Finally, we get the following effect:

This is a lot of dummy text meant to show what transparent borders look like on a floating container. This is a lot of dummy text meant to show what transparent borders look like on a floating container. This is a lot of dummy text meant to show what transparent borders look like on a floating container. This is a lot of dummy text meant to show what transparent borders look like on a floating container. This is a lot of dummy text meant to show what transparent borders look like on a floating container. This is a lot of dummy text meant to show what transparent borders look like on a floating container. This is a lot of dummy text meant to show what transparent borders look like on a floating container. This is a lot of dummy text meant to show what transparent borders look like on a floating container. This is a lot of dummy text meant to show what transparent borders look like on a floating container. This is a lot of dummy text meant to show what transparent borders look like on a floating container. This is a lot of dummy text meant to show what transparent borders look like on a floating container.

My transparent borders with a bit of CSS.

Want a semi-transparent red border? Simply change the first three values of rgba:

border: 20px solid rgba(255, 0, 0, 0.5);

And we get:

This is a lot of dummy text meant to show what transparent borders look like on a floating container. This is a lot of dummy text meant to show what transparent borders look like on a floating container. This is a lot of dummy text meant to show what transparent borders look like on a floating container. This is a lot of dummy text meant to show what transparent borders look like on a floating container. This is a lot of dummy text meant to show what transparent borders look like on a floating container. This is a lot of dummy text meant to show what transparent borders look like on a floating container. This is a lot of dummy text meant to show what transparent borders look like on a floating container. This is a lot of dummy text meant to show what transparent borders look like on a floating container. This is a lot of dummy text meant to show what transparent borders look like on a floating container. This is a lot of dummy text meant to show what transparent borders look like on a floating container. This is a lot of dummy text meant to show what transparent borders look like on a floating container.

My transparent borders with a bit of CSS.

And that would be all. As you can see, using the same border property combined with rgba() and background-clip: padding-box you can vary the thickness (in these examples they are 20px) and color, obtaining a clean and truly transparent effect.

CSS Trick: inner borders with box-shadow inset

Inner borders in CSS with box-shadow inset

When you define padding, margin, or border on an element, these properties directly impact its total size. The classic box model calculation would be:

total_width = width + 2*border + 2*padding + 2*margin = 300px + 2*5px + 2*7px +2*5px = 334px;
total_length = height + 2*border + 2*padding + 2*margin = 150px + 2*5px + 2*7px +2*5px = 184px;

A visual aid of the above:

Traditional borders in CSS

What are inner borders in CSS?

Inner borders are borders that do not affect the overall size of the container because they are drawn inside the element's area, not outside. This makes them very useful in fluid layouts where you need multiple elements to occupy an exact percentage of the available width without the border "pushing" them and breaking the row.

1
2
3

Try resizing your browser window.

As you may have noticed in the previous example, these three containers occupy 33% of the total container width. If the borders were traditional ones:

1
2
3

The third container could not align in the same row because the border adds to the total width.

Creating inner borders in CSS with box-shadow inset

The solution lies in the box-shadow property with the inset value. The complete syntax is:

box-shadow: inset offset-x offset-y blur-radius spread-radius color
  • inset: indicates that the shadow will appear inside the container instead of outside.
  • offset-x and offset-y: horizontal and vertical offset. Set them to 0 for symmetrical borders.
  • blur-radius: blur degree. For a sharp border it must be set to 0.
  • spread-radius: controls the thickness of the inner border. This is the key parameter.
  • color: border color in any CSS format (#08B, rgba(), etc.).

Individual side inner borders in CSS

To create a border only on a specific side, use offset-x or offset-y to "push" the shadow towards that side and leave the spread-radius at 0:

13-pixel top border:

box-shadow: inset 0 13px 0 0 #08B;
13px border

13-pixel left border:

box-shadow: inset 13px 0 0 0 #08B;
13px border

13-pixel right border:

box-shadow: inset -13px 0 0  #08B;
13px border

13-pixel bottom border:

box-shadow: inset 0 -13px 0  #08B;
13px borders

Symmetrical inner borders in CSS

To apply the same border on all four sides at once, use 0 for offset-x, offset-y, and blur-radius, and set the desired thickness in spread-radius:

Symmetrical 3-pixel borders:

box-shadow: inset 0 0 0 3px #08B;
3px borders

Symmetrical 7-pixel borders:

box-shadow: inset 0 0 0 7px #08B;
7px borders

Symmetrical 13-pixel borders:

box-shadow: inset 0 0 0 13px #08B;
13px borders

Diagonal borders in CSS

By combining positive and negative values in offset-x and offset-y, you can create inner borders that affect only two opposite corners. These are the four possible cases for 13 pixels:

box-shadow: inset -13px -13px 0 0 #08B;
13px borders
box-shadow: inset 13px -13px 0 0 #08B;
13px borders
box-shadow: inset 13px 13px 0 0 #08B;
13px borders
box-shadow: inset -13px 13px 0 0 #08B;
13px borders

Frequently Asked Questions about borders in CSS

  • Can I make borders completely invisible?
    • Yes, by using the transparent keyword as the color: 
    • border: 10px solid transparent;
    • Very useful for layout tricks using pseudo-elements or for reserving space without displaying the border.
  • Do transparent borders with rgba() work with background images?
    • Yes, as long as you use background-clip: padding-box, the effect works the same with any type of background: flat color, gradient, or image.
  • Can I use hsla() instead of rgba()?
    • Absolutely. The transparency channel works identically in both formats:
    • border: 10px solid hsla(0, 0%, 0%, 0.3);
  • Does border-radius work with box-shadow inset?
    • Yes. The inner shadow respects the border-radius of the element, so you can combine both properties to create rounded inner borders without any issues.
  • Do inner borders with box-shadow affect the layout?
    • No. Unlike border, the box-shadow property does not take up space in the document flow, so it does not alter the size or position of adjacent elements.

Conclusion

CSS borders are far more versatile than they appear at first glance. With the basic properties (border-width, border-style, border-color), you have complete control over each side of the box. And when you need to go further—multiple borders, transparent borders, or borders that don't affect the layout—the box-shadow property combined with background-clip: padding-box is your best ally.

Transparent borders in particular are easy to achieve once you understand the key trick: combining rgba() with background-clip: padding-box. This allows you to build more modern interfaces, cleaner buttons (I use them extensively in my own projects), and visual effects that do not clutter the design.

If you want to take them even further, try the box-shadow or border-image variants to achieve advanced styles without complications.

The next very interesting property to learn about is how you can create reflections on your images using pure CSS and webkit-box-reflect.

Learn to master borders in CSS: key properties, style types, transparent borders using `background-clip`, and multiple inner borders using `box-shadow`.


Únete a la comunidad de desarrolladores que han decidido dejar de picar código y empezar a construir productos reales. Recibe mis mejores trucos de arquitectura cada semana:

I agree to receive announcements of interest about this Blog.