The problem is: I can't get where is the mistake here:
#function calcSize($value) {
$containerWidth: calc(100vw - 405px);
$initialContainer: 1278;
$result: $value * $containerWidth / $initialContainer;
#return $result;
}
I'm trying to use it:
.module-title {
font-weight: 700;
font-size: calcSize(45);
}
But I get mistake: "Undefined operation "45 * calc(100vw - 405px)""
The calc() function needs to be sent to the client, so that the 100vw element can be re-calculated every time the browser is resized.
However, you've used it in a server-side formula ($value * $containerWidth / $initialContainer) which needs to be processed before sending it to the browser.
What you probably need to do is have Sass render a calc() formula with all the parts in, which will then be sent to the client to calculate:
#function calcSize($value) {
$initialContainer: 1278;
$result: calc($value * (100vw - 405px) / $initialContainer);
#return $result;
}
(Theoretically, SCSS could work out that that's what you meant, but it might be quite complex to implement.)
Related
Let's say for instance we have the next sass partial file:
//_colors.scss
$foo: red;
And we "use" it on another file:
//test.scss
#use './colors'
.test{
color: colors.$foo;
}
All good, but what if I would like to use/get the value in a dynamic way within a mixin? something like:
//test.scss
#use './colors'
#mixin getColor($type){
color: colors[$type]; //JavaScript example, * don't actually work *.
or
color: #{colors.{$type}; * don't work neither *
//The above returns `color: colors.foo` instead of `color: red` on compilation.
or
color: colors.#{$type}; * doesn't work neither *
}
.test{
#include getColor(foo);
}
Is it possible? thanks for the help!
For a color, I really much prefer a function so it can be used on any property (color, background-color, border, box-shadow...)
I usually declare a string equivalent to variable names, then define them inside a map. Finally this map is accessible via a dedicated function.
Something like
//_colors.scss
#use 'sass:map';
$favoriteRed: "favoriteRed";
$favoriteYellow: "favoriteYellow";
$favoriteBlue: "favoriteBlue";
$MyColors: (
$favoriteRed: #c00,
favoriteYellow: #fc0,
$favoriteBlue: #0cf
);
#function my-color($tone: $favoriteRed) {
#if not map.has-key($MyColors, $tone) {
#error "unknown `#{$tone}` in MyColors.";
}
#else {
#return map.get($MyColors, $tone);
}
}
This _colors.scss generates no code at all, it can be imported anywhere at no cost.
Then, in a specific style file:
//test.scss
#use './colors' as *;
//inside a mixin
#mixin special-hue-component($tone){
div.foo {
span.bar {
border-color: my-color($tone);
}
}
}
//or directly
.foobartest {
color: my-color($favoriteBlue);
}
so I've been trying to figure this out but maybe I'm just beating my head against the wall. I'm trying to make a sass mixin that uses null arguments so that the argument will not be included unless a value is specifically assigned to the output like so:
// main mixin
#mixin fontSettings(
$font-size: null,
$line-height: null,
)
{
// if null, get the default value
#if not $font-size {
$font-size: -get-font-defaults(font-size);
}
// if null get, default value
#if not $line-height {
$line-height: -get-font-defaults(line-height);
}
// calculate font stuff
$font-size: $font-size * 1rem;
$line-height: $line-height * 1rem;
//output
font-size: $font-size;
line-height: $line-height;
}
// map merge mixin
#mixin -set-font-defaults() {
$-font-defaults: map-merge($-font-defaults, keywords($defaults)) !global;
}
// function to get map values
#function -get-font-defaults($key){
#return map-get($-font-defaults, $key);
}
// default settings config map
$-font-defaults: (
'font-size': 1.2,
'line-height': 2,
);
and usage would be
p {
//output sets fontsize to 12px and line height to 20px
#include fontSettings;
}
my question is - is there any way to shorten this without having to do an #if validation for each argument? like using a #each loop to loop through the arguments? I keep getting invalid null operations unless I do a validation for each argument separately. if there's no way to shorten this with a loop, then I'll accept that since I'm a noob but if there is a way to shorten this I would appreciate some advise on how to do so. I plan on adding more arguments to the mixing, this is just a test with the two. thanks in advance for any help.
There is an easier way, you need to leverage the optional parameters of the mixin in your favor. By using optional parameters, not defining them allows the default values set in the declaration to kick in like the example below.
#mixin fontSettings($font-size: 1.2, $line-height: 2) {
font-size: $font-size * 1rem;
line-height: $line-height * 1rem;
}
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.
What I want to achieve is something like this:
.indent-me-($num) {
text-indent: ($num * 2.5em);
}
So if I add the class indent-me-10 to some element, it would receive the style text-indent: 25em. I want to do this because 1) I need a fair amount of flexibility (there probably won't be more than 4 or so levels of "indent", but I like to have all my bases covered — these classes will be generated by javascript logic, I'm not hard-coding them into the HTML), and 2), I would hate to have to write something like the following in a language as smart as SASS. I'm not super familiar with all of its intricacies, so I feel like I must be missing something.
.indent-me-1 { text-indent: 2.5em; }
.indent-me-2 { text-indent: 2 * 2.5em; }
.indent-me-3 { text-indent: 3 * 2.5em; }
.indent-me-4 { text-indent: 4 * 2.5em; }
...
You can achieve this by using a combination of SCSS interpolation and a loop.
sass interpolation using #{$variable}
$num: 1;
.indent-me-#{$num} {
text-indent: ($num * 2.5em);
}
and a #for loop to do this as well
#for $num from 1 through 10 {
.indent-me-#{$num} {
text-indent: ($num * 2.5em);
}
}
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