Использование Media Queries в Sass 3.2

от автора

С выходом Sass 3.2 начал продвигаться в массы путь объектно-ориентированного CSS (OOCSS), принося с собой принцип DRY и программистское мышление. Media queries и OOCSS стали жизненно важны для современной фронтенд разработки.


Давайте посмотрим, что нового

Sass имеет очень полезный функционал, не широко известный @content. Можно думать о @content, как о yield — позволяет нам определить sass @mixin, который имеет вложенный CSS. Это позволит сэкономить драгоценные часы и уменьшить повторение кода и значительно упростит работу с media queries.

Как это работает

Для начала надо объявить переменные, которые будут определять точки входа для устройств и добавим слой абстракции в наши media queries. Для этого создадим @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; } }​ 

Код лучше читается и мгновенно больше смысла, чем расшифровка, например, @media only screen and (max-width: 320px) and (orientation: portrait).
Вся магия заключается в @content, который позволяет нам передать в CSS свойства, которые мы хотим применить в соответствии с медийным запросом выше. Мы не можем знать, что в будущем будет требовать дизайн, но через эту абстракцию будет легко обновлять стили, когда эти изменения произойдут.
После компиляции Sass мы получим нужный 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;   } }​ 

Если необходимо применять CSS, для чего угодно меньше ipad-lanscape, например, то можно не расписывать вариации respond-to, а сделать новый @mixin, который будет адаптирован под разные устройства:

$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;   }   }​ 

С какими проблемами можно столкнуться

Все это очень прекрасно и позволяет делать интересные интерфейсы, но не будет работать в IE ниже девятой версии. Решение проблемы заключается в генерирование раздельных стилевых файлов:

<!--[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]--> 

В файле для IE объявляются переменные $old-ie: true; и необходимые фиксирование ширины и импортируется основной стилевой файл. В основном стилевом файле переменные IE $old-ie будут принимать значение false по умолчанию. Необходимо будет написать @mixin для IE и расширить функционал apply-to:

@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';         }     } } 

Также есть некоторые ограничения на использование @extend внутри media queries… Это означает, что если вы используете @extend в media queries, вы можете только расширить селекторы, которые появляются в том же блоке. Например, такой код работает отлично:

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

Такой вариант ошибочен:

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

Но мы можем поступить иначе, использовав silent classes, которые не попадают в стили, пока не сделать их @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;   } } 

Получим правильно откомпилированный CSS:

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

Кроме того, всем бы хотелось, чтобы откомпилированный CSS был меньше и CSS правила отдельного запроса были скомбинированы, например:

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

Хотелось бы получить:

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

Вместо этого получаем:

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

Работая с Rails 3.1+ и Sprockets можно использовать джем sprockets-media_query_combiner, чтобы CSS правила были оптимизировано скомбинированы.
Также есть неплохой джем, который можно использовать в проекте responder, для более удобного использования media queries.

Посетители, просматривающие ваш сайт на планшетах или телефоне обязательно поблагодарят вас.

ссылка на оригинал статьи http://habrahabr.ru/post/156645/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *