How to do a dashed border with a gradient and a border-radius in css?

Closest I could get to was with an svg background-image:
.dashed-border {
background-size: 100% 100%;
border-radius: 8px;
padding: 2px;
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 100 100" preserveAspectRatio="none"><defs><linearGradient id="borderGradient" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="6.34%" stop-color="%23fe8401" /><stop offset="51.74%" stop-color="%23c913b9" /><stop offset="97.13%" stop-color="%23009e9c" /></linearGradient></defs><path vector-effect="non-scaling-stroke" d="M8,1 H92 A7,7 0 0 1 99,8 V92 A7,7 0 0 1 92,99 H8 A7,7 0 0 1 1,92 V8 A7,7 0 0 1 8,1 Z" fill="none" stroke="url(%23borderGradient)" stroke-width="1" stroke-dasharray="6,6" /></svg>') !important;
}
.dashed-border {
background-size: 100% 100%;
border-radius: 8px;
padding: 2px;
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 100 100" preserveAspectRatio="none"><defs><linearGradient id="borderGradient" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="6.34%" stop-color="%23fe8401" /><stop offset="51.74%" stop-color="%23c913b9" /><stop offset="97.13%" stop-color="%23009e9c" /></linearGradient></defs><path vector-effect="non-scaling-stroke" d="M8,1 H92 A7,7 0 0 1 99,8 V92 A7,7 0 0 1 92,99 H8 A7,7 0 0 1 1,92 V8 A7,7 0 0 1 8,1 Z" fill="none" stroke="url(%23borderGradient)" stroke-width="1" stroke-dasharray="6,6" /></svg>') !important;
}
This looks fine if you have a 100px to 100px box (see 2cnd picture). But the border should fit on any box. As soon as you increase width and height to another aspect ratio, it breaks, especially the border-radius (see 1st picture). i also tried several different solutions, but nothing works as expected...
No description
36 Replies
oemer
oemerOP2w ago
No description
clevermissfox
clevermissfox2w ago
I would try a pseudo element with a 2px dashed transparent border, bg clip/origin to the border-box and mask padding-box exclude. Then the bg image of conic gradient . I'm on mobile and I'm trying not to hand out solutions anymore anyways (no one learns if they just copy and paste) but lmk if you have questions.
oemer
oemerOP2w ago
Does this approach only work with a white background? In my case the background has to be transparent
Chris Bolson
Chris Bolson2w ago
One method is to place the "border" gradient on a pseudo element and use a mask to only allow the edges to be visible, leaving the content area transparent.
capt_uhu
capt_uhu2w ago
the responsive squishing and stretching of the corners can be fixed by using border-image instead of background-image
Tok124 (CSS Nerd)
This is how i would do it https://codepen.io/tok124/pen/ZYEYxEZ
Tim
CodePen
Untitled
...
Tok124 (CSS Nerd)
Just make sure to include the vendor prefixes so that it works on chromium based browsers
No description
Tok124 (CSS Nerd)
i have autoprefixer enabled in codepen so you don't really see the prefixes unless you compile the code
clevermissfox
clevermissfox2w ago
Yea the mask will make it transparent except for the gradient in the borderbox “padding-box exclude “
clevermissfox
clevermissfox2w ago
Unprefixed for mask is pretty well supported ! The purple border shows versions when prefix was required. Although with autoprefixer it doesn’t hurt to include anyway ✨
No description
Tok124 (CSS Nerd)
Yeah, but you need it for the mask-composite 🙂
clevermissfox
clevermissfox2w ago
Aha that’s right , how quickly I forget ; just used it a few months ago and had to prefix for exclude
Tok124 (CSS Nerd)
Yeah 😄
oemer
oemerOP2w ago
Switching to border-image doesn't show anything anymore, do i need to adapt the svg?
oemer
oemerOP2w ago
That really looked promising, but as soon as you change the width/height the apperance breaks :/
No description
oemer
oemerOP2w ago
I also think border-image doesn't account for border-radius?
Tok124 (CSS Nerd)
Strange... Works fine for me... Correct
Tok124 (CSS Nerd)
@oemerSee here, works perfectly fine
Tok124 (CSS Nerd)
Maybe you changed the width/height of the pseudo element and thats why it looked messed up... But anyway, if it does look messed up on any width/height, just adjust the mask gradient
oemer
oemerOP7d ago
If you compare it to a normal css border, the line lenght and distance is different:
No description
oemer
oemerOP7d ago
But don't I have to adjust it for any case where i use this style then? The card could have different dimensions for different use cases @Tok124 (CSS Nerd) I really think this is onlypossible with javascript, where you get the dimensions of the container and do some calculations with it.. which i would like to avoid because of SSR
clevermissfox
clevermissfox7d ago
Yep you can’t use border radius on border-image
Tok124 (CSS Nerd)
Yeah. this is because i have used % unit. Idk if there is any other unit that would work better, perhaps vmin/vmax unit, i never really using these units, but maybe they could be useful here, otherwise you may have to go with em/rem/px unit
capt_uhu
capt_uhu7d ago
the radius of the corner is already included in the SVG image so border-radius wouldn't be necessary. or am i missing something?
Tok124 (CSS Nerd)
But yeah if you have a box like this, then 10% on the width is greater than 10% on the height, as you can probably imagine, that's why you end up with this problem, it's due to the % unit in mask gradient
No description
Tok124 (CSS Nerd)
But yeah if no other unit works you may need to use JS to calculate the correct % amount for the height
oemer
oemerOP7d ago
I see, if play around with values, it changes yeah
Tok124 (CSS Nerd)
Yeah 🙂
oemer
oemerOP7d ago
would love to avoid javascript, but with px values it seems to be tricky
Tok124 (CSS Nerd)
Otherwise you can use a conic-gradient, that works too, it may work a little better, but then there is a new problem, the corners may look kinda strange...
No description
oemer
oemerOP7d ago
also interesting, but there are always buggy artefacts depending on which size you go for unfortunatelyy.. not only the corners
No description
No description
oemer
oemerOP7d ago
Hopefully CSS will support this in the future Regardless, I learned a lot here, you guys are awesome
clevermissfox
clevermissfox7d ago
I got such an interesting result with a repeating conic gradient too, it looked like a pattern
capt_uhu
capt_uhu7d ago
For the future take a look at the border-area value for background-clip. It's only in Safari right now but hopefully Chrome and Firefox will start to play around with it this year. To be honest it's not the best solution for this (it's a bit clunky and hacky to reuse background and set the border to transparent) but it's something we got a browser to actually work on... https://github.com/w3c/csswg-drafts/issues/9456#issuecomment-2325278729 also tinkered with your svg a bit to get it to work in border-image as expected. Needed to remove the viewbox to make it a fixed size: https://codepen.io/jsnkuhn/pen/RNwNYdz
oemer
oemerOP7d ago
Oh wow, that looks really good! I am honestly baffled how deeply you guys understand CSS. I just checked all diffs. You are using a fixed height, not percent. You added 32 / 32px round to the border-image prop. You removed the viewBox and also vector scaling. If you miss one of those, it just breaks. I am really wondering how you learned this? Do you guys just do trial and error or is this your profession? It seems really complicated and very detailed. In my company i am the kind of "CSS guy" but i feel really noobish compared to you guys
capt_uhu
capt_uhu7d ago
updated the pen I made above to use the border-image-* long hands to give a better idea of what's going on. MDN article is probably the best place to find more info: https://developer.mozilla.org/en-US/docs/Web/CSS/border-image

Did you find this page helpful?