Расширение селекторов из медиа-запросов с помощью Sass


86

У меня есть класс элемента и компактный класс «модификатор»:

.item { ... }
.item.compact { /* styles to make .item smaller */ }

Это отлично. Однако я хотел бы добавить @mediaзапрос, который заставляет .itemкласс быть компактным, когда экран достаточно мал.

На первый взгляд это то, что я пытался сделать:

.item { ... }
.item.compact { ... }
@media (max-width: 600px) {
  .item { @extend .item.compact; }
}

Но это вызывает следующую ошибку:

Вы не можете @расширять внешний селектор из @media. Вы можете использовать только селекторы @extend в одной директиве.

Как мне добиться этого с помощью SASS, не прибегая к копированию / вставке стилей?


Fyi, вот проблема, которая заставит приведенный вами пример работать правильно: github.com/sass/sass/issues/1050
Ajedi32

Ответы:


112

Простой ответ: вы не можете, потому что Sass не может (или не хочет) составлять для него селектор. Вы не можете находиться внутри медиа-запроса и расширять то, что находится за пределами медиа-запроса. Конечно, было бы неплохо, если бы он просто взял его копию вместо того, чтобы пытаться скомпоновать селекторы. Но это не так, поэтому вы не можете.

Используйте миксин

Если у вас есть случай, когда вы собираетесь повторно использовать блок кода внутри и вне медиа-запросов и по-прежнему хотите, чтобы он мог его расширять, тогда напишите и миксин, и класс расширения:

@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 снимет это ограничение (или исправьте его самостоятельно)

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


@mindeavour Это сработало для вас? Вы смогли использовать расширенный класс в медиа-запросе? В Sass 3.2?
Yahreen

1
%fooненужно, .fooможет напрямую @include foo.
phil294

В моем случае я просто использовал заполнитель% с расширенными внешними медиа-запросами. Затем в медиа-запросе для моего селектора просто добавлен заполнитель extension%. Посмотрим, придет ли обсуждение чего-нибудь полезного. Спасибо, Цимманон.
Keypaul

11

Для записи, вот как я решил проблему, только один раз скопировав сгенерированные стили:

// 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's 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's 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;
  }
}

2

Я считаю, что SASS / SCSS не поддерживает @extendдирективу внутри медиа-запроса. http://designshack.net/articles/css/sass-and-media-queries-what-you-can-and-cant-do/

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


Ссылка на решение приветствуется, но убедитесь, что ваш ответ полезен и без нее: добавьте контекст вокруг ссылки, чтобы ваши друзья-пользователи имели некоторое представление, что это такое и почему оно есть, а затем процитируйте наиболее релевантную часть страницы, которую вы повторная ссылка на, если целевая страница недоступна. Ответы, которые представляют собой не более чем ссылку, могут быть удалены.
dippas

1

Это самое чистое и частичное решение, которое я нашел. Он использует преимущества @extend там, где это возможно, и возвращается к миксинам внутри медиа-запросов.

Директивы @extend кросс-медиа запросов в Sass

См. Статью для получения полной информации, но суть в том, что вы вызываете миксин «заполнитель», который затем решает, выводить ли @extend или @include.

@include placeholder('clear') {
   clear: both;
   overflow: hidden;
}

.a {
    @include _(clear);
}
.b {
    @include _(clear);
}
.c {
    @include breakpoint(medium) {
      @include _(clear);
   }
}

В конечном итоге это может быть не лучше, чем просто использовать миксины, что в настоящее время является принятым ответом.


0

Я использую точки останова, но идея та же:

@mixin bp-small {
    @media only screen and (max-width: 30em) {
        @content;
    }

Как это использовать:

.sidebar {
    width: 60%;
    float: left;
    @include bp-small {
        width: 100%;
        float: none;
    }
}

Есть текст о миксинах, где вы можете узнать больше об этой опции.


-2

Не могли бы вы реструктурировать?

.compact { //compact-styles }
.item {}
.item.compact { @extend .compact } 

@media (max-width: 600px) {
    .item { @extend .compact; }
}

Если я правильно понимаю документацию, это должно сработать. Я думаю, причина, по которой вы пытаетесь не работать, заключается в том, что он не видит .item.compact при анализе @extend, но это неосведомленное предположение, так что возьмите это с кучей соли! :)


Как вы составляете свой SASS? Внешне, с JS или каким-то серверным компонентом?
Джейсон М. Бэтчелор

Он компилируется с помощью стандартного rails-sassгема с использованием SASS v3.2.4
soundly_typed

1
Похоже, что возможность расширения внутри запросов @media устарела и будет исключена в 3.3: chriseppstein.github.com/blog/2012/08/23/sass-3-2-is-released (прочтите область, в которой говорится «Ограничения @extendв директивах CSS»)
Джейсон М. Бэтчелор,

Если я правильно понял эту информацию, возможно, это и является причиной проблемы. Мне было бы интересно узнать, что вы узнаете!
Джейсон М. Бэтчелор
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.