SASS - compare vh and px with min function - sass

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>

Related

SASS create function to do max and min on margin

I couldn't find a solution for this problem: I need to set a margin in SASS with a max between 2 values, one is a calc() and the other is a regular px value. It would be something like this:
$calculation: calc(15vw + 10px);
.cssClass {
margin-right: max($calculation, 100px);
}
Any ideas on how to create a SCSS function or some way to make this work? Thank you in advance!
The Sass max() function doesn't work with values that have different units.
That said, you can use the CSS max() function by overriding the Sass version with your own:
// Override Sass function
#function max($numbers...) {
#return m#{a}x(#{$numbers});
}
$calculation: calc(15vw + 10px);
.cssClass {
margin-right: max($calculation, 100px);
}
...the SCSS above compiles to this CSS:
.cssClass {
margin-right: max(calc(15vw + 10px), 100px);
}
Credit to Jianqiu Xiao on GitHub for pointing out this solution. Having to create a custom function is an unfortunate Sass compiler quirk, though it has apparently been fixed in Dart Sass already.

SASS: Incompatible units: 'vw' and 'px'

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);
}

Custom postion for v-dialog Vuetify

I need to open a v-dialog of certain width and height on right bottom side of my page, but, I can't understand how to do.
V-dialog always are centered on the page, I searched on official doc, tried use CSS, but wasn't able
any ideas?
Note: Other provided solutions are not satisfying because they mess up transitions, or we can't use scoped-styles, or they suggest using !important etc.
Solution
Add arbitrary content-class class to your dialog:
<v-dialog content-class="my-custom-dialog">
Then we can use scoped styles:
<style scoped>
>>> .my-custom-dialog {
align-self: flex-end;
}
</style>
This feature is being looked at but for now you can use edit the CSS class yourself. For instance, to get it to display in the bottom right use:
.v-dialog {
position: absolute;
bottom: 0;
right: 0;
}
style="position: absolute; bottom: 0;"
On the first v-card inside the v-dialog
Add this to your styles:
.v-dialog:not(.v-dialog--fullscreen) {
bottom: 0 !important;
right: 0 !important;
position: absolute !important;
}
For anyone new coming to this post, its worth checking out VBottomSheet for this functionality.
https://vuetifyjs.com/en/components/bottom-sheets
Came to this page looking for answers but none of the above suggestions worked for me with Vuetiful 2.2.11. Ended up doing this:
.v-dialog__content {
align-items: flex-end;
justify-content: flex-end;
}
Using Vue 3 and Vuetify 3.0 alpha this solution allows to use the dialog with current mouse position. v-dialog is inside the v-overlay-container which is outside the v-app element hierarchy so the global CSS file must be used. In Vuetify 2.x v-overlay-container is inside the v-app hierarchy.
I guess a solution with scoped CSS and usage of deep() is possible in this case.
CSS variables are defined and a rule for v-overlay__content which is responsible for the position is added :
:root {
--dialog-xpos: 22px;
--dialog-ypos: 55px;
}
.v-overlay__content {
top: var(--dialog-ypos);
left: var(--dialog-xpos);
}
The click event handler modifies the variables before dialog activation :
function onClick(ev: MouseEvent) {
document.documentElement.style.setProperty('--dialog-xpos', ev.clientX.toString() + 'px');
document.documentElement.style.setProperty('--dialog-ypos', ev.clientY.toString() + 'px');
showDialog.value = true;
}

How do I make a Pinterest Widget Builder Responsive?

The Pinterest Widget Builder allows for flexibility in creating a widget to place on your site. I added one on this page, but there appears to be a limit to the width you can set for the widget. For example I set the width to 1170, but it is only displaying at 1111px.
Here is the code:
<a data-pin-do="embedUser" href="http://www.pinterest.com/rouvieremedia/" data-pin-scale-width="180" data-pin-board-width="1170">Follow Pinterest's board Pin pets on Pinterest.</a>
This is a Bootstrap site and I would really like to be able to make this widget responsive as well. I tried applying css styling to the widget just to see if I could impact it using this. Alas, no luck.
div.container > span.PIN_1407891215996_embed_grid.PIN_1407891215996_fancy {
border: 5px solid red;
}
Any suggestions for interacting with this element would be appreciated. Then I can apply some additional styling.
Wrap your widget in a container, e.g. #pinterest-container, and add the following styles:
#pinterest-container > span {
width: 100% !important;
overflow: hidden;
}
#pinterest-container > span > span > span > span {
min-width: 0;
}
The first one overrides width which is otherwise fixed, making it responsive. The second one deals with an issue where the last column is not displayed if the widget is very narrow.
The width of the widget depends on a number of factors:
The width of the enclosing element: you can't exceed that width
A multiple of the data-pin-scale-width + padding: the width of the widget won't pad right. It'll be exactly the size of the multiple of the items inside + small padding left and right, and the padding between the items
And given the above, the data-pin-scale-width obviously
So if you want an exact width of 1200, try the data-pin-scale-width="195". That should do it, assuming the enclosing element is larger.
Here's a solution I came up with: http://pastebin.com/kXVDWUu8
I suggest including the following style:
#pin-container > span {
box-shadow: none !important;
width: 100%;
overflow: hidden;
}
To make the Pinterest widget responsive, this is the solution that worked for me. Taken from here.
CSS
#pinterest-container {
display: flex;
}
#pinterest-container a {
flex: 1;
}

SASS/SCSS: Refer to property without using an intermediate variable

Is it possible to refer to a property previously defined in a selector without introducing an intermediate variable?
I'd like to say something like:
.foo {
padding: 15px;
width: 300px - $padding;
}
I know that $padding syntactically looks for a defined variable, I only use it in the above example to illustrate what I want to achieve in functionality.
The above example would be equivalent to this:
.foo {
$padding: 15px;
padding: $padding;
width: 300px - $padding * 2;
}
No, you can't, and it would be great.
I haven't tested, but as far as I know the only css pre-processor that can do that is stylus. Look at the variable section in its documentation, where it says Property Lookup. It works that way:
.foo {
padding: 15px;
width: 300px - #padding * 2;
}
But no, in Sass you can't, as far as I'm concerned.
If its an option to use an other preprocessor then scss, I really recommend using Stylus. There is a feature called Property lookup which is exactly what you want.

Resources