Crispy dashed borders
So, you want to draw a perfectly even dashed border around your HTML element? At first glance, it looks like a no-brainer. However, I soon realized there are nuances.
This is the design: we want a pixel-perfect, evenly distributed dashed border around an image.

Navigate to "Basic solution" Basic solution
Okay, you say. Let’s slap on some CSS border-style on it. Right? Well, check what happens when i do.
Check the dashes around the corners. They are congested. Drawing dashes evenly works much nicer when using an SVG instead. Check the following example.
Much better, isn’t it? We are using an almost full-sized <rect> with some stroke-dasharray pattern. And look at that, it already prettier.
Navigate to "Further improvements" Further improvements
So there are more things that bothers me:
- If the stroke is very narrow then it’s barely visible.
- We had to scale down the
<rect>
Navigate to "Overflow" Overflow
Why is that? Well, in SVG, strokes are naturally centered on the shape’s path. Anything that overflows is hidden because of how HTML works: images generally don’t spill beyond their bounds.
There are clever techniques that rely on techniques that rely on <clip-path> or <mask> while shrinking the original object, but I found the most elegant solution from Josh Comeau: overflow: visible ✨. We allow the spillover: overflow: visible ✨. We simply allow the spillover.
Navigate to "Scaling" Scaling
Perfect, but we can make it even better.
By default, when we scale (stretch or squish) an SVG, the strokes are affected by vector transformations. We can opt out if we use preserveAspectRatio on the SVG itself, but what if that’s not an option?
We can use a ‘hidden’ SVG feature called vector-effect: non-scaling-stroke. Rich Harris has a great article on applying this to data visualization. With this property, the stroke width remains independent of the transformation. It also affects the dash pattern, making it render even more cleanly. The browser calculates the stroke width based on the screen pixels rather than the internal SVG coordinate system
To be honest, it’s an optional property that depends on the final design requirements. Check out the following example and experiment with different sizes or zoom levels!