Is there a way to make CSS calc() never be a negative value?
Asked Answered
P

5

12

I have the following code which works great with centering my content until the vh is less then 650px. I was wondering if there was a way to make this value never go below 0 only using CSS calc.

.my-margin-top {
    margin-top: calc(50vh - 325px);
}
Photoengrave answered 24/2, 2016 at 15:14 Comment(1)
Does this answer your question? Calc of max, or max of calc in CSSCluny
L
18

Premising that there's no way to bound the values computed by calc() you could use a mediaquery when max-height is at most 650px

.my-margin-top {
    margin-top: calc(50vh - 325px);
}

@media all and (max-height: 650px) {
   .my-margin-top {
       margin-top: 0;
   }
}

or you might also revert the logic by wrapping the existing rule into a min-height mediaquery

@media all and (min-height: 650px) {
   .my-margin-top {
       margin-top: calc(50vh - 325px);
   }
}
Leaving answered 24/2, 2016 at 15:16 Comment(5)
great answer i was making a comment to change that to max-height, which you did before i got it out. I can't believe I wasn't thinking of a media query.Photoengrave
@cmorrissey: To be fair, your use case just happens to feature viewport units which lends itself to media queries. Generally speaking, you simply can't clamp the result of a calc() expression to a certain range of values - CSS would need to provide some form of min() and max() for that.Sigrid
@Sigrid an exception would occur when calc() is computing an height/width so you could limit with min/max-height/width (also without mediaqueries), see https://mcmap.net/q/1007965/-how-to-adjust-an-image-size-with-a-progressive-scaling-on-viewport-resizeLeaving
Yes, these are entirely property-dependent and don't apply in the general case. I've posted an answer now with more details. I also upvoted your answer.Sigrid
Be aware this is possible now! max(), min(), and clamp() are available in CSS now. So for the poster's question, one answer would be: max(0, 50vh-325px). See this stackoverflow question for further information: #16617748Chiton
S
4

To answer the general question:

Is there a way to make CSS calc() never be a negative value?

The answer is no, because CSS does not provide a way to manually constrain (or clamp) a quantity to some minimum or maximum value.

Whether or not a number or a length may be natively restricted to a certain range is dependent on the property that has this calc() value. From the spec:

The value resulting from an expression must be clamped to the range allowed in the target context.

These two are equivalent to 'width: 0px' since widths smaller than 0px are not allowed.

width: calc(5px - 10px);
width: 0px;

For example, while negative values for margin and z-index are valid, negative values for border-width, padding, height, width and so on are not. The specifics of these are almost always defined in the specification for the respective property.

As you happen to be using viewport units in your example, you can employ media queries in conjunction with them as demonstrated by fcalderan.

Sigrid answered 24/2, 2016 at 15:30 Comment(0)
C
2

In the latest browser versions there is max() function in CSS:

.my-margin-top {
    margin-top: max(50vh - 325px, 0);
}

Browser compatibility: Firefox 75+, Chrome/Edge: 79+, Safari: 11.1+

There is also clamp(): clamp(0, 50vh - 325px, 100vh), where 100vh is an upper bound. But this is not in Safari yet, although can be simulated with min() and max() calls.

Cluny answered 3/5, 2020 at 9:29 Comment(0)
G
0

You can also use this trick: calc((#{$gap} + 1.5rem) / -1); will result calc(-32px + -1.5rem)

Glue answered 23/3, 2020 at 15:49 Comment(0)
I
-2

You could do something like:

.my-margin-top {
    margin-top: calc((50vh - 325px) * (-1));
}

Multiplying your calc by -1 makes it a negative value.

Indemnify answered 16/3, 2021 at 19:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.