SASS dynamic responsive classes mixin? - sass

I'm trying to make a mixin to produce results similar to the following:
#media (max-width: 767px)
{
.m-text-left
{
text-align: left;
}
.m-text-right
{
text-align: right;
}
.m-text-center
{
text-align: center;
}
.m-float-right
{
float: right;
}
.m-float-left
{
float: left;
}
.m-float-none
{
float: none;
}
.m-text-justify
{
text-align: justify;
}
.m-hide
{
visibility: hidden;
overflow: hidden;
max-height: 0;
}
.m-remove
{
display: none;
}
}
/* Portrait tablet to landscape */
#media (min-width: 768px) and (max-width: 1029px)
{
.t-text-left
{
text-align: left;
}
.t-text-right
{
text-align: right;
}
.t-text-center
{
text-align: center;
}
.t-float-right
{
float: right;
}
.t-float-left
{
float: left;
}
.t-float-none
{
float: none;
}
.t-text-justify
{
text-align: justify;
}
.t-hide
{
visibility: hidden;
overflow: hidden;
max-height: 0;
}
.t-remove
{
display: none;
}
}
/* Landscape to small desktop */
#media (min-width: 1030px)
{
.d-text-left
{
text-align: left;
}
.d-text-right
{
text-align: right;
}
.d-text-center
{
text-align: center;
}
.d-float-right
{
float: right;
}
.d-float-left
{
float: left;
}
.d-float-none
{
float: none;
}
.d-text-justify
{
text-align: justify;
}
.d-hide
{
visibility: hidden;
overflow: hidden;
max-height: 0;
}
.d-remove
{
display: none;
}
}
This is the mixin I wrote:
#mixin respond($responsive-classes) {
#each $screen, $query in (
m: max-width $small-screen, // Phones
p: min-width $small-screen+1 max-width $medium-screen, // Phones to Phablets
t: min-width $medium-screen+1 max-width $large-screen, // Phablets to Tablets
l: min-width $large-screen+1 max-width $wide-screen, // Tablets to Desktops
d: min-width $wide-screen+1) { // Desktops
#include media($query, $grid-columns) {
#each $selector, $properties in $responsive-classes {
#if (length($properties) == 1 AND length(nth($properties, 2)) > 1) {
#each $value in nth($properties, 2) {
.#{$screen}-#{$selector}-#{$value} {
#{nth($properties, 1)}: #{$value};
}
}
} #else {
#each $property, $value in $properties {
.#{$screen}-#{$selector} {
#{$property}: #{$value};
}
}
}
}
}
}
}
This is how I used it:
#include respond((
(text, (text-align, (left, right, center, justify))),
(float, (float, (left, right, none))),
(hide, (visibility, hidden), (overflow, hidden), (max-height, 0)),
(remove, (display, none))
));
This is the result I'm getting:
#media screen and (max-width: 480px) {
.m-float,
.m-text {
left: right
}
}
#media screen and (min-width: 481px) and (max-width: 620px) {
.p-float,
.p-text {
left: right
}
}
#media screen and (min-width: 621px) and (max-width: 955px) {
.t-float,
.t-text {
left: right
}
}
#media screen and (min-width: 956px) and (max-width: 1200px) {
.l-float,
.l-text {
left: right
}
}
#media screen and (min-width: 1201px) {
.d-float,
.d-text {
left: right
}
}
.hide {
visibility: hidden;
overflow: hidden;
max-height: 0
}
Ignore the media queries; I know they're different. It's the overall final result that I want.

I was putting in lists instead of maps.
The Mixin:
#mixin respond($modifier-class) {
#each $screen, $query in (
m: max-width $small-screen, // Phones
p: min-width $small-screen + 1 max-width $medium-screen -1, // Phones to Phablets
t: min-width $medium-screen max-width $large-screen, // Phablets to Tablets
l: min-width $large-screen + 1 max-width $wide-screen - 1, // Tablets to Desktops
d: min-width $wide-screen) { // Desktops
#include media($query) { // Mixin from Bourbon's Neat
#each $selector, $rules in $modifier-class {
#each $property, $values in $rules {
#if (type-of($values) == "list") {
#each $value in $values {
.#{$screen}-#{$selector}-#{$value} {
#{$property}: $value;
}
}
} #else {
.#{$screen}-#{$selector} {
#{$property}: $values;
}
}
}
}
}
}
}
The call:
$modifier-classes: (
text: ( text-align: (left, right, center, justify) ),
float: ( float: (left, right, none) ),
hide: ( visibility: hidden,
overflow: hidden,
max-height: 0, ),
remove: ( display: none )
);
#include respond($modifier-classes);

Related

scss how to reuse inner selector?

I have code like this:
.outer1 {
&.same-inner {
background-color: white;
}
}
.outer2 {
&.same-inner {
background-color: white;
}
}
.outer3 {
&.same-inner {
background-color: white;
}
}
How do I reuse .same-inner selector?
.outer1, .outer2, .outer3 {
&.same-inner {
background-color: white;
}
}
Translates to CSS:
.outer1.same-inner, .outer2.same-inner, .outer3.same-inner {
background-color: white;
}
Or if you wanted to give each of the outer's there own properties, but also inherit same-inner
.same-inner {
background-color: white;
}
.outer1 {
width:10px;
#extend .same-inner
}
.outer2 {
width:20px;
#extend .same-inner
}
.outer3 {
width:30px;
#extend .same-inner
}
Translates to CSS:
.same-inner, .outer1, .outer2, .outer3 {
background-color: white;
}
.outer1 {
width: 10px;
}
.outer2 {
width: 20px;
}
.outer3 {
width: 30px;
}
Or maybe what you want is:
.same-inner {
background-color: white;
&.outer1 {
width:10px;
#extend .same-inner
}
&.outer2 {
width:20px;
#extend .same-inner
}
&.outer3 {
width:30px;
#extend .same-inner
}
}
Which churns out CSS:
.same-inner, .same-inner.outer1, .same-inner.outer2, .same-inner.outer3 {
background-color: white;
}
.outer1.same-inner {
width: 10px;
}
.outer2.same-inner {
width: 20px;
}
.outer3.same-inner {
width: 30px;
}
You can reuse a selector by #extend.
follow this sass documentation about #extend.

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.

Create hidden classes

I try to take a mixin from bootstrap 4. Unfortunately, there is a mistake that I can not explain.
Here is my SASS code:
$mdc-layout-grid-breakpoints: (
desktop: 840px,
tablet: 480px,
phone: 0px
);
#mixin media-breakpoint-up($name, $breakpoints: $mdc-layout-grid-breakpoints) {
$min: breakpoint-min($name, $breakpoints);
#if $min {
#media (min-width: $min) {
#content;
}
} #else {
#content;
}
}
#each $breakpoint in map-keys($mdc-layout-grid-breakpoints) {
#include media-breakpoint-up($breakpoint) {
$infix: breakpoint-infix($breakpoint, $mdc-layout-grid-breakpoints);
.d#{$infix}-none { display: none !important; }
.d#{$infix}-inline { display: inline !important; }
.d#{$infix}-inline-block { display: inline-block !important; }
.d#{$infix}-block { display: block !important; }
.d#{$infix}-table { display: table !important; }
.d#{$infix}-table-row { display: table-row !important; }
.d#{$infix}-table-cell { display: table-cell !important; }
.d#{$infix}-flex { display: flex !important; }
.d#{$infix}-inline-flex { display: inline-flex !important; }
}
}
The error in the console:
I do not understand the information with the "&".
Error in plugin 'sass'
Message:
src\scss\mixins\_display.scss
Error: Base-level rules cannot contain the parent-selector-referencing character '&'.
Backtrace:
src/scss/mixins/_display.scss:40, in mixin `#content`
src/scss/mixins/_display.scss:29, in mixin `media-breakpoint-up`
src/scss/mixins/_display.scss:37
on line 40 of src/scss/mixins/_display.scss
>> .d#{$infix}-none { display: none !important; }
--------^
I hope for help :-)
It seems that it's hard to determine where the style code starts, and where the selector code ends.
Therefore, such a hack:
.d#{$infix + '-none'} { display: none !important; }

SCSS: How to use variables to write style classes ?

I was wondering whether there is a certain way to use variables that affect the style in SCSS.
I'm looking for something like:
var x = 1
.class1 {
if (x==1) {
background-color: red;
} else {
background-color: blue;
}
}
.class2 {
if (x==1) {
background-color: blue;
} else {
background-color: red;
}
}
You can use #if and #else
$x:1;
.class1 {
#if $x == 1 {
background-color: red;
} #else {
background-color: blue;
}
}
.class2 {
#if $x == 1 {
background-color: blue;
} #else {
background-color: red;
}
}

SASS if function to check property value

With SASS' if() function, is it possible to check for a property value? E.g. I want a button to have a margin-right: 10px by default. But, if the button is float: right, I want the margin to be margin-left: 10px.
Something like below:
margin: if(float=="right" $margin-right $margin-left);
Obviously, the above doesn't work (otherwise I wouldn't be writing here). But, is this possible?
This mixin can set float and margin properties for any element.
#mixin set-button($float: null) {
#if ($float == right) or ($float == left) {
float: $float;
}
#if ($float == right) {
margin-left: 10px;
} #else {
margin-right: 10px; // default value
}
}
.but-1 {
#include set-button(right);
}
.but-2 {
#include set-button();
}
.but-3 {
#include set-button(left);
}
.but-4 {
#include set-button(lol);
}
Css output:
.but-1 {
float: right;
margin-left: 10px;
}
.but-2 {
margin-right: 10px;
}
.but-3 {
float: left;
margin-right: 10px;
}
.but-4 {
margin-right: 10px;
}
Sassmeister demo.
It's been a while since I did any css stuff so this might be LESS but you could try
.buttonClass {
#if $float == "right" {
$margin-left;
} #else {
$margin-right;
}
}

Resources