Расширение селекторов из медиа-запросов с помощью Sass
У меня есть класс элемента и компактный класс "модификатор":
.item { ... }
.item.compact { /* styles to make .item smaller */ }
Это нормально. Тем не менее, я хотел бы добавить запрос @media
, который заставляет класс .item
быть компактным, когда экран достаточно мал.
Сперва подумайте, вот что я пытался сделать:
.item { ... }
.item.compact { ... }
@media (max-width: 600px) {
.item { @extend .item.compact; }
}
Но это порождает следующую ошибку:
Вы не можете @расширить внешний селектор из @media. Вы можете только @extend селекторов в рамках одной и той же директивы.
Как я могу выполнить это, используя SASS, не прибегая к стилям копирования/вставки?
Ответы
Ответ 1
Простой ответ: вы не можете, потому что Sass не может (или не будет) составлять селектор для него. Вы не можете находиться внутри медиа-запроса и расширять то, что находится вне медиа-запроса. Конечно, было бы неплохо, если бы он просто взял копию вместо того, чтобы пытаться составить селекторов. Но это не так, как вы не можете.
Использовать mixin
Если у вас есть случай, когда вы собираетесь повторно использовать блок кода внутри и вне медиа-запросов и все еще хотите, чтобы он мог его расширить, напишите как mixin, так и класс расширения:
@mixin foo {
// do stuff
}
%foo {
@include foo;
}
// usage
.foo {
@extend %foo;
}
@media (min-width: 30em) {
.bar {
@include foo;
}
}
Расширьте селектор внутри медиа-запроса снаружи
Это не поможет вашему случаю использования, но это еще один вариант:
%foo {
@media (min-width: 20em) {
color: red;
}
}
@media (min-width: 30em) {
%bar {
background: yellow;
}
}
// usage
.foo {
@extend %foo;
}
.bar {
@extend %bar;
}
Подождите, пока Sass не снимет это ограничение (или не исправит его самостоятельно)
Существует ряд текущих обсуждений по этой проблеме (просьба не вносить свой вклад в эти потоки, если у вас нет чего-то значимого для добавления: разработчики уже знают, что пользователи желают этой функции, это просто вопрос о том, как ее реализовать и какой должен быть синтаксис).
Ответ 2
Для записи, вот как я решил решить проблему только с дублированием сгенерированных стилей:
// This is where the actual compact styles live
@mixin compact-mixin { /* ... */ }
// Include the compact mixin for items that are always compact
.item.compact { @include compact-mixin; }
// Here the tricky part, due to how SASS handles extending
.item { ... }
// The following needs to be declared AFTER .item, else it'll
// be overridden by .item NORMAL styles.
@media (max-width: 600px) {
%compact { @include compact-mixin; }
// Afterwards we can extend and
// customize different item compact styles
.item {
@extend %compact;
/* Other styles that override %compact */
}
// As shown below, we can extend the compact styles as many
// times as we want without needing to re-extend
// the compact mixin, thus avoiding generating duplicate css
.item-alt {
@extend %compact;
}
}
Ответ 3
Я считаю, что SASS/SCSS не поддерживает директиву @extend
внутри медиа-запроса. http://designshack.net/articles/css/sass-and-media-queries-what-you-can-and-cant-do/
Возможно, вам понадобится использовать mixin, хотя разбухание кода необходимо сопоставить с вашей целью.
Ответ 4
Это самое чистое, частичное решение, которое я нашел. Он использует преимущества @extend, где это возможно, и возвращается обратно к mixins, когда внутри медиа-запросов.
Cross-Media Query @extend Directives в Sass
Подробности см. в статье, но суть в том, что вы вызываете "placeholder" mixin, который затем решает, выводить ли @extend или @include.
@include placeholder('clear') {
clear: both;
overflow: hidden;
}
.a {
@include _(clear);
}
.b {
@include _(clear);
}
.c {
@include breakpoint(medium) {
@include _(clear);
}
}
В конечном счете это может быть не лучше, чем просто использование mixins, что в настоящее время является принятым ответом.
Ответ 5
Могли бы вы реструктурировать?
.compact { //compact-styles }
.item {}
.item.compact { @extend .compact }
@media (max-width: 600px) {
.item { @extend .compact; }
}
Если я правильно понимаю документацию, это должно сработать. Я думаю, что причина, по которой вы пытаетесь, не будет работать, так это то, что она не видит .item.compact при анализе @extend, но это неосведомленное предположение, поэтому возьмите это с грузом с солью!:)