SASS mapped property doesn't enter in IF else statement - sass

I'm just pulling my hair right know.
I have a mixing that receives a simple object. Depending on the value of one of the properties should enter inside de IF statement or the ELSE one.
However it's always evaluating as TRUE and can't figure why.
Code is compiled using node-sass (libsass v3.5.4 ) and the gist can be seen here:
https://www.sassmeister.com/gist/40eb28fd55173d7534a7162de3c1b960
Both times calculateHeight mixin is invoked evaluates the if to TRUE and creates a CSS with twice color: red, instead of color: red and color: blue
// ----
// libsass (v3.5.4)
// ----
$headerHeight: 150px;
$headerHeightM: 115px;
$headerHeightS: 100px;
#mixin calculateHeight($obj:()){
#if #{map-get($obj, value)} {
color: red;
#media (min-width: 480px) {
#{map-get($obj, property)}: $headerHeightS;
}
#media (min-width: 768px) {
#{map-get($obj, property)}: $headerHeightM;
}
#media (min-width: 1280px) {
#{map-get($obj, property)}: $headerHeight;
}
}
#else {
color: blue;
#media (min-width: 480px) {
#{map-get($obj, property)}: #{map-get($obj, value)} 233px;
}
}
}
.header{
#include calculateHeight((property: 'height', value: false));
#include calculateHeight((property: "background", value: "url('../img/red_header_wave_1.png') no-repeat center top/100% "));
}

Not sure why, but, if I assign the value of the object property to a variable it does the trick and works. Again, not sure why but it's working now:
// ----
// libsass (v3.5.4)
// ----
$headerHeight: 150px;
$headerHeightM: 115px;
$headerHeightS: 100px;
#mixin calculateHeight($obj:()){
// Assign the mapped property to a variable prior to #if
$var: #{map-get($obj, value)};
#if $var == 'false' {
color: red;
#media (min-width: 480px) {
#{map-get($obj, property)}: $headerHeightS;
}
#media (min-width: 768px) {
#{map-get($obj, property)}: $headerHeightM;
}
#media (min-width: 1280px) {
#{map-get($obj, property)}: $headerHeight;
}
}
#else {
color: blue;
#media (min-width: 480px) {
#{map-get($obj, property)}: #{map-get($obj, value)} 233px;
}
}
}
.header{
#include calculateHeight((property: 'height', value: false));
#include calculateHeight((property: "background", value: "url('../img/red_header_wave_1.png') no-repeat center top/100% "));
}

You are interpolating the value from your map into a string, so you are actually checking the string "false", which is truthy (as you already found out). Get rid of the interpolation #{...} and it should work as expected.
- #if #{map-get($obj, value)} {
+ #if map-get($obj, value) {

Related

How to reference nested scss class within media query?

I have media query used in scss class, I would like to create media query and define all scss class in that media query. I have trouble accessing nested scss class in media query.
Here is my code
.data-one {
display: flex;
flex-wrap: wrap;
&.mobile {
width: 100%;
.data {
max-width: 100%;
}
}
.data {
height: 72px;
margin-right: 10px;
max-width: 224px;
// #media (max-width: layout-breakpoint-tablet-start) { -----------> This is the original code
// display: none;
// }
}
}
This is what I have tried but it is not working as expected
#media (max-width: layout-breakpoint-tablet-start) {
.data-one {
+.data {
display: none;
}
}
}
Sass 3.2 added the #content directive, which allows us to pass a content block into a mixin as following:
#mixin screen($size) {
$desktop: "(min-width: 1024px)";
$tablet: "(min-width: 768px) and (max-width: 1023px)";
$mobile: "(max-width: 767px)";
#if $size == desktop {
#media only screen and #{$desktop} {
#content;
}
}
#else if $size == tablet {
#media only screen and #{$tablet} {
#content;
}
}
#else if $size == mobile {
#media only screen and #{$mobile} {
#content;
}
}
#else {
#media only screen and #{$size} {
#content;
}
}
}
.wrapper {
margin: 0 auto;
width: 100%;
#include screen('tablet') {
width: 90%;
}
#include screen('desktop') {
width: 85%;
}
}
If you have any question about it feel free to ask.

How to insert a selector inside a Mixin?

I'm trying to use in this case a placeholder inside a mixin, however I get the following error:
"message": "You may not #extend an outer selector from within #media.\nYou may only #extend selectors within the same directive.\nFrom \"#extend %shadow-sm\" on line 7 of build/scss/components/cards/_form-register.scss\n",
"formatted": "Error: You may not #extend an outer selector from within #media.\n You may only #extend selectors within the same directive.\n From \"#extend %shadow-sm\" on line 7 of build/scss/components/cards/_form-register.scss\n on line 2 of build/scss/abstracts/placeholders/_shadows.scss\n>> %shadow-sm { box-shadow: 0 .125rem .25rem rgba(0, 0, 0, .075) !important; \n ^\n"
}
Where my Mixin is:
// BOOTSTRAP GRID
#mixin media-breakpoint-xs {
#media (min-width: 320px) {
#content;
}
}
#mixin media-breakpoint-sm {
#media (min-width: 576px) {
#content;
}
}
#mixin media-breakpoint-md {
#media (min-width: 768px) {
#content;
}
}
#mixin media-breakpoint-lg {
#media (min-width: 992px) {
#content;
}
}
#mixin media-breakpoint-xl {
#media (min-width: 1200px) {
#content;
}
}
Where my Placeholder is:
%shadow-none { box-shadow: none !important; }
%shadow-sm { box-shadow: 0 .125rem .25rem rgba(0, 0, 0, .075) !important; }
MY CODE:
#include media-breakpoint-lg {
#extend %shadow-sm;
width: 25rem;
}
Is it possible to do insert a placeholder and or maybe even a mixin inside another mixin?
If not, what would be the best way to use good practices?
Before I had a color %placeholder, now I changed and created a #mixin for the same generation .. Which looked like this:
$default-color-property-type-list: border-color, background-color, color;
$default-color-name-map: (
'cream-1': #FAFAFA,
'cream-2': #EFEFEF,
'correct': #02C22B,
'dark-blue-1': #3897F0,
'dark-grey-2': #999999,
'incorrect': #EE2D3E,
'transparent': transparent,
'white': white,
);
#mixin getColor($color-name, $color-property-type) {
#if not map-has-key($default-color-name-map, $color-name) {
#error 'The color #{$color-name} does not exist!';
} #else if not index($default-color-property-type-list, $color-property-type) {
#error 'The color type #{color-type} does not exist!';
} #else {
$color-value: map-get($default-color-name-map, $color-name);
#{$color-property-type}: #{$color-value} !important;
}
}
Soon to insert the way I was wanting (inside another #mixin), I just need to give an #include in my #mixin of colors this way:
#include media-breakpoint-NAME {
#include getColor($color-name, $color-property-type);
}

SASS: Get value of variables after returning a string from list

Is there a way I can get the value of nth($list , 1)
$xs: 600px;
$sm: 960px;
$md: 1280px;
$lg: 1920px;
$list: xs, sm, md, lg;
#mixin respond($media) {
#for $i from 1 through length($list) {
#if $media==nth($list, 1) {
#media only screen and (max-width: nth($list, 1) - 1px) {
#content;
}
}
}
}
I'm getting this now
#media only screen and (max-width: xs-1px) {}
I want the value of the variable $xs = 600px;
#media only screen and (max-width: 600px - 1px) {}
I tried:
$nth($scree-size , 1)
$#{nth($scree-size , 1)}
The short answer is: no, as what you are looking for are dynamic variable names and they are not well supported. However, I suggest to use a map instead to have a somewhat cleaner code without the need to repeat the variable names and to simplify your mixin in general:
$breakpoints: (
xs: 600px,
sm: 960px,
md: 1280px,
lg: 1920px
);
#mixin respond($media) {
#if map-has-key($breakpoints, $media) {
#media only screen and (max-width: map-get($breakpoints, $media) - 1px) {
#content;
}
}
}
#include respond("md") {
.class {
color: red;
}
}
outputs:
#media only screen and (max-width: 1279px) {
.class {
color: red;
}
}

Media queries in Sass

I am wondering if there is a way to write media queries in sass, so I can give a certain style between let's say: 300px to 900px
in css it looks like this
#media only screen and (min-width: 300px) and (max-width: 900px){
}
I know I can write
#media (max-width: 900px)
in sass but how to make that range?
$small: 300px;
$medium: 900px;
.smth {
//some CSS
#media screen and (max-width: $small) {
//do Smth
}
#media screen and (min-width: $medium) {
//do Smth
}
}
Something like this?
This is what I use for a Mixin with sass, it allows me to quickly reference the breakpoint that I want. obviously you can adjust the media query list to suite your project mobile fist etc.
But it will jin multiple queries for you as I believe you're asking for.
$size__site_content_width: 1024px;
/* Media Queries */ Not necessarily correct, edit these at will
$media_queries : (
'mobile' : "only screen and (max-width: 667px)",
'tablet' : "only screen and (min-width: 668px) and (max-width: $size__site_content_width)",
'desktop' : "only screen and (min-width: ($size__site_content_width + 1))",
'retina2' : "only screen and (-webkit-min-device-pixel-ratio: 2) and (min-resolution: 192dpi)",
'retina3' : "only screen and (-webkit-min-device-pixel-ratio: 3) and (min-resolution: 288dpi)",
'landscape' : "screen and (orientation:landscape) ",
'portrait' : "screen and (orientation:portrait) "
);
#mixin for_breakpoint($breakpoints) {
$conditions : ();
#each $breakpoint in $breakpoints {
// If the key exists in the map
$conditions: append(
$conditions,
#{inspect(map-get($media_queries, $breakpoint))},
comma
);
}
#media #{$conditions} {
#content;
}
}
Use it like this in your scss:
#masthead {
background: white;
border-bottom:1px solid #eee;
height: 90px;
padding: 0 20px;
#include for_breakpoint(mobile desktop) {
height:70px;
position:fixed;
width:100%;
top:0;
}
}
Then this will compile to:
#masthead {
background: white;
border-bottom: 1px solid #eee;
height: 90px;
padding: 0 20px;
}
#media only screen and (max-width: 667px), only screen and (min-width: 1025px) {
#masthead {
height: 70px;
position: fixed;
width: 100%;
top: 0;
}
}
Check this out for scss.
https://github.com/Necromancerx/media-queries-scss-mixins
Usage
.container {
#include xs {
background: blue;
}
#include gt-md {
color: green
}
}
Demo: Stackblitz
Based on Angular FlexLayout MediaQueries
$small: 300px;
$medium: 900px;
#media screen and (min-width: $small) and (max-width: $medium) {
//css code
}

Sass: Storing #content into list for use later in another mixin?

I am trying to store the #content directive from one mixin into a list so that I can use it later in another mixin. I am getting errors when I try this. Anyone know if this is possible?
Example is a simplified version of what I am doing, but basically I want to create custom breakpoint classes but without having all of the extra markup from the media query on every class.
Heres what I've got:
$breakpoints: ((sm, 320px), (md, 780px), (lg, 960px));
$all: ();
#mixin push($name) {
$content: (#content);
$all: append($all, ($name, $content));
}
#mixin printAll() {
#each $breakpoint in $breakpoints {
$breakpointName: nth($breakpoint, 1);
$breakpointSize: nth($breakpoint, 2);
#media only screen and (min-width: $breakpointSize) {
#each $item in $all {
$className: nth($item, 1);
$content: nth($item, 2);
#{$className}-#{$breakpointName} {
#{$content};
}
}
}
}
}
#include push(color-red){ color: red; }
#include push(color-green){ color: green; }
#include push(color-blue){ color: blue; }
#include push(totally-crazy){
color: red;
background-color: green;
border-top: solid 5px brown;
border-left: solid 5px gray;
border-right: solid 5px blue;
border-bottom: solid 5px yellow;
}
#include printAll();
So basically I want to output something like:
#media only screen and (min-width: 320px) {
//all custom classes with -sm suffix here
}
#media only screen and (min-width: 728px) {
//all custom classes with -md suffix here
}
#media only screen and (min-width: 960px) {
//all custom classes with -lg suffix here
}
INSTEAD of:
#media only screen and (min-width: 320px) {
//first pushed class with -sm suffix here
}
#media only screen and (min-width: 728px) {
//first pushed class with -md suffix here
}
#media only screen and (min-width: 960px) {
//first pushed class with -lg suffix here
}
#media only screen and (min-width: 320px) {
//second pushed class with -sm suffix here
}
#media only screen and (min-width: 728px) {
//second pushed class with -md suffix here
}
#media only screen and (min-width: 960px) {
//second pushed class with -lg suffix here
}
etc..
Example here:
http://sassmeister.com/gist/10332360

Resources