Подтвердить что ты не робот

Расширение селекторов из медиа-запросов с помощью 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, не прибегая к стилям копирования/вставки?

4b9b3361

Ответ 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;
  }
}

Ответ 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, но это неосведомленное предположение, поэтому возьмите это с грузом с солью!:)