The Lodge is members-only design/dev videos and Office Hours.

Next Office Hours Session: "Implementing an SVG Icon System" Nov 30 - 6:00 PM Eastern


Last updated on:

border-image is a shorthand property that lets you use an image or CSS gradient as the border of an element.

.module {
  border-image: url(border.png) 25 25 round;

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.


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:


.module {
  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.


.module {
  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.

Border image with slice lines marked in red (enlarged to show detail).

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.


.module {
  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.


.module {
  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.


.module {
  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.

  • 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):

See the Pen border-image demo: border-image-repeat tester by CSS-Tricks (@css-tricks) on CodePen.

Using Gradients for 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).

See the Pen border-image demo: repeating linear gradient border by CSS-Tricks (@css-tricks) on CodePen.

The browser will slice the gradient like it would slice a square image with width and height equal to the border-image-width.

Using SVG for 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:

.module {
  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.


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.

See the Pen border-image demo: Inline SVG by CSS-Tricks (@css-tricks) on CodePen.

Making a Border of a Single Repeating 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.

Eight hearts in a "frame" image, enlarged to show detail. The red lines indicate slices.

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.

See the Pen border-image demo: icon border by CSS-Tricks (@css-tricks) on CodePen.

More Usage 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.


More Information

More 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.

Browser Support

border-image originally required vendor prefixes on all browsers that supported it. Now it works unprefixed in the latest version of all browsers. This table shows both the earliest prefixed support and the earliest unprefixed support where applicable.

Chrome Safari Firefox Opera IE Android iOS
7*, 16 3*, 6 3.5†, 15 10.5, 15‡ 11 2.1*, 4.4 3.2*, 6

* with -webkit prefix.
† with -moz prefix.
‡ 10.5 - 14 series with -o prefix; fill keyword is not supported in any version.


  1. shshaw
    Permalink to comment#

    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:

    Editors note: thx fixed!

  2. b1ackhawk
    Permalink to comment#

    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.

  3. Ray Whitfield
    Permalink to comment#

    Is there a way to use an embedded svg image as a border?

  4. MerZikain
    Permalink to comment#

    This says it works in FF but it’s not working in mine. Using FF 37.0.2

  5. Dmitriy
    Permalink to comment#

    Can I use image only for border-bottom or border-top? (Sorry for bad English)

  6. Nigel Anderson
    Permalink to comment#

    Comprehensive and helpful, thanks Marie.

    Viewing this page in Safari reveals that it does not support round for border-image-repeat, it treats it as repeat.

Leave a Comment

Posting Code

We highly encourage you to post problematic HTML/CSS/JavaScript over on CodePen and include the link in your post. It's much easier to see, understand, and help with when you do that.

Markdown is supported, so you can write inline code like `<div>this</div>` or multiline blocks of code in in triple backtick fences like this:

  function example() {
    element.innerHTML = "<div>code</div>";

There's a whole bunch of content on CSS-Tricks.

Search for Stuff   •   Browse the Archives

Get the Newsletter ... or get the RSS feed