How to solve the incompatible units problem?
#mixin square-size($size, $min: $size, $max: $size) {
$clamp-size: min(max($size, $min), $max);
width: $clamp-size;
height: $clamp-size;
}
The input is:
#include square-size(10vw, 40px, 70px);
Problem:
Incompatible units: 'vw' and 'px'.
node_modules\#ionic\app-scripts\dist\util\helpers.js:253.replace(/&/g, '&')
But if I use calc(1vw - 1px) it works. (no unit problem).
e.g. max(calc(1vw - 1px)) does not work. Because no number for max.
In my case I want a mixin to square the size of an element. Including clamp.
min-width, max-width, etc. does not work. It will be a rect or an ellipse. Because it does not keep the aspect ratio.
I want a element with dynamic size but with min and max size.
I understand that the dynamic unit vw (Viewport) must be present after sass compilation. Therefore it is not possible to convert the value to a fixed unit.
But is there no way?
I was able to fix the error in React SASS using the calc function.
font-size: calc(max(8vw, 30px));
If you're unable to work around it in any other way, SCSS has a function for ignoring things in quotes:
width: unquote("max(50px, 5rem)");
This will be compiled without the quotes and be valid CSS.
width: max(50px, 5rem);
It will be strange to have this in your scss, but it's a sure-fire way of allowing modern CSS to not interrupt your scss functions
The Problem
CSS didn't use to have its own runtime min() and max() functions, and before they existed SASS had a compile-time version. Since SASS doesn't run live it would be impossible for it to determine whether 10vw or 40px is larger - hence the error.
The Solution
Since SASS is case sensitive while CSS isn't, you can force the parser to use the CSS version of min or max by just calling MIN() or MAX() instead. If you need to resume SASS parsing inside of MAX() ( like to reference a SASS variable ) just surround the SASS code with #{...}.
Here's a fixed version of your code to demonstrate:
#mixin square-size($size, $min: $size, $max: $size) {
/* $clamp-size: min(max($size, $min), $max); */
$clamp-size: MIN(MAX(#{$size}, #{$min}), #{$max});
width: $clamp-size;
height: $clamp-size;
}
Good luck!
You would need to bypass the scss compiler & use a literal instead.
#mixin square-size($size, $min: $size, $max: $size) {
$clamp-size: #{'min(max(#{$size}, #{$min}), #{$max})'};
width: $clamp-size;
height: $clamp-size;
}
Try this
when doing min or max in sass, if you get incompatible units error, you can simply put the value in a quotation, and it will let it pass.
min(10vw, 20px) to"min(10vw, 20px)"
This works for other functions too.
And if you are using variables in calculations, you use #{} on the variables to make it pass
$a: 10px;
$b: 25%;
.mydiv {
width: calc(#{$a} - #{$b});
}
And the #{} converts them to string so that sass wouldn't make arithmetic using them while compiling
You could do it like this using min-width/height and max-width/height to avoid mixing units:
#mixin square-size($size, $min: $size, $max: $size) {
min-width: $min;
max-width: $max;
min-height: $min;
max-height: $max;
width: $size;
height: $size;
}
.class {
#include square-size(10vw, 40px, 70px);
}
For this, instead of SCSS #include
.foo {
#include square-size(10vw, 40px, 70px);
}
use better css function "clamp":
.foo {
width:clamp(10vw, 40px, 70px);
height:clamp(10vw, 40px, 70px);
}
I am trying to get the minimum between 7.6% of the viewport height and 55px.
min-height: min(7.6vh, 55px);
This gives me an error about incompatible units. Can this be done?
The Sass min() function only works when both values have the same unit (%, px, em, etc.). However, CSS itself has a min() function built in. Modern Dart Sass will automatically use the CSS function when possible.
For older versions of Sass, to use the CSS function you need to override min() with your own custom function like this:
// Override Sass min()
#function min($numbers...) {
#return m#{i}n(#{$numbers});
}
div {
// This now works
width: min(7.6vh, 55px);
}
Thanks to Jianqiu Xiao on GitHub for pointing out the "override" solution.
The SASS compiler can't know the viewport height of the target device(s), so it is impossible to compare vh to a fixed value given pixels.
What you can do is to set the height to either of the two numbers and set a min-height to the other number. However, the semantics are slightly different, as you now also have a max-height. In the following example, the div will take (at most) 100% of the viewport height, but at least 450px:
html, body {
height: 100%;
margin: 0;
padding: 0;
}
div {
background: darkgreen;
height: 450px;
min-height: 100vh;
}
<div>
</div>
I am switching from LESS to SASS but have some difficulties to use it
very simple less variable + function Less :
#mini :0.1rem;
#brown:#533a38;
.border(#color:#brown){border:#mini solid #color;}
I use it :
#contact-form{
.border();
}
how can I do the same with SASS ?
thank you
$mini :0.1rem;
$brown:#533a38;
#mixin border($color:$brown){border:$mini solid $color;}
Use mixin if you don't want to return anything. Now when we use border:
#contact-form{
border: #include border;
}
I have been using sass for a while and for ages I have been using the following px to em function for my media queries:
$browser-context: 16; // Default
#function em($pixels, $context: $browser-context) {
#return #{$pixels/$context}em
}
However, I am now wanting to set up a different base font size depending on width of screen. SO for instance for mobile sizes
$browser-context: 14; // Default
and for bigger screens:
$browser-context: 16; // Default
But Im not sure how to wrap this all up in sass. Any ideas?
Thanks,
I'm pretty sure that this won't be achievable in SASS without thinking outside the box.
SASS, as you know compiles before getting sent to the browser, therefore, at that point we have no idea what browser, let alone what screen size. Therefore, media queries are out.
What you could do (I'm theorising here) is:
Set up you em function to produce a series of font sizes specific to different browser widths e.g.
#function em780($pixels, $context: $browser-context) {
#return #{$pixels/$context}em
}
and
#function em420($pixels, $context: $browser-context) {
#return #{$pixels/$context}em
}
etc.
This should produce the correct em size for each specific screen width. Then, assign those em sizes within a normal media query
#media all and (max-width: 420px){
h1{ font-size: $em420;
}
#media all and (max-width: 780px){
h1{ font-size: $em780;
}
Does that make any sense ?
Obviously, don't copy the 'code' I've written here but hopefully the general idea is valid.
This is my mixin:
#function em($px, $base: 16px) {
#return ($px / $base) * 1em;
}
use it like font-size: em(24px);. I think it is more clear then just typing values
Is it possible to use the value of a selector as a variable?
.warning {
color:Red;
border:1px solid #{.warning.color};
}
or
.total {
padding-top:#{.font-size};
color:Red;
}
No. SASS does not build the object model in mind when parsing the code.
You'll have to keep all the necessary stuff in variables.