Updating CSS Border Radius When A Container Is Overflowing
In this article we’ll create a container element that dynamically adjusts its border-radius when its contents overflows.
This week I learned about corner-shape via nerdy.dev. This led me down the path of adding big squircle corners to code blocks in the FilePond documentation. Great! But unfortunately they looked terrible when the scrollbar was active.
I wondered if I could detect (with CSS only) if a container is overflowing so I could dynamically lower the border-radius to fit the scrollbar, and I quickly found on bram.us that, yes, that’s very much possible.
So here we are, the CSS below detects the x and y overflow and then sets the per corner border-radius accordingly.
In short, the --overflows-x and --overflows-y custom properties are set to 1 if overflow is detected (with the CSS animation). The amount we subtract from the default border-radius --tl is multiplied by the --overflows variable which either sets it to 0 or results in a lowered border-radius.
We use max() to set the --br border-radius so if either of the two --overflows variables is 1 the border-radius is lowered.
Scroll down for demo’s, please note that at the time of this writing this only works in Chrome and Safari, see caniuse for latest support stats.
pre {
/* fallback */
border-radius: 0.5em;
}
/* corners */
@supports (animation-timeline: scroll(self)) {
pre {
--overflows-x: 0;
--overflows-y: 0;
animation: detect-overflow-x, detect-overflow-y;
animation-timeline: scroll(x self), scroll(y self);
/* the default border radius */
--tl: 2em;
/* what we subtract from the default when overflowing */
--s: 1.5em;
/* calculate the border radius for each corner */
--tr: calc(var(--tl) - (var(--overflows-y) * var(--s)));
--br: calc(
var(--tl) - (max(var(--overflows-x), var(--overflows-y)) * var(--s))
);
--bl: calc(var(--tl) - (var(--overflows-x) * var(--s)));
border-radius: var(--tl) var(--tr) var(--br) var(--bl);
}
}
@keyframes detect-overflow-x {
from,
to {
--overflows-x: 1;
}
}
@keyframes detect-overflow-y {
from,
to {
--overflows-y: 1;
}
}
No scrollbars
When no scrollbars are active all corners use a big border-radius.
Vertical scrollbar
We automatically lower the top right and bottom right border-radius.
Horizontal scrollbar
When only a horizontal scrollbar is visible we lower the bottom left and bottom right border-radius.
Both horizontal and vertical scrollbar
Now we lower all the border-radius values except for the top left one.