The native dashed border property value does not offer control over the dashes themselves... so bring on the border-image property!
Brew your own border with border-image
Compatibility: It offers great browser support (IE 11 and all modern browsers). A normal border can be set as a fallback for older browsers.
Let's create these
These borders will display exactly the same cross-browser!

Step 1 - Create a suitable image
This example is 15 pixels wide by 15 pixels high and the gaps are currently 5px wide. It is a .png with transparency.
This is what it looks like in photoshop when zoomed in:

This is what it looks like to scale:

Controlling gap and stroke length
To create wider / shorter gaps or strokes, widen / shorten the gaps or strokes in the image.
Here is an image with wider 10px gaps:
correctly scaled = 
Step 2 - Create the CSS โ this example requires 4 basic steps
Define the border-image-source:
border-image-source:url("https://i.sstatic.net/wLdVc.png");Optional - Define the border-image-width:
border-image-width: 1;The default value is 1. It can also be set with a pixel value, percentage value, or as another multiple (1x, 2x, 3x etc). This overrides any
border-widthset.Define the border-image-slice:
In this example, the thickness of the images top, right, bottom and left borders is 2px, and there is no gap outside of them, so our slice value is 2:
border-image-slice: 2;
The slices look like this, 2 pixels from the top, right, bottom and left:

- Define the border-image-repeat:
In this example, we want the pattern to repeat itself evenly around our div. So we choose:
border-image-repeat: round;
Writing shorthand
The properties above can be set individually, or in shorthand using border-image:
border-image: url("https://i.sstatic.net/wLdVc.png") 2 round;
Complete example
Note: border-style must be set to a value such as solid or dashed as the initial border style is none. Alternatively, you can add a fallback border, such as border: dashed 4px #000 in this example, non-supporting browsers will receive this border.
.bordered {
display: inline-block;
padding: 20px;
/* Optional:
A normal dashed border can be set as a fallback, particularly if older browsers need to be supported. Notes:
- the 4px width here is overwritten with any border-image-width value
- a border-image-width can be omitted if it is the same value as the dashed border width
*/
border: dashed 4px #000;/*optional*/
/* the initial value of border-style is "none", so it must be set to a different value for the border-image to show*/
border-style: dashed;
/* Individual border image properties */
border-image-source: url("https://i.sstatic.net/wLdVc.png");
border-image-slice: 2;
border-image-repeat: round;
/* or use the shorthand border-image */
border-image: url("https://i.sstatic.net/wLdVc.png") 2 round;
}
/*The border image of this one creates wider gaps*/
.largeGaps {
border-image-source: url("https://i.sstatic.net/LKclP.png");
margin: 0 20px;
}
<div class="bordered">This is bordered!</div>
<div class="bordered largeGaps">This is bordered and has larger gaps!</div>
Answer from misterManSam on Stack OverflowVideos
The native dashed border property value does not offer control over the dashes themselves... so bring on the border-image property!
Brew your own border with border-image
Compatibility: It offers great browser support (IE 11 and all modern browsers). A normal border can be set as a fallback for older browsers.
Let's create these
These borders will display exactly the same cross-browser!

Step 1 - Create a suitable image
This example is 15 pixels wide by 15 pixels high and the gaps are currently 5px wide. It is a .png with transparency.
This is what it looks like in photoshop when zoomed in:

This is what it looks like to scale:

Controlling gap and stroke length
To create wider / shorter gaps or strokes, widen / shorten the gaps or strokes in the image.
Here is an image with wider 10px gaps:
correctly scaled = 
Step 2 - Create the CSS โ this example requires 4 basic steps
Define the border-image-source:
border-image-source:url("https://i.sstatic.net/wLdVc.png");Optional - Define the border-image-width:
border-image-width: 1;The default value is 1. It can also be set with a pixel value, percentage value, or as another multiple (1x, 2x, 3x etc). This overrides any
border-widthset.Define the border-image-slice:
In this example, the thickness of the images top, right, bottom and left borders is 2px, and there is no gap outside of them, so our slice value is 2:
border-image-slice: 2;
The slices look like this, 2 pixels from the top, right, bottom and left:

- Define the border-image-repeat:
In this example, we want the pattern to repeat itself evenly around our div. So we choose:
border-image-repeat: round;
Writing shorthand
The properties above can be set individually, or in shorthand using border-image:
border-image: url("https://i.sstatic.net/wLdVc.png") 2 round;
Complete example
Note: border-style must be set to a value such as solid or dashed as the initial border style is none. Alternatively, you can add a fallback border, such as border: dashed 4px #000 in this example, non-supporting browsers will receive this border.
.bordered {
display: inline-block;
padding: 20px;
/* Optional:
A normal dashed border can be set as a fallback, particularly if older browsers need to be supported. Notes:
- the 4px width here is overwritten with any border-image-width value
- a border-image-width can be omitted if it is the same value as the dashed border width
*/
border: dashed 4px #000;/*optional*/
/* the initial value of border-style is "none", so it must be set to a different value for the border-image to show*/
border-style: dashed;
/* Individual border image properties */
border-image-source: url("https://i.sstatic.net/wLdVc.png");
border-image-slice: 2;
border-image-repeat: round;
/* or use the shorthand border-image */
border-image: url("https://i.sstatic.net/wLdVc.png") 2 round;
}
/*The border image of this one creates wider gaps*/
.largeGaps {
border-image-source: url("https://i.sstatic.net/LKclP.png");
margin: 0 20px;
}
<div class="bordered">This is bordered!</div>
<div class="bordered largeGaps">This is bordered and has larger gaps!</div>
In addition to the border-image property, there are a few other ways to create a dashed border with control over the length of the stroke and the distance between them. They are described below:
Method 1: Using SVG
We can create the dashed border by using a path or a polygon element and setting the stroke-dasharray property. The property takes two parameters where one defines the size of the dash and the other determines the space between them.
Pros:
- SVGs by nature are scalable graphics and can adapt to any container dimensions.
- Can work very well even if there is a
border-radiusinvolved. We would just have replace thepathwith acirclelike in this answer (or) convert thepathinto a circle. - Browser support for SVG is pretty good and fallback can be provided using VML for IE8-.
Cons:
- When the dimensions of the container do not change proportionately, the paths tend to scale resulting in a change in size of the dash and the space between them (try hovering on the first box in the snippet). This can be controlled by adding
vector-effect='non-scaling-stroke'(as in the second box) but the browser support for this property is nil in IE.
.dashed-vector {
position: relative;
height: 100px;
width: 300px;
}
svg {
position: absolute;
top: 0px;
left: 0px;
height: 100%;
width: 100%;
}
path{
fill: none;
stroke: blue;
stroke-width: 5;
stroke-dasharray: 10, 10;
}
span {
position: absolute;
top: 0px;
left: 0px;
padding: 10px;
}
/* just for demo */
div{
margin-bottom: 10px;
transition: all 1s;
}
div:hover{
height: 100px;
width: 400px;
}
<div class='dashed-vector'>
<svg viewBox='0 0 300 100' preserveAspectRatio='none'>
<path d='M0,0 300,0 300,100 0,100z' />
</svg>
<span>Some content</span>
</div>
<div class='dashed-vector'>
<svg viewBox='0 0 300 100' preserveAspectRatio='none'>
<path d='M0,0 300,0 300,100 0,100z' vector-effect='non-scaling-stroke'/>
</svg>
<span>Some content</span>
</div>
Method 2: Using Gradients
We can use multiple linear-gradient background images and position them appropriately to create a dashed border effect. This can also be done with a repeating-linear-gradient but there is not much improvement because of using a repeating gradient as we need each gradient to repeat in only one direction.
.dashed-gradient{
height: 100px;
width: 200px;
padding: 10px;
background-image: linear-gradient(to right, blue 50%, transparent 50%), linear-gradient(to right, blue 50%, transparent 50%), linear-gradient(to bottom, blue 50%, transparent 50%), linear-gradient(to bottom, blue 50%, transparent 50%);
background-position: left top, left bottom, left top, right top;
background-repeat: repeat-x, repeat-x, repeat-y, repeat-y;
background-size: 20px 3px, 20px 3px, 3px 20px, 3px 20px;
}
.dashed-repeating-gradient {
height: 100px;
width: 200px;
padding: 10px;
background-image: repeating-linear-gradient(to right, blue 0%, blue 50%, transparent 50%, transparent 100%), repeating-linear-gradient(to right, blue 0%, blue 50%, transparent 50%, transparent 100%), repeating-linear-gradient(to bottom, blue 0%, blue 50%, transparent 50%, transparent 100%), repeating-linear-gradient(to bottom, blue 0%, blue 50%, transparent 50%, transparent 100%);
background-position: left top, left bottom, left top, right top;
background-repeat: repeat-x, repeat-x, repeat-y, repeat-y;
background-size: 20px 3px, 20px 3px, 3px 20px, 3px 20px;
}
/* just for demo */
div {
margin: 10px;
transition: all 1s;
}
div:hover {
height: 150px;
width: 300px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class='dashed-gradient'>Some content</div>
<div class='dashed-repeating-gradient'>Some content</div>
Pros:
- Scalable and can adapt even if the container's dimensions are dynamic.
- Does not make use of any extra pseudo-elements which means they can be kept aside for any other potential usage.
Cons:
- Browser support for linear gradients is comparatively lower and this is a no-go if you want to support IE 9-. Even libraries like CSS3 PIE do not support creation of gradient patterns in IE8-.
- Cannot be used when
border-radiusis involved because backgrounds don't curve based onborder-radius. They get clipped instead.
Method 3: Box Shadows
We can create a small bar (in the shape of the dash) using pseudo-elements and then create multiple box-shadow versions of it to create a border like in the below snippet.
If the dash is a square shape then a single pseudo-element would be enough but if it is a rectangle, we would need one pseudo-element for the top + bottom borders and another for left + right borders. This is because the height and width for the dash on the top border will be different from that on the left.
Pros:
- The dimensions of the dash is controllable by changing the dimensions of the pseudo-element. The spacing is controllable by modifying the space between each shadow.
- A very unique effect can be produced by adding a different color for each box shadow.
Cons:
- Since we have to manually set the dimensions of the dash and the spacing, this approach is no good when the dimensions of the parent box is dynamic.
- IE8 and lower do not support box shadow. However, this can be overcome by using libraries like CSS3 PIE.
- Can be used with
border-radiusbut positioning them would be very tricky with having to find points on a circle (and possibly eventransform).
.dashed-box-shadow{
position: relative;
height: 120px;
width: 120px;
padding: 10px;
}
.dashed-box-shadow:before{ /* for border top and bottom */
position: absolute;
content: '';
top: 0px;
left: 0px;
height: 3px; /* height of the border top and bottom */
width: 10px; /* width of the border top and bottom */
background: blue; /* border color */
box-shadow: 20px 0px 0px blue, 40px 0px 0px blue, 60px 0px 0px blue, 80px 0px 0px blue, 100px 0px 0px blue, /* top border */
0px 110px 0px blue, 20px 110px 0px blue, 40px 110px 0px blue, 60px 110px 0px blue, 80px 110px 0px blue, 100px 110px 0px blue; /* bottom border */
}
.dashed-box-shadow:after{ /* for border left and right */
position: absolute;
content: '';
top: 0px;
left: 0px;
height: 10px; /* height of the border left and right */
width: 3px; /* width of the border left and right */
background: blue; /* border color */
box-shadow: 0px 20px 0px blue, 0px 40px 0px blue, 0px 60px 0px blue, 0px 80px 0px blue, 0px 100px 0px blue, /* left border */
110px 0px 0px blue, 110px 20px 0px blue, 110px 40px 0px blue, 110px 60px 0px blue, 110px 80px 0px blue, 110px 100px 0px blue; /* right border */
}
<div class='dashed-box-shadow'>Some content</div>
You can try with some background and gradients. Resize the below to see the result:
.box {
--c: red;
--t: 5px; /* border thickness */
width: 300px;
height: 200px;
border: var(--t) solid #0000;
--b1:/calc(4*var(--t)) var(--t) linear-gradient(90deg,var(--c) 25%,#0000 0 75%,var(--c) 0) border-box round no-repeat;
--b2:/var(--t) calc(4*var(--t)) linear-gradient( var(--c) 25%,#0000 0 75%,var(--c) 0) border-box no-repeat round;
background:
0 0 var(--b1),0 100% var(--b1),
0 0 var(--b2),100% 0 var(--b2);
/* to debug */
overflow: hidden;
resize: both;
}
<div class="box"></div>
Figma allow you to control exact dash length and gap:
Border: 1 px
Style: Dashed
Dashes: e.g.
10, 5Alignment: Inside
CSS, unfortunately, does not provide a built-in dashed border with configurable dash length or gap.
Even worse:
border-style: dasheduses the browserโs own dash algorithm โ no control.border-imagestretches the pattern around the rectangle โ vertical dashes never match horizontal ones unless the box has special proportions.
If you want a border that looks exactly like Figma, you must manually draw the 4 sides with linear-gradient.
The following solution reproduces the exact Figma behavior and supports custom dash length & gap.
Pure CSS or Tailwind v4 solution:
/* Draw 4 dashed sides using a pseudo-element */
@layer utilities {
.border-dash-box {
position: relative;
}
.border-dash-box::after {
position: absolute;
inset: 0;
pointer-events: none;
content: "";
/* fallback values when user does not override them */
background:
/* top */
linear-gradient(to right, currentColor 0 var(--border-dash-length, 10px), transparent 0)
0 0 /
calc(var(--border-dash-length, 10px) + var(--border-dash-gap, 5px)) 1px repeat-x,
/* bottom */
linear-gradient(to right, currentColor 0 var(--border-dash-length, 10px), transparent 0)
0 100% /
calc(var(--border-dash-length, 10px) + var(--border-dash-gap, 5px)) 1px repeat-x,
/* left */
linear-gradient(to bottom, currentColor 0 var(--border-dash-length, 10px), transparent 0)
0 0 /
1px calc(var(--border-dash-length, 10px) + var(--border-dash-gap, 5px)) repeat-y,
/* right */
linear-gradient(to bottom, currentColor 0 var(--border-dash-length, 10px), transparent 0)
100% 0 /
1px calc(var(--border-dash-length, 10px) + var(--border-dash-gap, 5px)) repeat-y;
border-radius: inherit;
}
}
/* Dash length utility */
@utility border-dash-length-* {
--border-dash-length: calc(var(--spacing) * --value(integer));
--border-dash-length: --value([length]);
}
/* Gap utility */
@utility border-dash-gap-* {
--border-dash-gap: calc(var(--spacing) * --value(integer));
--border-dash-gap: --value([length]);
}
Usage Examples
<div class="border-dash-box text-gray-600 p-4">
Default: dash 10px, gap 5px
</div>
Custom dash pattern
<div class="border-dash-box border-dash-length-6 border-dash-gap-3 text-blue-600 p-4">
Dash 6px, Gap 3px
</div>
Arbitrary values
<div class="border-dash-box border-dash-length-[12px] border-dash-gap-[8px] text-red-600 p-4">
Dash 12px, Gap 8px
</div>
This trick works for both horizontal and vertical borders:
/*Horizontal*/
background-image: linear-gradient(to right, black 33%, rgba(255,255,255,0) 0%);
background-position: bottom;
background-size: 3px 1px;
background-repeat: repeat-x;
/*Vertical*/
background-image: linear-gradient(black 33%, rgba(255,255,255,0) 0%);
background-position: right;
background-size: 1px 3px;
background-repeat: repeat-y;
You can adjust the size with background-size and the proportion with the linear-gradient percentages. In this example I have a dotted line of 1px dots and 2px spacing. This way you can have multiple dotted borders too using multiple backgrounds.
Try it in this JSFiddle or take a look at the code snippet example:
div {
padding: 10px 50px;
}
.dotted {
border-top: 1px #333 dotted;
}
.dotted-gradient {
background-image: linear-gradient(to right, #333 40%, rgba(255, 255, 255, 0) 20%);
background-position: top;
background-size: 3px 1px;
background-repeat: repeat-x;
}
.dotted-spaced {
background-image: linear-gradient(to right, #333 10%, rgba(255, 255, 255, 0) 0%);
background-position: top;
background-size: 10px 1px;
background-repeat: repeat-x;
}
.left {
float: left;
padding: 40px 10px;
background-color: #F0F0DA;
}
.left.dotted {
border-left: 1px #333 dotted;
border-top: none;
}
.left.dotted-gradient {
background-image: linear-gradient(to bottom, #333 40%, rgba(255, 255, 255, 0) 20%);
background-position: left;
background-size: 1px 3px;
background-repeat: repeat-y;
}
.left.dotted-spaced {
background-image: linear-gradient(to bottom, #333 10%, rgba(255, 255, 255, 0) 0%);
background-position: left;
background-size: 1px 10px;
background-repeat: repeat-y;
}
<div>no
<br>border</div>
<div class='dotted'>dotted
<br>border</div>
<div class='dotted-gradient'>dotted
<br>with gradient</div>
<div class='dotted-spaced'>dotted
<br>spaced</div>
<div class='left'>no
<br>border</div>
<div class='dotted left'>dotted
<br>border</div>
<div class='dotted-gradient left'>dotted
<br>with gradient</div>
<div class='dotted-spaced left'>dotted
<br>spaced</div>
You cannot do it with pure CSS - the CSS3 spec even has a specific quote about this:
Note: There is no control over the spacing of the dots and dashes, nor over the length of the dashes. Implementations are encouraged to choose a spacing that makes the corners symmetrical.
You can, however, use either a border-image or a background image that does the trick.