Creating a Body Border

Published by Chris Coyier

This article as originally published on February 25, 2008, but is now being completely re-written to be more comprehensive and show modern techniques.

Jon Hick's site Hicksdesign is where I first saw the concept of a "body border." In this case, it's a very subtle and lovely effect.

Characteristics of a body border:

  • Go around entire browser window, stuck to the edge regardless of screen size
  • All edges stay in place as page scrolls
  • Content goes beneath borders as page scrolls

View Demo

Technique #1: Four Divs

The way to do this with the deepest cross browser compatibility is to use four elements to do it. Hicksdesign does it this way, using four <b> elements and has this to say in an HTML comment:

I use the b tag borders because it's just visual stuff with no meaning so I may as well use the smallest tag I can find.

No matter what, this is presentational markup which is not ideal. We'll use a div here:

<div id="left"></div>
<div id="right"></div>
<div id="top"></div>
<div id="bottom"></div>

Then we style with CSS. Some properties are shared by all of the elements, some by only the top/bottom and left/right, and some unique to themselves. Here is a clean way to code that, without unnecessary repeated properties.

#top, #bottom, #left, #right {
	background: #a5ebff;
	position: fixed;
	}
	#left, #right {
		top: 0; bottom: 0;
		width: 15px;
		}
		#left { left: 0; }
		#right { right: 0; }
		
	#top, #bottom {
		left: 0; right: 0;
		height: 15px;
		}
		#top { top: 0; }
		#bottom { bottom: 0; }

This should work fine in IE 7 and up and just about any other good desktop browser. For IE 6, which doesn't support fixed positioning, we'll just get rid of it (no harm no foul) by using a conditional comment in the head:

<!--[if lte IE 6]>
	<style>#top, #bottom, #left, #right { display: none; }</style>
<![endif]-->

We also should ditch it on small screens (likely to be mobile) which also don't handle fixed positioning:

@media 

/* Fairly small screens including iphones */
only screen and (max-width: 500px),

/* iPads */
only screen and (min-device-width: 768px) and (max-device-width: 1024px) 

{
	#top, #bottom, #left, #right { display: none; }
}

So now we get the effect where we want it and not where we don't:

Technique #2: Pseudo Elements

In the above example, we needed four unique elements to get the job done. But that's four more elements than are appropriate semantically in our document. Ideally we would use zero. Well wouldn't ya know it, there are two elements that are the size of the browser window already, the <html> and <body> elements. Using the :before and :after pseudo elements on those, we get four!

We would use the same properties and values as above, only we would use:

html:before, html:after, body:before, body:after {
    content: "";
    position: fixed;
    background: #a5ebff;

    /* etc. */
}

Harry Roberts had this idea as well and published it on CSS Wizardy.

While the browser support for pseudo elements is pretty good, it's not as good as Technique #1. A bigger problem is that there is an WebKit bug which the background on an html-element pseudo element bleed over the entire viewport. This makes using pseudo elements on the html-element a no-go for the time being.

But there is a solution! While saying semantic!

We don't really need four unique elements, we really only need two. The top and the bottom need to be unique, so they can be of fixed position and not scroll. For the left and the right, we can literally just use a border on the <body>.

body:before, body:after {
    content: "";
    position: fixed;
    background: #900;
    left: 0;
    right: 0;
    height: 10px;
}
body:before {
    top: 0;
}
body:after {
    bottom: 0;
}
body {
    border-left: 10px solid #900;
    border-right: 10px solid #900;  
}

Same exact effect, slightly less browser support, way more semantic.

View Demo

For Funzies: Kottke.org body border

Jason Kottke's Kottke.org has a pretty cool body-border effect.

It takes Jason eight different elements and eight different images (!) to pull this off. Because this border style doesn't stay fixed to the top and bottom of the viewport (just the top and bottom of content) this is actually really easy to pull off with CSS3.

We'll use box-shadow on the <body> element, and it's neat ability to comma-separate multiple shadows. Here it is in it's entirety with

body {
	padding: 40px;
	overflow-x: hidden; /* For Opera */
	-webkit-box-shadow:
		inset #19d4ff 0 0 0 5px,
		inset #18cdf7 0 0 0 1px,
		inset #53dfff 0 0 0 10px,
		inset #50d8f7 0 0 0 11px,
		inset #8ce9ff 0 0 0 16px,
		inset #88e2f7 0 0 0 17px,
		inset #c5f4ff 0 0 0 22px,
		inset #bfecf7 0 0 0 23px;
	-moz-box-shadow:
		inset #19d4ff 0 0 0 5px,
		inset #18cdf7 0 0 0 1px,
		inset #53dfff 0 0 0 10px,
		inset #50d8f7 0 0 0 11px,
		inset #8ce9ff 0 0 0 16px,
		inset #88e2f7 0 0 0 17px,
		inset #c5f4ff 0 0 0 22px,
		inset #bfecf7 0 0 0 23px;
	box-shadow:
		inset #19d4ff 0 0 0 5px,
		inset #18cdf7 0 0 0 1px,
		inset #53dfff 0 0 0 10px,
		inset #50d8f7 0 0 0 11px,
		inset #8ce9ff 0 0 0 16px,
		inset #88e2f7 0 0 0 17px,
		inset #c5f4ff 0 0 0 22px,
		inset #bfecf7 0 0 0 23px;
}

Bug Note: Opera (Mac, 11.10) has a weird bug where it expands the size of the element to accommodate for the shadows on the outside (even thought the shadows are inset). This triggers unwanted scrollbars, since we're using it on a full-width body element. Horizontal scrollbars can be hidden by hiding overflow-x. But unfortunately there will still be a bit of space at bottom of screen.

While this has the least browser support of all the stuff covered, it's not bad: IE 9+, Fx 3.5+, Opera 10.5+, Chrome any, Safari 3+

View Demo