Quick Tip: Multiple Borders with Simple CSS
videos

Quick Tip: Multiple Borders with Simple CSS

Tutorial Details
  • Topic: CSS Borders
  • Difficulty: Normal
  • Estimated Completion Time: 4 Minutes

Did you know that we can achieve multiple borders with simple CSS, by using the :after amd :before psuedo-classes? This is something I recently learned myself! I’ll show you how to add more depth to your designs, without images, in just a few minutes.


Final Code

<!DOCTYPE html>

<html lang="en">
<head>
	<meta charset="utf-8">
	<title>Multi-Borders</title>
	<style>
		body { background: #d2d1d0; }

		#box {
			background: #f4f4f4;
			border: 1px solid #bbbbbb;
			width: 200px;
			height: 200px;
			margin: 60px auto;
			position: relative;
		}

		#box:before {
			border: 1px solid white;
			content: '';
			width: 198px;
			height: 198px;
			position: absolute;
		}

		#box:after {
			content: '';
			position: absolute;
			width: 196px;
			height: 196px;
			border: 1px solid #bbbbbb;
			left: 1px; top: 1px;
		}
	</style>

</head>
<body>
	<div id="box"></div>
</body>
</html>

In short, any browser that supports the :before and :after psuedo-elements (all major browsers) can take advantage of this effect. Of course, there are alternatives, including the use of box-shadow, as well as adding additional mark-up to the page; however, this is clean solution that you should definitely consider. Thanks for watching!

Add Comment

Discussion 134 Comments

Comment Page 1 of 21 2
  1. drumkeyjw says:

    Thanks so much! I really enjoy these quick tips…

  2. Jon says:

    Jeffrey,

    I just wanted to thank you for the jQuery series you did. I just finished it this morning and it helped me tremendously.

    I Just wanted to let you know that your work is appreciated. I’m getting ready to tackle the PHP series now and watch the above quick tip as well.

    thx again.

  3. Jeffrey Way says:
    Author

    Hey guys — I actually discovered this technique from a blog a week ago or so…but I can’t remember where. If anyone knows, reply to this comment, and I’ll be sure to link to the blog I learned it from. :)

  4. Nice idea, I like it.

    Although, the final result you their in the video could have been achieved with “border: 1px double #bbb”

  5. Erik says:

    That’s an awesome tip, thanks for sharing!

    How do you get that live preview next to Coda?

  6. Mohamed Zahran says:

    Hi Jeff, I would like to see a PHP tutorial written by your own. By the way, your css quick tips works properly and it helps us a lot but we’re greedy to learn from your experiences!

    Yours, Mohammed

  7. This is interesting – i’m not sure I would use the example given but this is my first discovery of the content: property.

    As always, thanks for your wisdom, i’m off to do more research!

  8. Ted says:

    Much quicker and cleaner than the way I was doing it before! Thanks

  9. Brian Kulp says:

    Nice effect! Thanks Jeffrey.
    I will be using this in my current project to get that nice depth effect.

  10. I’ve actually strayed away from using this ‘highlighting’ technique when designing as I didn’t want to add extra markup but once again, problem solved!

    Thank-you muchly!

  11. Thim says:

    WOW! Thnx Jeffrey!

    This quick tip helped alot, thnx for sharing :)

  12. Brian says:

    Seems this only works with a fixed height/width value? You could make some killer buttons with this technique and CSS3 background gradients…if it would allow for variable widths :P

  13. JohnDel says:

    Nice trick but it doesn’t work in internet explorer 7 and later. It works in ie 8.

  14. Thomas says:

    Thanks for this tutorial.

    Where did you get this TextMate like color scheme?

    Thanks
    Thomas

  15. Karl says:

    i have just tried this technique for a box that contains a hyperlink and now the link does seem to be clickable… any ideas?

    • Gautam Chadha says:

      It is because :after pseudo class adds another layer in front of the box class. To over come this problem you can change the z-index property on the pseudo classes so that they are positioned behind the original class.

      Multi-Borders

      body { background: #d2d1d0; }

      #box {
      background: #f4f4f4;
      border: 1px solid #bbbbbb;
      width: 196px;
      height: 196px;
      margin: 60px auto;
      position: relative;
      z-index:50;
      }

      #box:before {
      border: 1px solid white;
      content: ”;
      width: 198px;
      height: 198px;
      position: absolute;
      z-index:-2000;
      left:-2px; top:-2px
      }

      #box:after {
      content: ”;
      position: absolute;
      width: 200px;
      height: 200px;
      border: 1px solid #bbbbbb;
      left: -3px; top: -3px;
      z-index:-500;
      }

      Google.com

  16. Christophor S. says:

    This was great! thanks Jeffrey

  17. Gautam Chadha says:

    Nice tutorial Jeffrey. I was just playing with the code and found that further adding outline to each of the pseudo class and the element property will allow usage of 6 different borders with just a single element.

  18. Andi says:

    The result looks very cool but unfortunately not all the browsers support this feature…

  19. jmarreros says:

    Interesting tip, Thanks for sharing

  20. Doug Neiner says:

    I think it is fine that it doesn’t work in IE <7, but just wanted you to be aware it completely breaks in FF 3.0 since they have `:before` and `:after` *partially* implemented. They have it implemented enough to show the boxes, but not enough to fully position them.

    Apart from that, this is a great technique and has a *ton* of application in the mobile world where Webkit dominates!

    • Jeffrey Way says:
      Author

      Ahh – that’s interesting; though, I’d imagine that the upgrade percentage from Firefox 3.0 is super high.

      Another possibility would be to use -moz-borders, but that’s of course Firefox-specific.

  21. Karol says:

    Great stuff.
    I think it’s worth adding that it even works with css3 rounded corners! You have to add -moz/webkit-border-radius to both pseudo-classes and the actual class, but the result is worth it :)

  22. Ilie Ciorba says:

    Very nice tip, going to give it a try

  23. You realize that your code creates an unusable situation if you have any content in the box, right? The :before and :after pseudo elements overlay the content blocking it from user interaction. Put a link in side your box and try to click it!

  24. Djkanna says:

    I noticed that if you use something like border-radius on your box, you have to apply it to the after/before aswell. (most might know this but I thought I’d point it out aswell :) )

    Nice tip Jeffrey.

  25. Mike says:

    Thanks! This is a great article :)

  26. Ahmad Alfy says:

    WOW that was new! Thanks, I really enjoyed that and definitely gonna use it :)

  27. vas 5054a says:

    Thank you first.But the last I coudn’t see.can you say it more clearly?

  28. Nice and useful tips as for me! Thanks for sharing! Yo seem to be a really professional!

  29. Nice tip! I’m looking forward to using this.

  30. Xcellence IT says:

    Great, thanks for this great technique.

  31. Sauro says:

    I want only to tell that in general I hate video tutorials. Much better to follow a step-by-step instruction that you can also print down and follow off-line.
    But expecially in coding, video tutorials are really a creepy tool. They let you to loose a lot of time.

  32. Diane says:

    Awesome tip, thx!

  33. Robbert says:

    A great technique thank you for sharing! Keep up the good work.

  34. Hi, my original article on multiple borders and backgrounds works with fluid-width containers because I used absolute positioning differently.

    If you want to emulate multiple background images in IE8 (and other effects) you can find out more here:

    http://nicolasgallagher.com/multiple-backgrounds-and-borders-with-css2/

  35. Damion says:

    I have been trying to get a double top border, and ended up using outline and then i had to try to hide the sides and bottom. This was a big help.

    Thank you.

  36. Thank you so much for this neat little quick tip Jeffrey.

    - that solves the problem of simulating that nice subtle image border effect like img {padding:2px; border:1px solid #ccc; background:white;} -on boxes :)

  37. Jeffrey, you know you could zoom in far more with the CTRL + Scroll technique, right? Just in case.

    Neat trick, greatly explained!

    Kev

  38. Dasha says:

    This is totally awesome! Thank you for sharing and explaining it very well. I was looking for this the other day – win! Thanks again.

  39. Andrew Ckor says:

    Nice Jeffry and what? when we have a resizable (height) box??

  40. Sz-Media.org says:

    This is such a nice post. typical nettuts quality! i am looking forward to the wordpress 3.0 feature tutorial :)

  41. Great implementation, that would be a great way to set off photographs.

  42. Steve Maggs says:

    Wow, a lot of comments for what is essentially a simple post! It is a really useful and potentially wide ranging tip though, so thanks for coming up with it.

    Also love the HTML tags post, quick reads like this are always handy. Although it takes twice as long to wade through the comments!

  43. Haziq says:

    Thanks for this cool tut! Jeffrey and Nicolas rock! I like the idea how Nicolas created Pure CSS Social Media Icons using :before and :after pseudo classes.

  44. Mike says:

    A great post and a great technique – unlike Sauro I just love video tutorials!

    Jeffrey – if you really want to impress me, how do you work the same effect on a fieldset border? I have tried

    fieldset:before{}

    but it doesn’t repeat the break for the legend.

  45. Laz says:

    Wonderful, thanks!

    I just used it to create a border that changes color… just by setting the :before border-bottom to none and the :before height to half of the box’s (repositioning it by -1px top and left). Works like a charm!

    #box {
    width: 100px;
    height: 100px;
    border: 1px solid #000;
    position: relative;
    }

    #box:before {
    border: 1px solid red;
    border-bottom: none;
    content: ”;
    width: 100px;
    height: 50px;
    top: -1px;
    left: -1px;
    position: absolute;
    }

  46. Heam says:

    It helps a lot … thanks for sharing …

  47. Great post, Jeffrey. I’m using this technique in a webkit specific app – works quite nicely, and plays well with content.

    Just wanted to point out to IE folks,

    If you really need a double border, it is important to solve the problem early. The best solution, imo, to keep your markup readable, is to use jQuery, and do something like this:

    $(‘.someClass’).wrap(“”);

    Then use CSS to style accordingly.

    Check out this nifty little example.
    http://jsfiddle.net/39uLf/

  48. ^^ That .wrap(“”) is supposed to have a div class=”anotherClass” in it. :)

  49. Rather than deal with the width of the parent on the :before and :after you can set their position absolutely rather than the width. This allows for dynamic sized without having to rewrite this code over and over again.

    #box:before{
    border: 1px solid #ffcc99;
    content: ”;
    position: absolute;
    top:0;
    bottom:0;
    left:0;
    right:0;
    }
    #box:after{
    border: 1px solid #ffcc99;
    content: ”;
    position: absolute;
    top:1px;
    bottom:1px;
    left:1px;
    right:1px;
    }

    • Jeffrey Way says:
      Author

      Good point.

    • This is the method I use in the original article. But you also need to set some z-index values to avoid the pseudo-elements sitting on top of your content rendering it unselectable and links unclickable. Unfortunately, this nettuts article misses out the bits of CSS that are required to make this more flexible and practical.

  50. Jasper says:

    Can’t dis be done with ‘border: 3px double #BBBBBB;’? Or did I missed something?

Comment Page 1 of 21 2

Add a Comment

To add a code snippet to your comment, please wrap your code like so: <pre name="code" class="html">YOUR CODE</pre>. You can replace the class name with "js," "css," "sql," or "php." If there are any "<" or ">" within your code, please search and replace them with: &lt; and &gt; respectively.