border-image
is a shorthand property that lets you use an image or CSS gradient as the border of an element.
The border-image
property can be applied to any element, except internal table elements (e.g. tr, th, td) when border-collapse
is set to collapse
.
.element {
border-image: url(border.png) 25 25 round;
}
Syntax
border-image: <'border-image-source'> || <'border-image-slice'> [ / <'border-image-width'> | / <'border-image-width'>? / <'border-image-outset'> ]? || <'border-image-repeat'>
Properties
The only required property for the border-image
shorthand is border-image-source
. The other properties default to their initial values if they’re not specified. These are the border-image
properties in order:
border-image-source
.element {
border-image-source: url(border.png);
}
This property specifies the source for the border image. This can be a URL, data URI, CSS gradient, or inline SVG (though support is limited for inline SVG, see SVG usage notes).
The initial value is none
.
border-image-slice
.element {
border-image-source: url(border.png);
border-image-slice: 20;
}
The values of this property tell the browser where to “slice” the image to create the pieces of the border. The image is divided into 9 sections — the four corners, the four sides, and the center.
The property accepts up to four positive unitless numbers or percentages, and an optional fill
keyword. The initial value is 100%
.
Unitless numbers measure the slice by pixels on a raster image, and by coordinates on an SVG. A percentage value is relative to the size of the image. For example, on a raster image that is 100px x 100px, 10%
from any side of the image is 10px. See the usage notes on SVG for more information about how percentages work on SVG images.
The values measure from the top, right, bottom, and left edges of the image (in that order). If one value is missing, its value defaults to the value of its opposite side — for example if the left value is missing, but the right value is set at 10px, the left value becomes 10px too.
By default, the center of the source image is discarded. But, when the fill
keyword is used, it’s applied to the background of the bordered element instead.
border-image-width
.element {
border-image-source: url(border.png);
border-image-slice: 20;
border-image-width: 20;
}
This property sets the width of the border image. It accepts a percentage value, a positive unitless number, or the keyword auto
.
The values are for the top, right, bottom, and left sides of the element (in that order). If one value is missing, it is drawn the same as its opposite value.
For this property, percentage values are relative to the size of the border image area, while a unitless number is multiplied with the border-width
.
The initial value is 1
, so if this value is not set but there’s a border
or border-width
declaration for the element, the border image will be drawn at that width.
The auto
keyword tells the browser to use either the size of the border-image-slice
if available, or the size of the border-width
.
border-image-outset
.element {
border-image-source: url(border.png);
border-image-slice: 20;
border-image-width: 20;
border-image-outset: 1;
}
The value for this property specifies how far the border image area extends past the border box. The initial value is 0
. The property accepts up to four positive length values or unitless numbers. Length values are absolute measurements, while a unitless number is multiplied with the border width to compute the outset value, similar to how unitless numbers work for border-image-width
.
border-image-repeat
.element {
border-image-source: url(border.png);
border-image-slice: 20;
border-image-width: 20;
border-image-outset: 1;
border-image-repeat: round;
}
This property controls how the image is repeated to fill the area of the border.
You can specify up to two values for this property. If one value is specified, it’s applied to both the horizontal and vertical sides of the border. If two are specified, the first is applied to the horizontal sides and the second is applied to the vertical sides.
Values
stretch
: the initial value. The border image is stretched as needed to fill the area.repeat
: the image tiles to fill the area, dividing tiles if necessary.round
: the image tiles to fill the area, and is rescaled if necessary to avoid dividing tiles.space
: the image tiles to fill the area. If the area can’t be filled with whole tiles, space is inserted around the tiles for an even fit. Note: this value is not implemented by any browser yet.
Try out the different border-image-repeat
values in this demo (space
is included for future compatibility only; it doesn’t work as specified in any browser yet):
Gradient border images
All of the browsers that support border-image
support CSS gradients too. You can use gradients of any type to make your border. This demo shows a repeating linear gradient making a striped border (hover it to see the stripe colors swap).
The browser will slice the gradient like it would slice a square image with width and height equal to the border-image-width
.
SVG border images
The biggest difference between using raster images and SVG for border-image
is in how the slices are measured.
Unitless values represent coordinates on SVG images.
Percentage values are relative to the size of the image.
If the SVG doesn’t have a defined size, it is sized with the default sizing algorithm, which will use the border image area set by the border-image-outset
as the default size. This can be confusing in practice, so it’s helpful to set a size for the SVG when possible.
SVG in an image source URL
You can link an SVG file as the border-image-source
the same way you’d link a raster image:
.element {
border-image-source: url(border.svg);
}
This is probably the best method for using SVG as border images. It’s well-supported — all modern browsers that support border-image
will accept a linked SVG as the border-image-source
.
Inline
You can Base64 encode an SVG border image, or write the SVG markup directly into the border image source, but both methods have fairly significant issues.
Base64 SVG has enough problems to merit its own article: Probably Don’t Base64 SVG.
Writing SVG image markup directly into a border-image
declaration also has complications; Internet Explorer will not recognize it, and support in Firefox is quirky (see Bug 619500).
The border image in this demo is an inline SVG gradient. If you check out the “CSS” tab, you’ll notice that the markup has to be carefully composed — note the double quotes around the markup, the single quotes inside the markup, and the escaped octothorpe (#) characters in the hex colors.
Single repeating border image
Bordering an element with a single repeating image is something that seems like it should be easy with a property called border-image
, but the process for actually doing that is somewhat counter-intuitive.
Let’s say, for example, that you want to border an element with a repeating heart icon. You can’t do that with a image of a single heart. Instead, you have to make an image of a “frame” of hearts arranged as you’d like them to appear in the border, then slice that image.
If you think that sounds preposterous, you’re in good company. There was a lengthy discussion of the subject on Eric Myer’s blog a few years ago where many frontend development greats weighed in.
In this demo, a heart repeats around the border of the div. The border-image-source
image is a composite image of eight of the same heart icon, sliced so that the full heart shape is used on each side of the element.
Additional notes
Though support for border-image
has improved — it’s supported unprefixed in all current browser versions — setting a fallback border
style is still worthwhile. Your fallback border will show on browsers that don’t support border-image
, or if the image fails to load.
Unlike some of the other border properties, border-image
can’t be animated. It also can’t be styled with border-radius
.
If you declare a border-image-source
and a border
width or border-image-width
without any slices, the entire unsliced image will be placed at the four corners of the element, scaled to your specified width.
Demos
- Also from Dudley Storey, Practical border-image: responsive picture frame, a CodePen demo. This is a good example of using a border image sensibly on a responsive image. Notice that the “frame” is removed at smaller screen sizes.
- True dotted borders using SVG and border-image, a Pen by Lucas Lemonnier. A solution for the ugly square “dotted” border, this method gives you real round dots!
- gradient button, a Pen by CodePen user GSSxGSS. A pretty example of a linear gradient as a border image.
- Film Strip, a Pen by Nick Pettit. Perhaps not the most practical demo, this is a fun, arty example of what you can do with
border-image
.
More Information
- CSS Background and Borders Module Level 3 (Candidate Recommendation)
- border-image.com: This tool lets you upload an image and play with the border slices until you get them right, then it generates the CSS for you.
- Border Image Explained (Dudley Storey)
Browser support
This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.
Desktop
Chrome | Firefox | IE | Edge | Safari |
---|---|---|---|---|
56 | 50 | 11 | 12 | 9.1 |
Mobile / Tablet
Android Chrome | Android Firefox | Android | iOS Safari |
---|---|---|---|
123 | 124 | 123 | 9.3 |
This is the weirdest property ever. Such a strange syntax.
Under More Information, you have Understanding Border Image listed, but there isn’t a link to the article: https://css-tricks.com/understanding-border-image/Editors note: thx fixed!
I don’t understand how the shorthand properties correspond to the individual. url, repeat and stretch make sense, but not the numbers. The numbers arent the same as in the individual and quantity of numbered properties are different from whats listed under individual.
Is there a way to use an embedded svg image as a border?
Yeah, just link to it via ID’s
can’t seem to get it to work… care to post an example?
This says it works in FF but it’s not working in mine. Using FF 37.0.2
Can I use image only for border-bottom or border-top? (Sorry for bad English)
Yes, you can. There’s a little trick to it — you need to set the
border-image-width
for the other 3 borders to 0 because their initial value is 1. This CSS tab in this pen shows a way to do that:http://codepen.io/mariemosley/pen/f085e48aa08096ce15a6dccda12f68fc
Comprehensive and helpful, thanks Marie.
Viewing this page in Safari reveals that it does not support
round
forborder-image-repeat
, it treats it asrepeat
.Hello !
Can you tell me why I cannot display the content of the black screens ?
https://image.prntscr.com/image/iw8YSKfETq_kheO1Xic9bg.png
It says
“CodePen requires a referrer
to render this. Your browser
isn’t sending one.
If you have questions,
contact [email protected].”
I use SeaMonkey as a browser, last release and I do not remember having configured anything related to referer sending.
Thanks
Is your internet connection behind a firewall? The content in those frames is served from CodePen. I’m happy to send you the direct links to the demos:
how to apply border image to an rounded image or div?
Wow! Nice question!
I hope it could be answered soon!
Can border-image be used to make something like pipeline in this problem?
https://stackoverflow.com/questions/59170127/how-can-i-make-a-pipeline-using-border-in-css
Hi. I always enjoy your posts and written tutorials.
I have a project that I’m working on and I’m actually done with it, BUT I have to implement a custom scrollar with a round thumb just exactly like in the css-tricks.com website. Please kindly tell me how you have done this as soon as possible. Thank you in advanced. stay safe.
can i give border radius to border image source?
Hey there! I don’t believe so. Adding
border-radius
to an element that already has a border image will round the corners of the element’s box, but will leave the image in tact. Here’s an example forked from the demo in this post: https://codepen.io/geoffgraham/pen/qBZGLqdI’m confused so how do I set a size for my svg? It already has a viewbox argument and consist of a path defined by coordinates.
Hey, so the
viewBox
isn’t so much about the size of the SVG as it is the dimensions and position of it. It still acceptswidth
andheight
attributes to define the physical size — which is the advice given in the article.