Давайте посмотрим, что нового
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/
Добавить комментарий