CSS comparability capabilities have been supported since virtually April 2020, and I wrote an introductory article about them again then. I like to make use of all of them, however my favourite considered one of them is clamp() and it’s the highest used one for me.
On this article, I’ll discover a couple of use-cases for comparability capabilities, and clarify every one intimately. Principally, the use circumstances will probably be about conditions apart from utilizing them for fluid sizing, as that is the most well-liked use case and I’ll maintain that to the final.
In case you don’t learn about comparability capabilities, that’s completely fantastic. I like to recommend studying this introduction article first after which coming again right here for the use circumstances.
Use circumstances for clamp(), max(), and min() CSS capabilities
Fluid sizing and positioning
On this instance, we’ve a piece with a cell phone, together with two pictures which can be positioned on high. Initially, it should appear like the next determine:
When the width of the container turns into smaller, we need to shrink the dimensions of the photographs to accommodate the accessible area. We will try this by utilizing a proportion worth for the width or the peak (e.g: width: 20%
) however this doesn’t give us a lot management.
We wish to have the ability to have a fluid dimension, that respects a minimal and a most worth on the similar time. That is the place clamp
come to the rescue!
.section-image {
width: clamp(70px, 80px + 15%, 180px);
}
By setting a minimal, most well-liked, and most width, the picture will shrink or develop as per its container width. This is because of utilizing a mixture of a hard and fast worth and proportion 80px + 15%
.
Ornamental component
Have you ever ever wanted so as to add an ornamental component to a piece? More often than not, the component must be responsive and may should be positioned in another way based mostly on the viewport dimension.
Think about the next instance.
There are two ornamental parts on either side. On cellular, they are going to occupy an excessive amount of area and so we need to present solely a little bit of every one.
To repair that, we are able to use media queries to offset them on cellular.
.decorative--1 {
left: 0;
}
.decorative--2 {
proper: 0;
}
@media (max-width: 600px) {
.decorative--1 {
left: -8rem;
}
.decorative--2 {
proper: -8rem;
}
}
Whereas this works, we are able to use a media query-less answer with CSS clamp()
operate.
@media (max-width: 600px) {
.decorative--1 {
left: clamp(-8rem, -10.909rem + 14.55vw, 0rem);
}
.decorative--2 {
proper: clamp(-8rem, -10.909rem + 14.55vw, 0rem);
}
}
Let me dissect the above CSS to make it simpler for you:
- What we would like is to set the minimal
left
offset as-8rem
, and the utmost worth as0rem
. - With that, we depart it to CSS
clamp()
to resolve on the most well-liked worth and respect the minimal and most values we set.
I used this calculator to get the above clamp()
numbers.
Fluid hero top
Associated to the earlier instance, a hero part top might be totally different based mostly on the viewport dimension. Because of this, we have a tendency to alter that by way of a media question or by utilizing viewport items.
.hero {
min-height: 250px;
}
@media (min-width: 800px) {
.hero {
min-height: 500px;
}
}
We will use a mixture of mounted worth and viewport items, however we should be cautious to not have an enormous top on bigger viewports, after which we have to set a max top.
.hero {
min-height: calc(350px + 20vh);
}
@media (min-width: 2000px) {
.hero {
min-height: 600px;
}
}
With CSS clamp()
, we are able to set a minimal, most well-liked, and most top with just one CSS declaration.
.hero {
min-height: clamp(250px, 50vmax, 500px);
}
When resizing the display screen, you’ll discover that the peak adjustments steadily based mostly on the viewport width. Within the instance above, 50vmax
means “50% of the viewport’s largest dimension.
Loading bar
This instance is impressed by this tweet from Andy Bell. I actually like the usage of CSS clamp()
for this use case!
The bar thumb is meant to animate from the left to proper and vice versa. In CSS, the thumb might be positioned completely to the left.
.loading-thumb {
left: 0%;
}
To place the thumb to the far proper, we are able to use left: 100%
however this may introduce a problem. The thumb will blow out of the loading bar container.
.loading-thumb {
left: 100%;
}
That’s anticipated, as a result of 100%
on this context begins from the tip of the thumb, thus pushing it out.
We will use CSS calc()
to subtract the thumb width and it’ll work, however this isn’t 100% versatile.
.loading-thumb {
/* 40px represents the thumb width. */
left: calc(100% - 40px);
}
Let’s discover find out how to higher CSS for that utilizing CSS variables and comparability capabilities.
.loading-thumb {
--loading: 0%;
--loading-thumb-width: 40px;
place: absolute;
high: 4px;
left: clamp(
0%,
var(--loading),
var(--loading) - var(--loading-thumb-width)
);
width: var(--loading-thumb-width);
top: 16px;
}
Right here is how the above CSS works:
- First, we set a minimal worth of
0%
. - The popular worth is the present worth of the
--loading
CSS variable. - The utmost worth represents the present loading minus the thumb width.
CSS clamp()
right here present us with three totally different stats for this part. I personally like this answer!
Not solely that, we are able to lengthen the identical idea for a special design. Think about the next determine:
The present progress worth has a little bit deal with on high of it. When the worth is 100%, we want the width to respect that.
As you see within the determine under, the circle should finish on the far proper facet. If we don’t care for that, it should find yourself blowing out by half of the deal with width (See the second row with the pink signal).
In such a case, we are able to use CSS clamp() operate.
.loading-progress {
width: clamp(10px, var(--loading), var(--loading) - 10px);
}
The minimal worth is the same as half the circle width, the popular worth is the present loading proportion, and the utmost worth is the subtraction outcome of the present proportion from half of the circle.
Dynamic Line separator
Earlier this 12 months, I printed an article about an attention-grabbing CSS answer for a UI I used to be engaged on.
Think about the next determine the place we’ve a line separator between two sections.
On cellular, that separator ought to change into horizontal as under.
My answer was to make use of a border and flexbox. The concept is {that a} pseudo-element with a border can increase to fill the accessible area for each the vertical and horizontal states.
.part {
show: flex;
flex-direction: column;
hole: 1rem;
}
.part:earlier than {
content material: "";
border: 1px stable #d3d3d3;
align-self: stretch;
}
@media (min-width: 700px) {
.part {
align-items: heart;
flex-direction: row;
}
}
We will even do higher by utilizing CSS clamp. Temani Afif prompt an answer that doesn’t want a media question in any respect.
.part {
--breakpoint: 400px;
show: flex;
flex-wrap: wrap;
}
.part:earlier than {
content material: "";
border: 2px stable lightgrey;
width: clamp(0px, (var(--breakpoint) - 100%) * 999, 100%);
}
Let’s dissect the above CSS:
0px
: the minimal worth, used for the vertical separator. It’s zero as a result of we’re utilizing a CSS border as a substitute.(var(--breakpoint) - 100%) * 999
a toggle that swap between0px
or100%
based mostly on the viewport width.
Here’s a video:
Conditional border radius
Virtually a 12 months in the past, I noticed a neat CSS trick within the Fb feed CSS. It’s about utilizing CSS max()
comparability operate to change the radius of a card from 0px
to 8px
relying on the viewport width.
.card {
border-radius: max(
0px,
min(8px, calc((100vw - 4px - 100%) * 9999))
);
}
Let’s stroll via the above CSS intimately.
Let’s dissect the above CSS:
- We’ve got a
max()
operate that compares between0px
and the computed worth of themin()
. It is going to decide the bigger worth. - The
min()
operate compares between8px
and a computed worth fromcalc((100vw - 4px - 100%) * 9999)
. This can end in a really massive constructive or adverse quantity. - The
9999
is a big quantity to power the worth to be both0px
or8px
.
With the above, the cardboard could have a zero radius when it’s taking the complete viewport width, or 8px
on bigger screens. Neat, proper?
You may learn extra right here in regards to the full particulars of the approach.
Defensive CSS article header
Whereas constructing the article header for [Defensive CSS][https://defensivecss.dev/], I wanted a means so as to add dynamic padding to the content material whereas sustaining a minimal worth on smaller viewports.
The concept is that the article header isn’t contained with a wrapper component, so we want a technique to mimic that the content material is definitely wrapped and aligned with the content material beneath.
To try this, we want a means to make use of the next formulation in CSS:
dynamic padding = (viewport width – wrapper width) / 2
Because of the CSS max()
operate, we are able to add minimal padding, and a technique to swap to the dynamic padding when wanted.
:root {
--wrapper-width: 1100px;
--wrapper-padding: 16px;
--space: max(
1rem,
calc(
(
100vw - calc(var(--wrapper-width) - var(--wrapper-padding) *
2)
) / 2
)
);
}
.article-header {
padding-left: var(--space);
}
The concept is that we want the minimal padding to be 1rem
, after which it is going to be dynamic based mostly on the viewport width.
For extra particulars, you’ll be able to learn the complete article on this system.
Spacing
Typically, we would want to alter the spacing for a part or a grid based mostly on the viewport width. Not with CSS comparability capabilities! We solely have to set it as soon as.
.wrapper {
show: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: min(2vmax, 32px);
}
To study extra about spacing in CSS, I wrote a deep-dive article on that.