The new CSS3 property border-image is a little tricky, but it can allow you to create flexible boxes with custom borders (or drop shadows, if that’s your thing) with a single div and a single image. In this article, I explain how the border-image shorthand property works in today’s browsers.
The basic idea
The border-image shorthand property has 3 parts:
border-image: url(border-image.png) 25% repeat;
Essentially, these allow you to specify:
- An image to use as the border
- Where to slice that image, dividing the image into 9 sections
- How the browser should apply those sections to the edges of your element
The pertinent details
Let’s look at each part of the process in a little more detail. The first part is easy, and is familiar from the background-image property. For demonstration purposes I’ll use this image, which is 100px x 100px:
Slicing your image
The second part can have from one to four values, much like the border-width property, and they are specified in the same order: top, right, bottom, left. You can use percentages or pixels. Strangely, the percentages require the “%”, while pixels should be listed without the “px”:
border-image: url(my-image.gif) 25% 30% 10% 20% repeat;
border-image: url(my-image.gif) 25 30 10 20 repeat;
In this case, since my image is 100px x 100px, the two rules above are equivalent – they slice the image in the same places. I’ve added some dimensions on my image to demonstrate:
Repeat, Round, Stretch
border-image
will always place the corner sections of your image into the corresponding corners of your element box, but the third part of the shorthand rule tells the browser how to treat the middle sections of your image – the ones that will go along the edges of your element.
Repeat
(repeat, or tile, the image) and stretch
(stretch, or scale, the image) are pretty self-explanatory.
Round
means tile the image but only so that a whole number of tiles fit, and otherwise scale the image. Right now, Safari and Chrome interpret round
as repeat
. There can be up to two values: one for the top and bottom edges of the element, and one for the left and right.
Here’s an example with the top/bottom value set to repeat
, and the left/right value set to stretch
:
#example-one {
border-width: 25px 30px 10px 20px;
border-image: url("border-image.png") 25 30 10 20 repeat stretch;
}
LIVE DEMO, RSS READERS CLICK OVER TO SEE. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean eu arcu non dui consequat vestibulum non vitae eros. Donec imperdiet lorem at mi rhoncus lacinia. Phasellus porttitor ligula eu justo condimentum eget placerat arcu pharetra. Proin fringilla vulputate eros in accumsan. Sed mi nibh, pulvinar eu sollicitudin ut, feugiat non ipsum. In ornare, quam sit amet tempor suscipit, erat odio suscipit nisi, eu gravida nisl orci ut arcu. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Border-width
border-image
won’t do anything if you don’t specify a width for your border. For browsers that understand border-image, your image slices will be scaled to the specified width. If you use the border shorthand property, it provides a nice fallback for browsers that don’t:
#example-two {
border: 50px double orange;
border-image: url("border-image.png") 25 30 10 20 repeat;
}
Or you can specify each width individually (in this example I’ve specified widths such that the image slices aren’t scaled at all):
#example-three {
border-color: orange;
border-style: double;
border-width: 25px 30px 10px 20px;
border-image: url("border-image.png") 25 30 10 20 repeat;
}
Using a plain border at the same widths as your border-image won’t always be ideal, however, so you may want to use conditional stylesheets to give IE some different border styles altogether.
Browser quirks
Predictably, IE doesn’t understand anything of border-image. Browsers that do support border-image only support the shorthand property, not all the individual properties that are described in the spec. Some potentially useful properties aren’t supported at all, especially border-image-outset, which would solve this problem.
Also, the default behavior is supposed to be to discard the center section of the image, and use the ‘fill’ keyword on the border-image-slice property to preserve it:
The
fill
keyword, if present, causes the middle part of the border-image to be preserved. (By default it is discarded, i.e., treated as empty.) (Read the spec)
But the current browser behavior is to preserve the middle, and there is no way to turn it off. Thus, if you don’t want your element’s content area to have a background, the center section of your image must be empty. However, you can use this filling behavior to your advantage, to create a box with a fancy border and background, with only one image.
Interactive demo
I built a border-image
demo page to help me get my head around this complicated new set of CSS3 properties. You can pick an image, specify repeat, round, or stretch, and adjust the border-width and slicing. Enjoy!
Examples in the wild
- Chris Spooner uses it to nice effect to give his images a custom border.
- On the travel blog Go Pink Boots (Update: now offline) I built recently, I used it to add a torn-paper background to images.
- I use it on my site The Web Designers’ Review of Books (Update: now offline) to highlight blockquotes.
If you have other examples on live sites, I’d love to see them. Leave a link in the comments!
These things I’ve not known. Many Thank you for helping us offer us.
Very useful article
Very helpful this post
Chris you are starting to creep me out. And I mean that in the best of ways… it’s amazing how timely your articles are. I was just investigating this to not much avail yesterday.
Thank you!
Thanks. Very informative.
Very useful article.
keep up the good work
I don’t know why, but this is way more confusing for me that linear and radial gradients. I’m going to have to read and re-read this article another 4 or 5 times to really get it. And, of course, play with it as much as possible. Thanks for another great resource/reference.
Thank you for clarifying a property that’s a little hard to understand.
O.T.: browsing “Go pink boots” I noticed that tag pages don’t work. Since you built it, I think this information may help you
Thanks so much Elisa. That site is still a bit of a work-in-progress. I’ll look into the tag glitch right away!
You’re welcome! Anyway, nice work. I like the way you used border-image property, I’ll try to implement it in my next projects an your guide will make it easier…
Elisa, are you Albanian? :-) just a thought…
By the way, great article…
No, I’m italian :-)
Wow I’m so used to creating border effects with a background picture that this almost seems unintuitive.
Thanks for your comment Tom. When IE supports this, and other browsers expand their support, we will be able to replace all kinds of multi-div, multi-background-image sliding-doors type stuff with a single border-image. Can’t wait!
Wild. Glad we have people like yourself who are ambitious enough to tackle it and explain it to the community
Good article. Chris, you might want to credit Nora where it says “Guest Author” up top.
Nice article.
May have a look at : http://css3pie.com/ trying to offer css3 support for IE.
Wow, that http://css3pie.com/ looks amazing! Im gonna try it :)
This is *the* solution for IE. I’m really that excited.
Good explanation. I think this will help me :-)
wow a lot of that went over my head, but you have done a really in-depth tutorial here, and i salute you.
i think i’ll have to look at this in bite-size chunks so that i understand it!
Thanks a lot silvers. Get in touch if you have any questions, maybe I can help! (find my email at on my website: norabrowndesign.com).
Oh wow, great article.
It definitely helped me understand one of the hardest, most-confusing (in my opinion) CSS3 properties out there. Definitely keep it going!
By the way, I just wanted to compliment you, Nora, on a very elegant site design.
Thanks Amit – I really appreciate the compliment. I agree border-image is one of the most confusing new bits in CSS3, but also one with a lot of potential!
Nice write up. I made a demo a while back with a “rounded” border image by starting with a rounded image for the border and adding a border radius declaration to the div:
http://blog.darkcrimson.com/samples/css3/
Hey great demo page. I love the “view css” option…perfect way to explain the features you’ve implemented. Got a tutorial on that somewhere?
Thanks Nora, like the interactive demo too.
Ok outset will be great, however can’t you just reduce the border and border-image widths to 80px, for example, instead of 213px, to reduce the white space? Solving the mentioned:
this problem
Thank you so much for this, I agree with the guy who said that this is harder than the gradients (and this is coming from a person who has a problem with gradients in PS and Illy, too!)
Also, that’s a sweet-looking travel blog, wonderful design.
This was very interesting for me to read and to know about today. Thank you very much for this. I just wonder how often this will/can be used?
Thanks alpaproductions. I would put border-image in that ever-growing category of things that can be implemented as “progressive enhancements” – things you can add as nice touches for browsers that understand them.
I guess that’s true. I use round corners the same way you just mentioned here.
You can also use a trick with :before and :after and set background images for that with absolute positioning. Of course, I don’t know the exact cross-compatibility for that but I’m sure it’s better than border-image.
Nice explanation though, I’ll go back to this one day when this becomes a more common thing.
this is the best border-image tutorial I found online! I had wondered how chris Spooners achieved that cool effect on his images. Glad I learned this!
Isn’t CSS so cool?
Thanks for explaining it so clearly.
Another great post! Lot of fun… but, one note: (it seams to me that) it is restricting application of gradient borders to elements with non-gradient background. What if you wanted to have an element of some gradient background and add to it borders of a different gradient… ? Then it wouldn’t work, right? Or did I get it all wrong…?