Calc of max, or max of calc in CSS
Asked Answered
S

8

166

Is it possible to do something like this

max-width: calc(max(500px, 100% - 80px))

or

max-width: max(500px, calc(100% - 80px)))

in CSS?

Sigismond answered 17/5, 2013 at 20:19 Comment(3)
Have you tried them out yourself?Fleischer
As @gert-sønderby said, just use these two: min-width:500px; width:calc(100% - 80px);Tondatone
some time you don't know which one is bigger. is 500px bigger or calc(100% - 80px) bigger ?Countrified
E
74

min(), max(), and clamp() are finally available!

Support starts in Firefox 75, Chrome 79, and Safari 11.1 (clamp is available in Safari 13.1).

min() and max() take any number of arguments.

clamp() has syntax clamp(MIN, VAL, MAX) and is equivalent to max(MIN, min(VAL, MAX)).

min() and max() may be nested. They can be used in calc() as well as outside of it, they also may contain math expressions, that means you can avoid calc() when using them.

Therefore the original example can be written as:

max-width: max(500px, 100% - 80px);
Eats answered 7/4, 2020 at 16:50 Comment(3)
For what it's worth, MS Edge for macOS (Version 81.0.416.68) also allows these. One would assume the Windows version also works. Don't know the min supported version.Ambrogino
The new Edge is essentially Chrome, its versions follow that of Chrome. Full browser compatibility data is at the end of the linked pages.Eats
Someone, give this guy some awardPhonemics
P
128

A 'pure' css solution actually is possible now using media queries:

.yourselector {
  max-width: calc(100% - 80px);
}

@media screen and (max-width: 500px) {
  .yourselector {
    max-width: 500px;
  }
}
Pitching answered 2/6, 2016 at 19:2 Comment(2)
Great solution! I've used it actually for min height, apparently you may use media queries for max-height as well +1Ru
That's a basic workaround, it won't work if the css rule is to be applied to an element rather than the whole screen.Melville
W
105

No you cannot. max() and min() have been dropped from CSS3 Values and Units. They may be re-introduced in CSS4 Values and Units however. There is currently no spec for them, and the calc() spec does not mention that either are valid inside a calc() function.

Weighting answered 17/5, 2013 at 20:36 Comment(7)
Thank you. Is there an alternative in order to have the same result ?Sigismond
You can use JavaScript to get the computed style (actually the used style) of the element. Remove 80px from it and compare it to 500 to see which is greater. Something like var val = parseInt(window.getComputedStyle(el,null).getPropertyValue("width")) - 80 ) for getting the width - 80 and el.style.maxWidth for setting the max-width.Weighting
Thank you. However, I would prefer a pure CSS solution.Sigismond
Anytime there is a CSS question and a response begins with "You can use JavaScript", it's incorrect. There are many valid reasons for wanting to keep all presentation code in CSS. All-- not most.Chink
It seems like min() and max() are back in CSS Values and Units Module Level 4 (Editor’s Draft, 1 September 2017) Link: drafts.csswg.org/css-values/#calc-notationMorven
BUT there is a solution to the problem, keep scrolling to @andy answer belowRockabilly
I'm sorry, but you didn't mention it works perfectly in Safari: Reference, Browser compatibility. So the answer to "is it possible?" should not be: "No you cannot." You should always mention browser compatibility in your browser related answers.Curtate
E
74

min(), max(), and clamp() are finally available!

Support starts in Firefox 75, Chrome 79, and Safari 11.1 (clamp is available in Safari 13.1).

min() and max() take any number of arguments.

clamp() has syntax clamp(MIN, VAL, MAX) and is equivalent to max(MIN, min(VAL, MAX)).

min() and max() may be nested. They can be used in calc() as well as outside of it, they also may contain math expressions, that means you can avoid calc() when using them.

Therefore the original example can be written as:

max-width: max(500px, 100% - 80px);
Eats answered 7/4, 2020 at 16:50 Comment(3)
For what it's worth, MS Edge for macOS (Version 81.0.416.68) also allows these. One would assume the Windows version also works. Don't know the min supported version.Ambrogino
The new Edge is essentially Chrome, its versions follow that of Chrome. Full browser compatibility data is at the end of the linked pages.Eats
Someone, give this guy some awardPhonemics
R
46

A workaround would be to use width itself.

max-width: 500px;
width: calc(100% - 80px);
Rescript answered 13/10, 2015 at 11:1 Comment(5)
This is a good idea, but if I understand @Arnaud's question correctly, he wants the max-width of either 500px or 100% - 80px. Your solution limits the max-width to 500px even if 100% - 80px is larger.Gristly
But it's the same as using min() therefore maybe helpful to others.Mien
It seems to me that using min-width instead of max-width in the above example might be an equivalent to the asked-for behavior, though.Terti
Answer helped me add a margin to a flex container once the page width got small. codepen.io/OBS/pen/wGrRJVGruel
I posted a solution demonstrating @GertSønderby's comment is indeed the correct solution.Faria
F
15

While @david-mangold's answer above, was "close" it was incorrect.
(You can use his solution if you want a minimum width, instead of a maximum width).

This solution demonstrates that @gert-sønderby comment to that answer does work:
The answer should have used min-width, not max-width.

This is what it should have said:

min-width: 500px;
width: calc(100% - 80px);

Yes, use min-width plus width to emulate a max() function.

Here's the codepen (easier to see the demo on CodePen, and you can edit it for your own testing).

.parent600, .parent500, .parent400 {
    height: 80px;
    border: 1px solid lightgrey;
}
.parent600 {
    width: 600px;
}
.parent500 {
    width: 500px;
}
.parent400 {
    width: 400px;
}

.parent600 .child, .parent500 .child, .parent400 .child {
    min-width: 500px;
    width: calc(100% - 80px);
    border: 1px solid blue;
    height:60px;
}

.ruler600 {
    width: 600px;
    border: 1px solid green;
    background-color: lightgreen;
    height: 20px;
    margin-bottom: 40px;
}
.width500 {
    height: 20px;
    width: 500px;
    background-color: lightyellow;
    float: left;
}
.width80 {
    height: 20px;
    width: 80px;
    background-color: green;
    float: right;
}

.parent600 .wrong, .parent500 .wrong, .parent400 .wrong {
    max-width: 500px;
    width: calc(100% - 80px);
    border: 1px solid red;
    height:60px;
}
<h2>(Min) min-width correctly gives us the Larger dimension: </h2>
<div class="parent600">
    600px parent
    <div class="child">child is max(500px, 600px - 80px) = max(500px, 520px) = 520px</div>
</div>

<div class="ruler600"><div class="width500">500px</div>20<div class="width80">80px</div></div>

<div class="parent500">
    500px parent
    <div class="child">child is max(500px, 500px - 80px) = max(500px, 420px) = 500px</div>
</div>

<div class="ruler600"><div class="width500">500px</div><div class="width80">80px</div></div>

<div class="parent400">
    400px parent (child expands to width of 500px)
    <div class="child">child is max(500px, 400px - 80px) = max(500px, 320px) = 500px</div>
</div>
<div class="ruler600"><div class="width500">500px</div><div class="width80">80px</div></div>


<h2>(Max) max-width <em>incorrectly</em> gives us the Smaller dimension: </h2>
<div class="parent400">
    400px parent
    <div class="wrong">child is min(500px, 400px - 80px) = min(500px, 320px) = 320px</div>
</div>
<div class="ruler600"><div class="width500">500px</div><div class="width80">80px</div></div>

<div class="parent500">
    500px parent
    <div class="wrong">child is min(500px, 500px - 80px) = min(500px, 420px) = 420px</div>
</div>

<div class="ruler600"><div class="width500">500px</div><div class="width80">80px</div></div>

<div class="parent600">
    600px parent
    <div class="wrong">child is min(500px, 600px - 80px) = min(500px, 520px) = 500px</div>
</div>

<div class="ruler600"><div class="width500">500px</div>20<div class="width80">80px</div></div>

That said, @andy's answer above may be easier to reason about, and may be more appropriate in many use cases.

Also note, that eventually a max() and a min() function may be introduced to CSS, but as of April 2019 it is not part of the spec.

Faria answered 9/4, 2019 at 15:5 Comment(1)
Why the downvote? Everything stated is correct, and all sources have been linked to and credited.Faria
C
10

Change max to Max, you will see the dirty magic

max-width: Max(500px, calc(100% - 80px)))
Countrified answered 24/11, 2020 at 2:28 Comment(2)
Thanks! You're right. As per this article: css-tricks.com/when-sass-and-new-css-features-collide This is because Sass has its ownmin() function, and ignores the CSS min() function. The trick here is to remember that Sass is case-sensitive, but CSS isn’t.Mikes
Thank you! I don't know why sass-loader's error isn't more descriptive to suggest this might be the issue.Baluchi
B
1

@Amaud Is there an alternative in order to have the same result ?

There is a non-js pure css approach that would achieve similar results. You would need to adjust the parent elements container padding/margin.

.parent {
    padding: 0 50px 0 0;
    width: calc(50%-50px);
    background-color: #000;
}

.parent .child {
    max-width:100%;
    height:50px;
    background-color: #999;
}
<div class="parent">
  <div class="child"></div>
</div>
Bullnose answered 25/1, 2018 at 17:41 Comment(0)
F
1

This is only supported in dart-sass https://sass-lang.com/documentation/syntax/special-functions#min-and-max.

You can also make use of string interpolation (similar to CSS variables) for this to work outside of dart-sass

max-width: #{"max(500px, calc(100% - 80px))"}
Foley answered 11/9, 2020 at 22:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.