Media queries in Sass - 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
}

Related

SCSS: Can I only #include in response to a successful #media?

With SCSS files, I am attempting to make a responsive layout by setting variables in response to an #media query.
I currently have two #media queries, and I was hoping that only one of them would proceed to call the #mixin, with the map defined for the specific situation: mobile or desktop.
My code is :
$page-header-height : 45px; // some dummy defaults
$page-subheader-height: 45px;
$page-footer-height : 50px;
$mobile-varmap : (
"page-header-height" : 50px,
"page-subheader-height": 50px
);
$desktop-varmap : (
"page-header-height" : 90px,
"page-subheader-height": 120px
);
#mixin setvariables($map) {
$page-header-height: map-get($map, "page-header-height") !global;
$page-subheader-height: map-get($map, "page-subheader-height") !global;
$page-footer-height: 50px;
}
$screen-size-mobile: 360px;
$screen-size-tablet: 600px;
#media screen and (min-width:$screen-size-mobile) {
body {
#include setvariables($mobile-varmap);
}
}
#media screen and (min-width:$screen-size-tablet) {
body {
#include setvariables($desktop-varmap);
}
}
div.page-wrapper {
display: grid;
grid-template-areas: 'page-header''page-subheader''page-content''page-footer';
grid-template-columns: auto;
grid-template-rows: $page-header-height $page-subheader-height 1fr $page-footer-height;
max-height: calc(100vh - 55px); // TODO: use variables to calc these
min-height: calc(100vh - 50px);
overflow: none;
}
I had expected that this would lead to $page-header-height, etc, being set according to the matching #media query, but the result is that whichever #media query appears last in the code, determines the values which are produced.
What would I need to do in order to call setvariables() with the varmap that corresponds to the screen size?
NB: I only added the body tags to the #media queries in response to viewing some examples - I'm not sure that they are correcty used or indeed necessary.
Your code is fine, but as i understand it, you expect the variables set via #include setvariables($desktop-varmap); to dynamically respond to device width... which will not happen because the two blocks with the media query do not render anything, the variables are just changed at compile time.
A possible way to build what you want is to have only one configuration map which then could be iterated over like
#mixin setvariables($map) {
$page-header-height: map-get($map, "page-header-height") !global;
$page-subheader-height: map-get($map, "page-subheader-height") !global;
$page-footer-height: 50px !global;
}
$responsive-vars: (
mobile: (
min-width: 360px,
page-header-height: 50px,
page-subheader-height: 50px
),
desktop: (
min-width: 600px,
page-header-height: 90px,
page-subheader-height: 120px
)
);
#each $alias, $map in $responsive-vars {
#media screen and (min-width: map-get($map, 'min-width')) {
#include setvariables($map);
div.page-wrapper {
display: grid;
grid-template-areas: 'page-header''page-subheader''page-content''page-footer';
grid-template-columns: auto;
grid-template-rows: $page-header-height $page-subheader-height 1fr $page-footer-height;
max-height: calc(100vh - 55px); // TODO: use variables to calc these
min-height: calc(100vh - 50px);
overflow: none;
}
}
}
However this is not the most practical approach, since mostly you want to tweak only some values and have other declarations for all devices. Instead, i'd recommend to drop the setvariables() mixin entirely and access the maps directly like:
// https://css-tricks.com/snippets/sass/deep-getset-maps/#deep-get
#function map-deep-get($map, $keys...) {
#each $key in $keys {
$map: map-get($map, $key);
}
#return $map;
}
$responsive-vars: (
mobile: (
min-width: 360px,
page-header-height: 50px,
page-subheader-height: 50px
),
desktop: (
min-width: 600px,
page-header-height: 90px,
page-subheader-height: 120px
)
);
div.page-wrapper {
display: grid;
grid-template-areas: 'page-header''page-subheader''page-content''page-footer';
grid-template-columns: auto;
max-height: calc(100vh - 55px); // TODO: use variables to calc these
min-height: calc(100vh - 50px);
overflow: none;
#media screen and (min-width: map-deep-get($responsive-vars, 'mobile', 'min-width')) {
grid-template-rows:
map-deep-get($responsive-vars, 'mobile', 'page-header-height')
map-deep-get($responsive-vars, 'mobile', 'page-subheader-height')
1fr
map-deep-get($responsive-vars, 'mobile', 'page-footer-height');
}
#media screen and (min-width: map-deep-get($responsive-vars, 'desktop', 'min-width')) {
grid-template-rows:
map-deep-get($responsive-vars, 'desktop', 'page-header-height')
map-deep-get($responsive-vars, 'desktop', 'page-subheader-height')
1fr
map-deep-get($responsive-vars, 'desktop', 'page-footer-height');
}
}
This may look like a lot of code at first glance, but it renders far less css.

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.

Styles for multiple breakpoints in SASS

I've defined two mixins in SASS that allow me to place media queries easily. The problem I'm encountering is that I'm repeating myself frequently across many queries. That is to say, some of my style changes are the same for tablet and mobile breakpoints and others are different. Example:
.foo
float: left
width: 50%
+tablet()
float: none
display: block
width: 100%
+mobile()
float: none
display: block
width: 100%
Where my mixins are defined like this:
=tablet
#media (min-width: #{$mobile-width} + 1) and (max-width: #{$tablet-width})
#content
=mobile
#media (max-width: #{$mobile-width})
#content
I'd love to do something like this:
...
+tablet(), +mobile
float: none
display: block
width: 100%
That doesn't compile, so what is the best way to keep my SASS stylesheets DRY?
You can define mobile and tablet medias as strings and then concatenate these strings.
Scss can be easily converted to sass.
$mobile-width: 320px;
$tablet-width: 760px;
// Media queries as strings
$tablet: "(min-width: #{$mobile-width + 1}) and (max-width: #{$tablet-width})";
$mobile: "(max-width: #{$mobile-width})";
// Converts a list to a string with delimiters between elements
#function join-list($list, $separator: ", ") {
$result-string: "";
#each $item in $list {
// Index of the current item of `$list` list
$index: index($list, $item);
$result-string: $result-string + $item;
// If this is not the last item, adds separator
#if ($index != length($list)) {
$result-string: $result-string + $separator;
}
}
#return $result-string;
}
#mixin get-media($medias...) {
#media #{join-list($medias, " and ")} {
#content;
}
}
.foo {
float: left;
width: 50%;
#include get-media($mobile, $tablet) {
// or #include get-media($mobile) {
// or #include get-media($tablet) {
float: none;
display: block;
width: 100%;
}
}
Css output:
.foo {
float: left;
width: 50%;
}
#media (max-width: 320px) and (min-width: 321px) and (max-width: 760px) {
.foo {
float: none;
display: block;
width: 100%;
}
}
SassMeister demo.
As per #Stefan F's comment, the easiest thing to do in this case was to create a third mixin called (something like): +both() which encapsulated the mobile and tablet sizing. (I'm answering this myself only because he did not and it has been some time.)
Example:
=both
#media (max-width: #{$tablet-width})
#content
Usage:
.foo
float: left
width: 50%
+both()
float: none
display: block
width: 100%

sass code style with media queries

I'm doing a code review for sass code and came across using media queries inside the code. Is it a good practice? Are there better alternatives to writing this code?
.col-md-push-8 {
padding-top: 1.5em;
.btn {
&.btn-block {
border: none;
background-color: $footer-button;
margin: 1em 0 .5em;
width: 100%;
padding: 7px 10px;
border-radius: 8px;
&:hover {
background-color: $footer-button-hover;
}
#media (min-width: $screen-md-min) {
color: #025191;
&:hover .media span p.media-heading {
color: #0070ca;
}
}
}
}
}
Note: The code is for illustration purpose only and is not completely shown here.
I think that what your way to do it is perfectly fine if you're using SASS >= 3.2 (was buggy before).
Just one thing that you could do to define your media queries breakpoints more globally is to create a mixin for that purpose that you will re-use on each element you need responsive.
This way when you have to change let's say your min breakpoint, add another or change your media min-width to max-width, you don't have to do it everywhere.
Some little example assuming you have already defined $screen-md-min and $screen-md-mid :
#mixin custom-media($size) {
#if ($size == $small) {
#media (min-width: $screen-md-min) { #content; }
}
#else if ($size == $middle) {
#media (min-width: $screen-md-mid) { #content; }
}
}
And call it like so :
.btn {
&.btn-block {
...
#include custom-media($small) {
color: #025191;
&:hover .media span p.media-heading {
color: #0070ca;
}
}
}
}
There is no difference if you put Media Query inside or outside. It just depends on your preffered style.
Style 1
.some-class {
#media (min-width: 700px) {
background: red;
}
}
Style 2
#media (min-width: 700px) {
.some-class {
background: red;
}
}
Both will compile as:
#media (min-width: 700px) {
.some-class {
background: red;
}
}
Sass handles this fine, but that code is going to produce overly qualified selectors and is hardly concise.
There are a number of patterns for writing “better” CSS and Sass, such as BEM, OOCSS, OOCSS + Sass, and SMACSS.
There's also a bunch of great information on Media Queries in Sass that is probably worth a read.

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