CodeinWP CodeinWP

Multiple Borders with CSS

Multiple Borders with CSSWhile fiddling around with the CSS3 box-shadow property, I stumbled across a method to put a double border on a single element. I thought to myself, that’s pretty cool, but obviously, it will only work in newer browsers that support box-shadow.

So I wondered how many different ways there are to create an element that has the appearance of a double border. Naturally, the most common way is by using a non-fluid background image. But that’s obviously not ideal.

So, I’ve compiled five different methods for doing this. Only one requires use of an image; the rest are pure CSS, with pretty good browser support for all methods. For brevity, in the code examples I’ve removed the common stuff like width, height, background, etc. You can view all the examples on the demo page:

Method 1: Border and Outline

This method will only work on browsers that support the outline property, so that means everything but IE6/7. Basically, you add a border using both the border and outline properties. Here’s the CSS, not including the stuff that’s common to all the examples (like width, float, background, etc):

.one {
  border: solid 6px #fff;
  outline: solid 6px #888;  
}

The reason it works is because an outline is always placed outside of the box. The problem with the outline property is that it doesn’t affect the flow of elements around it, so it will overlap or underlap other elements, so that could be undesirable.

Method 2: A Pseudo-Element

This one’s a bit tricky, because it requires (from what I can tell) absolutely positioning the border—which would seem to make it non-fluid. Well, using a bit of trickery, I was able to make this method work and be vertically fluid. Here’s the pertinent code:

.two {
  border: solid 6px #fff;
  position: relative;
  z-index: 1;
}

.two:before {
  content: "";
  display: block;
  position: absolute;
  top: -12px;
  left: -12px;
  border: solid 6px #888;
  width: 312px;
  padding-bottom: 12px;
  min-height: 100%;
  z-index: 10;
}

The key parts are the z-index settings (to keep the pseudo-element from overlapping the content), the positioning, and the min-height value. The latter keeps the fluidity intact.

Method 3: Box Shadow

As mentioned, the idea for this experiment was the result of serendipitous fiddling with box-shadow settings. I personally like this one the best, because it’s just one line of code, and it uses a new technology in an unexpected way.

.three {
  box-shadow: 0 0 0 6px #fff, 0 0 0 12px #888;
}

To make the shadow appear like a double border, I’m using two shadows (comma separated) and I’ve set the offset and blur settings to zero, while giving each shadow an appropriate size. Because one overlaps the other, the second shadow is twice the size of the other. The key parts are the lack of blur and a fully opaque color. This gives each shadow a straight edge, just like a border.

Just like the outline property, box-shadow will not impact elements around it, so you might have to fiddle with margins to position it so that it looks like a regular box with a border.

Naturally, this is limited to browsers that support box-shadow.

Method 4: An Extra Div

This method nests an extra <div> to give the appearance of a double border. This is the only one of these methods listed here that works everywhere (although even this one looks a bit whacked in my demo in IE6/7 because of margin settings, but that can be corrected). Not much else to say about this one, just a natural use of borders and backgrounds:

.four {
  border: solid 6px #888;
  background: #fff;
  width: 312px;
  min-height: 312px;
}

.four div {
  width: 300px;
  min-height: 300px;
  background: #222;
  margin: 6px auto;
  overflow: hidden;
}

The styles for this method would vary depending on the size and context of the box, but as you can see, the outer box is 12 pixels bigger than the inner box, to accommodate the space that lets the background peek through, giving the illusion of two borders on a single element.

Method 5: Border Image

Another modern-browser method, this one uses the often-forgotten CSS3 border-image property:

.five {
  border-width: 12px;
  -webkit-border-image: url(multiple-borders.gif) 12 12 12 12 repeat;
  -moz-border-image: url(multiple-borders.gif) 12 12 12 12 repeat;
  border-image: url(multiple-borders) 12 12 12 12 repeat; /* for Opera */
}

For an explanation of border-image see this post on SitePoint.

Any Other Methods?

I couldn’t think of any other methods to do this, so somehow I feel like I’ve overlooked something obvious. I’m sure someone will point it out if I have.

I’ve put all the methods in a demo page along with some JavaScript that will allow you to add and remove content from each box, so you can see that the box is not restricted to a single height.

40 Responses

  1. Scott says:

    Well there is the obvious (to me) border-style: double but that’s pretty limited in what you can do. Basically 3 borders with 2 colours (if you include the background).

    I was thinking that you should be able to do something with gradients and color-stops but maybe that’s just for backgrounds. In theory you can do a border on one side of a box, or two opposite sides, using a background.

    • Nice, I didn’t realize there was a “double” value for border-style. But yeah, pretty limited, but I suppose it’s an option depending how the different browsers display it.

  2. Andrei says:

    It shoul be as easy as

    
    border: 6px solid #fff, 12px solid #888;
    

    It isn’t unfortunately.

  3. Pierre says:

    Well, I just used it playing with padding! My div had a single (non-transparent) image inside, so I just used a padding:5px; with a background-color:#your-color; … And the border just wraps around this div! Simple but effective.

  4. IT Mitică says:

    I’m on my way out right now but I’ve got for you a quick idea to consider: CSS3 box-sizing property.

  5. TheAL says:

    Would be awesome if you could do:

    
    .class {
    border-1: 1px solid #ffffff;
    border-2: 1px solid #000000;
    border-3: 2px solid #ff0000;
    }
    

    Through infinity, or what have you…

  6. Wabbaly says:

    adding images as borders got my attention, as for the big picture, I prefer playing with the padding. why replace it if it is not broken?
    keep them coming!

  7. IT MiticÄ says:

    Here’s an article I wrote as a response: http://www.itmitica.com/en/articles/css3/m-borders/

    I’ve used nested divs as markup and display: table-cell as style to build a model that allows for multiple legitimate borders.

    Obviously I’m one of those developers: I don’t think I need to cover for older browser for stuff like this.

    • Well, the nesting makes it quite unusable, but I’m wondering if there’s something inherent in using display: table-cell to get multiple borders to work. I’ve never played around with those display values, so I’m really not sure off the top of my head.

      • IT MiticÄ says:

        I’m not sure why you’re saying the nesting makes it unusable. div nesting as a CSS practice has been around for quite some time: rounded corners, sliding doors etcetera.

        On the plus side, you get real borders that behave and accept real border properties, including CSS3 newest border properties.

        As for display: table-cell, it works perfectly fine, except for older browsers like IE7, a problem that can be solved with some extra effort.

        I’ve updated the article: http://www.itmitica.com/en/articles/css3/m-borders/ in an attempt to answer your question about inherent behavior. Let me know if I’ve understood correctly your question.

        • I think it’s not as usable, because you’re nesting a lot of divs, but you have a lot more borders on that one, so it’s understandable. I think in that case, it might be better to choose something like box-shadow, while falling back to a simpler border for IE. Or else just use images.

          Anyhow, thanks for the feedback and for the example.

          • IT MiticÄ says:

            No problem, just my two cents on the matter.

            One last thing. Your example using divs presented some margin problems. The real gain with using display: table-cell is that I don’t have to worry about margins even when I decide to go with fixed width.

    • Daan says:

      You’ve got a serious case of divitis. I would stay away from doing it like that. It’s like saying “but tables for layout work, so why do it differently?”. It’s bad for maintainability and semantically it makes no sense.

      • IT MiticÄ says:

        Hi Daan.

        I’m not sure how closely you’ve looked at my example or how well you’ve read the observations. I’ve used an exaggerated number of divs, four, just to outline the model. I can’t think of a scenario requiring four borders on an element. So I have to disagree, it’s not remotely close to a divitis scenario.

        Further more, if you’re looking for semantics in a CSS styling model that’s using divs, you’re in bad luck. Certainly I’m not trying to convey any meaning with my multiple borders construct, and certainly I can’t think of other suitable elements for my CSS multiple borders construct.

        HTML5 specs, much like HTML 4 / XHTML 1.0 specs, still have to say this about the div element: “The div element has no special meaning at all. […] Authors are strongly encouraged to view the div element as an element of last resort, for when no other element is suitable.”

        Finally, you’re getting a little weird here. I’m not sure I understand your tables for layout reference in this context. display: table, display: table-cell are powerful CSS (as in style) tools that have nothing to do with HTML (as in markup) tables past misuse.

      • Noon says:

        Daan, here’s an instructive article by a fellow Canadian of yours “It’s not divitis” http://snook.ca/archives/html_and_css/its_not_divitis/ you may find useful. It’s quite old, but so are your concerns.

  8. csschops says:

    I love the smartness and simplicity of method three, but on balance I’ll plumb for method one – and ie6/7 be damned. Great tinkerings!

  9. Simon Day says:

    I kbnow that Mozilla supports border gradiants as I added them to my site last year. My URL so you can see it is:
    http://www.simonday.com/web-design-blog/

    The code is:

    
    .yourstyle {
    	border: 8px solid #69c;
    	-moz-border-bottom-colors:#546e78 #73929d #9bb1b9 #afc1c7 #c3d0d5;
    	-moz-border-top-colors:#546e78 #73929d #9bb1b9 #afc1c7 #c3d0d5;
    	-moz-border-left-colors:#546e78 #73929d #9bb1b9 #afc1c7 #c3d0d5;
    	-moz-border-right-colors:#546e78 #73929d #9bb1b9 #afc1c7 #c3d0d5;
    }
    

    I believe that Chrome also now supports it but I haven’t looked into it yet.

  10. Philipp says:

    Thats pretty cool, but what can i do, if I need a top-border on my site? Your examples shouldnt work in this case, or?

  11. Jami says:

    Beat me to it guys my favourite and great for most images. Solid in ie also
    Jimmy

  12. Jason M says:

    I used the double div solution. Basically this code is for two-1px borders. Works for me. Not too sure how the code handles in IE6/IE7, but seems fine in everything else (for the purpose I’m using it for).

    #icons_container {
    border: 1px solid #a95759;
    padding: 1px;
    }
    #icons {
    width: 100%;
    height: 100%;
    background: #aa5958;
    }

  13. This is definitely the most exhaustive list on the net about ways of creating multiple borders in CSS. I thought that border-radius in itself supports multiple border, but seems that we still need to use some hacks to get to the result.

    Thanks.

  14. J Smilanic says:

    This is actually what I was looking for. Thanks!

  15. irakli says:

    method 1 is good, because its ver short and simple. but a have a problem with it: border radius works inside the outline and dont looks good. without border radius if the element dont needs border radius its cool

  16. Bird says:

    Thanks for the post! I found this pretty helpful. I actually ended up using a combination of a couple of your examples to achieve the desired effect.


    border: solid 2px #ccc;
    box-shadow: 0 0 0 10px #ccc;
    outline: solid 8px #fff;

  17. Alejandro says:

    Excelent! I liked the third way too. Thanks a lot.

  18. Joy says:

    Please forgive in advance. But all I have to say is you are super freaking fantastic. Wow! I had to get that out there. I am a designer who of course is still developing as we all continually do. Web Development is a daily learning skill.

    So I am extremely comfy with rounded corners and border effects. But decided to tone down a personal color choice by removing background color and using lines instead. I am using a template and trying to work with divs in template. So I tried using a double line with border-top in footer area and spent all day searching the web to find ways to style it since I couldnt figure out how to get the container above the footer to just style the border bottom downwards with rounded corner as opposed to rounding upwards.

    I decided to try to style the same div that I know I got the round border-top left and right corners rounded and try to find another element that would allow me to get a second border with different color and still rounded corner a top. Your site is the only one that got me the result needed. Thank you. Sorry if I confused you with my ramblings. One new lesson learned today.

    Cheers

  19. Craig says:

    I think you can simplify the style sheet for number 2 a bit:

    
    .two:before {
    	content: "";
    	position: absolute;
    	top: -12px;
    	bottom: -12px;
    	left: -12px;
    	right: -12px;
    	border: solid 6px #888;
    }
    
    • Demo or it didn’t happen. :)

      • Craig says:

        Demo

        One nice thing about this change is that it also facilitates horizontal fluidity instead of just vertical fluidity. I illustrated this in the demo.

        I also deleted all the z-indices. They weren’t necessary in this case.

        Thanks for putting this page up. I found a lot of good ideas from it.

        • Yeah, looks like you’re right, the z-index may not be necessary. But it’s possible the z-index was an issue in IE8 or something like that, which could be why I included it. I notice you’re missing the min-height value on the pseudo-element, but instead you’ve moved it to the main element. And yeah, a few of the other properties seem to be redundant.

          Thanks, always nice to see stuff optimized. I guess with demo pages, I like to be explicit about all properties, just to make sure it’s clear what I’m doing.

  20. Jake says:

    This post may be old but it’s still coming up in searches and I can’t even begin to tell you how incredibly helpful it was! Just wanted to say thanks so much for pointing me in a couple of really good directions as opposed to continuing to bang my head against the keyboard! I ended up modifying the double div route a bit and it worked like a charm!

  21. Schmüdde says:

    Love this box-shadow trick. Thank you!

    Schmüdde

  22. J says:

    Try this:
    .element {
    border-bottom: 1px solid #000;
    -webkit-box-shadow: 0px 3px 0px 0px #fff, 0px 10px 0px 0px #000;
    }

    http://jsfiddle.net/6UFX7/8351/

    It uses the box shadow property mentioned above, but also uses a basic border to achieve a double line effect with varying widths.

  23. Sam says:

    Well The simplest way to do double borders would be to have your outer border defined by your div (or li element) say.

    And then display block an anchor or image or label and border that.

    you may have to size things appropriately……

  24. Ashton says:

    How about something like this:

    .object {

    border: 2px solid red;
    outline: 2px solid green;
    box-shadow: 0 0 0 4px yellow;

    }

Leave a Reply

Comment Rules: Please use a real name or alias. Keywords are not allowed in the "name" field and deep URLs are not allowed in the "Website" field. If you use keywords or deep URLs, your comment or URL will be removed. No foul language, please. Thank you for cooperating.

Markdown in use! Use `backticks` for inline code snippets and triple backticks at start and end for code blocks. You can also indent a code block four spaces. And no need to escape HTML, just type it correctly but make sure it's inside code delimeters (backticks or triple backticks).