I was watching Juxtopposed’s video on blurring things and really liked “Level 5 - clip-path” where we create a border with backdrop-blur accomplish glowing border effect.

But, I really like rounded borders (i.e. border-radius); and to my knowledge, there is no method that allows us to use clip-path to create rounded borders without defining a bunch more points.


The final results of my method; hover over the buttons to see the effect.

As I was aiming to use pure CSS, the calc() function does not allow us to divide a value with units by another, so I had to use border-thickness ratio to express the border-radius where $\mathrm{radius} = \mathrm{ratio} \times \mathrm{thickness}$.

It would probably be more useful to use a preprocessor that allows us to compute $\mathrm{ratio} = \mathrm{radius} \div \mathrm{thickness}$ to use in the radial-gradient.


.glass-border {
    // These CSS variables can be redefined per-element.
    --thickness: 3px;
    --ratio: 4;
    --r: calc(var(--ratio) * var(--thickness));
    --blur: 40px;

.glass-border {
    position: relative;
    border-radius: var(--r);

    outline: var(--thickness) solid transparent;

    &:after {
        content: '';

        position: absolute;
        top: 0; left: 0;

        width: 100%;
        height: 100%;

        --border-linear-gradient: #0000, #0000 var(--r), #000 var(--r), #000 calc(100% - var(--r)), #0000 calc(100% - var(--r)), #0000;
        --corner-thickness: calc(100% * (1 - 1 / var(--ratio)));
        --border-radial-gradient: #0000, #0000 var(--corner-thickness), #000 var(--corner-thickness), #000 101%, #0000 101%;

                0 100% / var(--thickness) 100% no-repeat,
                100% 100% / var(--thickness) 100% no-repeat,
            linear-gradient(to right, var(--border-linear-gradient))
                0 0 / 100% var(--thickness) no-repeat,
            linear-gradient(to right, var(--border-linear-gradient))
                0 100% / 100% var(--thickness) no-repeat,

            conic-gradient(from 270deg at var(--r) var(--r), #000, #000 90deg, #0000 90deg, #0000)
                0 0 / calc(100% - var(--r)) calc(100% - var(--r)) repeat intersect,
            radial-gradient(var(--r) at right var(--r) top var(--r), var(--border-radial-gradient)) add,
            radial-gradient(var(--r) at right var(--r) bottom var(--r), var(--border-radial-gradient)) add,
            radial-gradient(var(--r) at left var(--r) top var(--r), var(--border-radial-gradient)) add,
            radial-gradient(var(--r) at left var(--r) bottom var(--r), var(--border-radial-gradient)) add;

        backdrop-filter: blur(var(--blur));
        pointer-events: none;

        z-index: 2;

Clip-path Issues§

The clip-path works fine if you desire sharp corners.


But it is not possible to combine this method with border-radius to accomplish rounded borders.



The issue with just applying `border-radius` is that the interior parts of the `clip-path` aren't rounded off, and there is no obvious way to accomplish this.

There is also this SVG that we can apply as a filter to round out the clip-path but it still only manages to round the exterior of the border and not the interior.

<svg style="visibility: hidden; position: absolute;" width="0" height="0">
        <filter id="goo"><feGaussianBlur in="SourceGraphic" stdDeviation="8" result="blur" />
            <feColorMatrix in="blur" mode="matrix"
                values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 19 -9" result="goo" />
            <feComposite in="SourceGraphic" in2="goo" operator="atop"/>

svg filter

CSS Masks§

The CSS mask property allows us to define a mask using some image as a mask-reference.

Regions of the underlying HTML element are exposed depending on the alpha value in the mask image.

(a) Base image
(b) Mask where the blue are regions that will be left unmasked.
(c) Image + Mask


Linear Gradients§

Typically, we’d use gradients to smoothly transition between colors.

Standard linear-gradient defined with evenly-spaced color stops.

But, we can create abrupt transitions by defining two colors at the same stop.

linear-gradient with a hard color transition between orange and green.

Using this, we can create a linear-gradient that is opaque at the edges and transparent else-where as one part of our mask.

Using linear-gradient to create masks for the straight border regions.

With this, we are able to form the straight lines composing the sides of the border and there is empty space where the rounded corners should be.

Radial Gradient§

A radial-gradient allows us to transition between colors starting from a central point.

Standard radial-gradient.

Using the same hard-transition trick with color stops, we can create an annulus.

A ring created via radial-gradient with hard-transitions.

We can add these rings into our mask to form our rounded borders.

Composition of our straight-line linear-gradient and annular radial-gradients for the corners.

Conic Gradient§

A conic-gradient is different from a radial-gradient in that we create a gradient travelling around a circle, rather than emanating from a point.

Standard conic-gradient.

Applying the hard-transition trick we can use this to create a conic-gradient which shades in only a quadrant.

Quarter-shading with conic-gradient.

Using this, we can pick out a quarter of the ring created by radial-gradient by using the intersect mask-composition method.

Quarter-ring by composing conic-gradient with radial-gradient.

Then applying this technique to all four corners, it allows us to create the rounded borders using mask

Final rounded-border result with solid background.

Through this, we are able to create an :after pseudoelement that has the same dimensions as the parent element and apply this mask with a backdrop-blur which creates the (rounded) glassy border effect we are looking for.