⬆️ ⬇️

Using Media Queries in Sass 3.2

With the release of Sass 3.2, the object-oriented CSS (OOCSS) path began to move into the masses, bringing with it the DRY principle and programmer thinking. Media queries and OOCSS have become vital for modern front-end development.







Let's see what's new



Sass has very useful functionality, not widely known content . You can think of content as yield - allows us to define sass @mixin, which has nested CSS. This will save precious hours and reduce code repetition and greatly simplify working with media queries.



How it works



First we need to declare the variables that will define the entry points for the devices and add an abstraction layer to our media queries. To do this, create @mixin respond-to:

')

$small: 320px; $large: 1024px; @mixin respond-to($media) { @if $media == handhelds { @media only screen and (max-width: $small) { @content; } } @else if $media == medium-screens { @media only screen and (min-width: $small + 1) and (max-width: $large - 1) { @content; } } @else if $media == wide-screens { @media only screen and (min-width: $large) { @content; } } } .block { float: left; width: 250px; @include respond-to(handhelds) { width: 100% ;} @include respond-to(medium-screens) { width: 125px; } @include respond-to(wide-screens) { float: none; } }​ 


The code is better readable and instantly makes more sense than decoding, for example, media only screen and (max-width: 320px) and (orientation: portrait).

All the magic lies in content , which allows us to pass to CSS the properties that we want to apply in accordance with the media query above. We cannot know what the design will demand in the future, but through this abstraction it will be easy to update styles when these changes occur.

After compiling Sass we get the required CSS:



 .block { float: left; width: 250px; } @media only screen and (max-width: 320px) { .block { width: 100%; } } @media only screen and (min-width: 321px) and (max-width: 1023px) { .block { width: 125px; } } @media only screen and (min-width: 1024px) { .block { float: none; } }​ 


If you need to use CSS, for anything less than ipad-lanscape, for example, then you can not paint variations of respond-to, but make a new @mixin, which will be adapted for different devices:



 $ipad-landscape: 980px; @mixin apply-to($ltgt, $device) { $extrema: null; @if $ltgt == less-than { $extrema: max; } @if $ltgt == greater-than { $extrema: min } @if $device == $ipad-landscape { @media only screen and (#{$extrema}-width: $ipad-landscape) { @content; } } } .block { @include apply-to(less-than, ipad-landscape) { background: black; } }​ 


What problems can be encountered



All this is very fine and allows you to make interesting interfaces, but will not work in IE below the ninth version. The solution to the problem is to generate separate style files:



 <!--[if lte IE 8]> <link rel="stylesheet" href="css/all-old-ie.css"> <![endif]--> <!--[if gt IE 8]><!--> <link rel="stylesheet" href="css/all.css"> <!--<![endif]--> 


The file for IE declares variables $old-ie: true; and the necessary width fixing and the main style file is imported. In the main style file, IE variables $ old-ie will default to false. You will need to write @mixin for IE and extend the apply-to functionality:



 @mixin old-ie { @if $old-ie { @content; } } @mixin apply-to($ltgt, $device) { $extrema: null; @if $ltgt == less-than { $extrema: max; } @if $ltgt == greater-than { $extrema: min } @if $fix-mqs-ipad-landscape { @content; } @else { @media screen and (#{$extrema}-width: $device) { @content; } } } .block { @include apply-to(less-than, $ipad-landscape) { float: left; width: 70%; @include old-ie { content: ' ,     IE'; } } } 


There are also some restrictions on using @extend inside media queries ... This means that if you use @extend in media queries, you can only expand the selectors that appear in the same block. For example, this code works fine:



 @media only screen and (max-width: 320px) and (orientation: portrait){ .error { border: 1px #f00; background-color: #fdd; } .seriousError { @extend .error; border-width: 3px; } } 


This option is wrong:



 .error { border: 1px #f00; background-color: #fdd; } @media only screen and (max-width: 320px) and (orientation: portrait) { .seriousError { @extend .error; border-width: 3px; } } 


But we can do otherwise by using silent classes that do not fall into styles until we make them @extend.



 //silent class %big { width: 20px; height: 20px; } .block_1 { @extend %big; } .block_2 { @include respond-to('large'){ @extend %big; } } .block_3 { @include respond-to('large'){ @extend %big; } } 


Get the correctly compiled CSS:



 .block_1 { height: 20px; width: 20px; } @media screen and (min-width: 600px) { .block_2, .block_3 { height: 20px; width: 20px; } } 


In addition, everyone would like the compiled CSS to be smaller and the CSS rules for a separate query to be combined, for example:



 .profile-pic { @media screen and (max-width: 320px) { width: 100px; float: none; } } .biography { @media screen and (max-width: 320px) { font-size: 15px; } } 


I would like to receive:



 @media screen and (max-width: 320px) { .profile-pic { width: 100px; float: none; } .biography { font-size: 15px; } } 


Instead we get:



 @media screen and (max-width: 320px) { .profile-pic { width: 100px; float: none; } } @media screen and (max-width: 320px) { .biography { font-size: 15px; } } 


Working with Rails 3.1+ and Sprockets, you can use the sprockets-media_query_combiner jam so that the CSS rules are optimized combined.

There is also a good jam that can be used in the responder project, for more convenient use of media queries.



Visitors who browse your site on tablets or phones will definitely thank you.

Source: https://habr.com/ru/post/156645/



All Articles