Why Doesn't Min() (Or Max()) Work with Unitless 0

Why doesn't min() (or max()) work with unitless 0?

You need to add a unit to 0 otherwise it's confusing for the browser to handle the comparison between a uniteless value (a <number>) and a value with unit (a <length>) and the top property accept a <length> not a <number>

top: max(0px, 120vh - 271px)

To understand this, you need to follow the specification:

The min() or max() functions contain one or more comma-separated calculations, and represent the smallest (most negative) or largest (most positive) of them, respectively.

Then for calculations:

A calc() function contains a single calculation which is a sequence of values interspersed with operators, and possibly grouped by parentheses (matching the <calc-sum> grammar),

So the content of min()/max() is treated like the one of calc() then from the type checking

A math function can be many possible types, such as <length>, <number>, etc., depending on the calculations it contains, as defined below. It can be used anywhere a value of that type is allowed.

and

Note: Altho there are a few properties in which a bare <number> becomes a <length> at used-value time (specifically, line-height and tab-size), <number>s never become "length-like" in calc(). They always stay as <number>s.

You may get surprised but using top:0 is valid while top:min(0) or top:max(0) is not. To make them valid you need to add the unit.

But you can use opacity: min(0) for example since opacity accept a number as argument.

Worth to note that the same also apply to clamp() since it's equivalent to max(MIN, min(VAL, MAX))

Related: Why doesn't css-calc() work when using 0 inside the equation?

Why doesn't css-calc() work when using 0 inside the equation?

The first equation is invalid because it will lead to calc(-10px + 0)

Note: Because <number-token>s are always interpreted as <number>s or <integer>s, "unitless 0" <length>s aren’t supported in calc(). That is, width: calc(0 + 5px); is invalid, even though both width: 0; and width: 5px; are valid. ref

And if the result was non-zero you will fall into this:

At + or -, check that both sides have the same type, or that one side is a <number> and the other is an <integer>. If both sides are the same type, resolve to that type. If one side is a <number> and the other is an <integer>, resolve to <number>.

The last one is more logical since 10px + 5 has no meaning whearas we may think that 10px + 0 is simply 10px but for the browser it's not.

Related question: Why doesn't min() (or max()) work with unitless 0?

Why is the width of this element not 0?

width accept length or percentage values and your calc() will return an integer.

It may look trivial for you because the result is 0 but it's not the case for the browser. calc(0) is not handled the same way as 0. The first one is invalid with width while the second is valid.

A math function can be many possible types, such as <length>, <number>, etc., depending on the calculations it contains, as defined below. It can be used anywhere a value of that type is allowed. ref

Add a unit to overcome this:

:root {
--show: 1;
}

.test {
display: inline-block;
overflow: hidden;
width: calc((var(--show) - 1)*1px);
opacity: calc(var(--show) - 1);
}
<span class="test">test</span>
<span class="test2">test2</span>

Why the CSS calc() function is not working?

You need to add spaces between operators, it's a common mistake to forget them. We can also nest operation using calc as many as we want but they are equivalent to simple parentheses.

From the documentation:

Note: The + and - operators must be surrounded by whitespace. For
instance, calc(50% -8px) will be parsed as a percentage followed by a
negative length—an invalid expression—while calc(50% - 8px) is a
percentage followed by a subtraction operator and a length. Likewise,
calc(8px + -50%) is treated as a length followed by an addition
operator and a negative percentage.

The * and / operators do not require whitespace, but adding it for
consistency is both allowed and recommended.

Note: It is permitted to nest calc() functions, in which case the
inner ones are treated as simple parentheses.

.one {
background: red;
width: calc(100% - 150px);
margin-top: calc(20px + calc(40px * 2)); /*Same as calc(20px + (40px * 2))*/
height: calc(100px - 10px);
padding: calc(5% + 10px) calc(5% - 5px);
}
<div class="one">

</div>

CSS nested minmax inside of grid layout

Use min() inside minmax() like below

.container {
display:grid;
grid-template-columns: repeat(auto-fill, minmax(min(15%, 180px), 1fr));
grid-gap:10px;
margin:5px;
}
.container > * {
height:50px;
background:red;
}
<div class="container">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>

<div class="container" style="grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>

Can I apply CSS to a flex-item when it wraps onto a new row?

For this particular case you can consider the use of max() combined with flex-basis. The trick is to either have 0px (horizontal item) or a very big value (vertical items).

You will note that this is not a generic solution and the value is based on your html structure:

395px = 300px (width of a-fx) + 70px (flex-basis of b-fc) + 10px (border of wrapper) + 16px (default body margin) - 1px

.wrapper {
border: 5px solid pink;
display: flex;
flex-wrap: wrap;
justify-content: center;
}

.a-fc {
background-color: purple;
width: 300px;
}

.b-fc {
background-color: orange;
display: flex;
flex-wrap: wrap;
flex-basis: 70px;
flex-grow: 1;
}

.b-fc>* {
flex-grow: 1;
flex-basis: max(0px, (100vw - 395px)*100);
height: 100px;
}

.b-fc>*:nth-child(1) {
background-color: red;
}

.b-fc>*:nth-child(2) {
background-color: blue;
}

.b-fc>*:nth-child(3) {
background-color: green;
}
<div class="wrapper">
<div class="a-fc">
<div>a1</div>
</div>
<div class="b-fc">
<div>b1</div>
<div>b2</div>
<div>b3</div>
</div>
</div>

When specifying a 0 value in CSS, should I explicitly mark the units or omit?

I argue you should also omit the units.

From a programmer's perspective, 0 == null == none == false, where 0px == 0px only.

Which means that if you specify a border width of 0 then no border will be there, but if you specify a 0px border, then a border of 0 px will be created (that's the idea behind it, in reality 0px gives the exact same result like 0).

Further Points

  • unit-less 0 makes it easier to read as it is easily distinguishable from normal unit'ed values.
  • It makes sense to remove the units as they have no point in being there (0 could mean size, color, etc.).

Conclusion: Omit the units in 0. They're not needed and confusing.



Related Topics



Leave a reply



Submit