Video summary
The video introduces an innovative CSS technique that allows border radius values to automatically disappear when an element reaches the edge of its viewport or parent container. The core concept involves using mathematical logic within CSS properties to invert the standard behavior where larger elements typically result in larger rounded corners. By calculating the difference between a fixed maximum width, such as 100 viewport units, and the current element width, developers can create a dynamic border radius that shrinks as the element grows. This approach ensures that when an element fills the entire available space, the calculated radius approaches zero, effectively creating sharp edges at the boundaries while maintaining rounded corners when there is still room to grow.
However, simply using this mathematical subtraction creates two distinct issues that require further refinement. First, as the element shrinks away from the edge, the border radius becomes excessively large, which is usually undesirable; this is solved by applying the `clamp` function to set a minimum limit on the radius size. Second, there is an unwanted transitional zone near the edge where the rounding effect fades gradually rather than switching instantly. To eliminate this "squishy" area, the video suggests using an exponent in the calculation to make the middle value either gigantic or zero, forcing an immediate transition between the rounded and sharp states once the element touches the boundary.
The implementation of this trick also addresses practical limitations regarding scrollbars and different container contexts. Initially, the technique fails on pages with fixed scrollbars because the 100 viewport unit calculation does not account for the scrollbar's space, preventing the element from ever truly reaching full width. This is resolved by utilizing the `scrollbar-gutter-stable` property, which reserves space for the scrollbar in supported browsers, ensuring accurate detection of the edge. Furthermore, the method is adaptable to internal containers rather than just the main viewport by switching to container query units, allowing the same logic to apply when an element fills a specific parent div. If no container is defined, the code defaults to using the viewport, making the solution robust across various layout scenarios.
The video concludes by acknowledging the origins of this clever workaround, crediting Ahmad Shadeed for the initial concept in 2021 and Adam Argyle for popularizing it through his Open Props project. The presenter expresses gratitude to these sources as well as to the channel's patrons for their support. Ultimately, the tutorial demonstrates how combining basic arithmetic with modern CSS features like `clamp`, container queries, and scrollbar handling can solve a complex visual problem with relative ease, encouraging developers to experiment with these tricks to enhance their web designs.
Read the full video transcript
Hello, my friend and friend. Wouldn't it
be really cool to have a border radius
that could turn itself off if an element
touched the edge of the viewport or of
its parent? Well, as you can see on the
screen right now, this is totally
possible. And not only is it possible,
it's actually relatively easy to do. So,
let's dive in and explore how we can
pull this off. So, as you might expect,
the very first thing we want to do is
add a border radius to our element. But
if we just do a fixed border radius like
this, well, it doesn't really help us
out. So, we need to think about how can
we make a border radius that can adjust
according to the size that it is. And
one of the ways that we can do that is
by using a percentage. But as you might
know, if you're using a percentage for a
border radius, this can cause a bit of a
weird behavior where you're getting
these weird shapes if you don't have
perfect squares. And this is also
working a little bit backward from what
we need because the larger we get, the
larger the border radius, and the
smaller we get, the smaller the border
radius. And we need to figure out a way
to invert that so we can get to zero
when we're at full size and have a
border radius when we're not at full
size. But of course, that raises a
really important question. How can we
get something to work backward like
that? And we don't have a unit that
actually allows us to pull something
like that off. But there's actually a
clever way that we can accomplish this
by using a little bit of math. If we set
the border radius by looking at the
viewport width and subtracting 100% from
100 viewport width. And that might sound
a little bit weird, but what it means is
the closer we get to the edge here, the
closer these numbers are to being the
same. So, if we just assumed that 100
viewport width would be 1,000 pixels and
we are around 50% of the size of the
viewport, we'd essentially be saying
that our border radius is 1,000 pixels
minus 500 pixels, giving us a border
radius of 500. If I got larger, now my
border radius is starting to shrink
because now it would be 1,000 pixels
minus, say, 750 pixels, leaving us with
a border radius of only 250. And then
the closer we get to the edge, the
closer we get to being 1,000 minus
1,000, so we have almost zero for our
border radius. And of course, this is
looking pretty good, but it's left us
with two problems. The first one is the
smaller we get, the larger and larger
and larger our border radius gets, and
we probably don't want that to happen.
And the second one is we want it to
instantly switch from zero to our
desired border radius. So, taking these
two problems in order, the first thing
we can do is use clamp to set some
limits on the total size of our border
radius. So, now as we start to shrink,
it will hit our 50 pixels and then never
get smaller than that, and then we still
get close to the zero at the edge there.
Now, we're left with the second problem
of how do we get rid of this little
weird squishy zone that's right near the
edge. And to accomplish that, we just
need the middle value to either be zero
or really, really big, and we can make
it really, really big by just putting an
exponent in there. And now we're saying
that this number is either gigantic,
which means it's going to clamp at the
50 pixels, or it's instantly going to
switch to zero and then it's going to be
our zero value there. And as we can see
now, it will instantly switch when we
get to the edge of our viewport, which
is fantastic. And as cool as this is,
there is a big problem with this cuz
it's not always going to work because a
lot of the time you are going to have a
scroll bar on your page. And if you have
a scroll bar, the 100 VW doesn't take
that into account, and it actually will
make it so it won't ever detect that
we're at 100 VW cuz your elements will
stop at the edge of the scroll bar. Of
course, this requires a fixed scroll
bar, but a lot of users have one. But
there's luckily an easy solution to this
now thanks to some updates they're
making in the browsers. Browser support
for this isn't perfect, but scroll bar
gutter stable will have it take into
account the space where the scroll bar
is on browsers and OS's where there is a
fixed scroll bar. And this is all fine
and dandy, but we do have one more
problem we have to address, which is
what happens if we're not trying to
detect the sides of the viewport, but of
another element instead. Well, as some
of you might have guessed, there is a
relatively easy solution to this, which
is to have our parent be a container,
and by making it a container, we can
switch our viewport units to container
units instead, and just like magic,
we'll know when we're taking up the
entire width of a container as well. And
a handy thing of using container query
units like I did here is that if you
don't have a defined container anywhere,
it will just use the viewport instead
anyway, so it will work in all the
different situations that you might run
into. And I can't leave this video
without saying a very big thank you to
my sources for this, uh which are Adam
Argyle and Ahmad Shadeed. Ahmad actually
came up with this back in 2021, or at
least that's when his blog article was
written, and I found that recently
thanks to Adam Argyle's Open Props,
where he was using something like this
and referenced Ahmad's article. So,
thank you to them, and of course a very
big thank you to Johnny, who's my
enabler of awesome, as well as all my
other patrons and channel members for
their monthly support, and of course
until next time, don't forget to make
your corner of the internet just a
little bit more awesome.