Erweitern von Selektoren aus Medienabfragen mit Sass

84

Ich habe eine Artikelklasse und eine kompakte "Modifikator" -Klasse:

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

Das ist in Ordnung. Ich möchte jedoch eine @mediaAbfrage hinzufügen , die die .itemKlasse dazu zwingt , kompakt zu sein, wenn der Bildschirm klein genug ist.

Auf den ersten Blick habe ich Folgendes versucht:

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

Dies erzeugt jedoch den folgenden Fehler:

Sie dürfen einen äußeren Selektor nicht innerhalb von @media erweitern. Sie dürfen nur Selektoren innerhalb derselben Direktive erweitern.

Wie würde ich dies mit SASS erreichen, ohne auf Kopier- / Einfügestile zurückgreifen zu müssen?

soundly_typed
quelle
Zu Ihrer Information, hier ist ein Problem, das dazu führen würde, dass das von Ihnen angegebene Beispiel korrekt funktioniert: github.com/sass/sass/issues/1050
Ajedi32

Antworten:

108

Die einfache Antwort lautet: Sie können nicht, weil Sass den Selektor dafür nicht komponieren kann (oder will). Sie können sich nicht innerhalb einer Medienabfrage befinden und etwas erweitern, das außerhalb einer Medienabfrage liegt. Es wäre sicherlich schön, wenn es einfach eine Kopie davon nehmen würde, anstatt zu versuchen, die Selektoren zusammenzustellen. Aber es ist nicht so, dass du es nicht kannst.

Verwenden Sie ein Mixin

Wenn Sie einen Fall haben, in dem Sie einen Codeblock innerhalb und außerhalb von Medienabfragen wiederverwenden und dennoch möchten, dass er ihn erweitern kann, schreiben Sie sowohl eine Mixin- als auch eine Extend-Klasse:

@mixin foo {
    // do stuff
}

%foo {
    @include foo;
}

// usage
.foo {
    @extend %foo;
}

@media (min-width: 30em) {
    .bar {
        @include foo;
    }
}

Erweitern Sie den Selektor innerhalb einer Medienabfrage von außen

Dies wird Ihrem Anwendungsfall nicht wirklich helfen, aber es ist eine weitere Option:

%foo {
  @media (min-width: 20em) {
    color: red;
  }
}

@media (min-width: 30em) {
  %bar {
    background: yellow;
  }
}

// usage
.foo {
  @extend %foo;
}

.bar {
  @extend %bar;
}

Warten Sie, bis Sass diese Einschränkung aufhebt (oder flicken Sie sie selbst).

Es gibt eine Reihe von laufenden Diskussionen zu diesem Thema (bitte tragen Sie nicht zu diesen Threads bei, es sei denn, Sie haben etwas Sinnvolles hinzuzufügen: Die Betreuer sind sich bereits bewusst, dass Benutzer diese Funktionalität wünschen, es ist nur eine Frage der Implementierung und der Funktionsweise Syntax sollte sein).

Cimmanon
quelle
@mindeavour Das hat bei dir funktioniert? Sie konnten die erweiterte Klasse in einer Medienabfrage verwenden? In Sass 3.2?
Yahreen
1
%fooist unnötig, .fookann direkt @include foo.
Phil294
In meinem Fall habe ich gerade% placeholder verwendet, um externe Medienabfragen zu erweitern. Dann, innerhalb der Medienabfrage, für meinen Selektor gerade Extend% Platzhalter hinzugefügt. Mal sehen, ob die Diskussionen etwas Nützliches bringen. Danke Cimmanon.
Keypaul
11

Für die Aufzeichnung ist hier, wie ich das Problem gelöst habe, indem ich generierte Stile nur einmal dupliziert habe:

// 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;
  }
}
soundly_typed
quelle
2

Ich glaube, SASS / SCSS unterstützt das nicht @extend Direktive innerhalb einer Medienabfrage nicht. http://designshack.net/articles/css/sass-and-media-queries-what-you-can-and-cant-do/

Möglicherweise müssen Sie stattdessen ein Mixin verwenden, obwohl das Aufblähen des Codes gegen Ihr Ziel abgewogen werden muss.

JHogue
quelle
Ein Link zu einer Lösung ist willkommen, aber stellen Sie sicher, dass Ihre Antwort ohne sie nützlich ist: Fügen Sie dem Link einen Kontext hinzu, damit Ihre Mitbenutzer eine Vorstellung davon haben, was es ist und warum es dort ist, und zitieren Sie dann den relevantesten Teil der Seite, die Sie verwenden. erneutes Verknüpfen mit, falls die Zielseite nicht verfügbar ist. Antworten, die kaum mehr als ein Link sind, können gelöscht werden.
Dippas
1

Dies ist die sauberste Teillösung, die ich gefunden habe. Wenn möglich, nutzt es @extend und greift bei Medienabfragen auf Mixins zurück.

Medienübergreifende Abfrage @ Erweiterungsanweisungen in Sass

Ausführliche Informationen finden Sie im Artikel. Im Wesentlichen wird jedoch ein Mixin-Platzhalter aufgerufen, der dann entscheidet, ob @extend oder @include ausgegeben wird.

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

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

Letztendlich ist es vielleicht nicht besser als nur Mixins zu verwenden, was derzeit die akzeptierte Antwort ist.

Tom Genoni
quelle
0

Ich benutze Haltepunkte, aber es ist die gleiche Idee:

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

Wie man es benutzt:

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

Es gibt einen Text über Mixins, in dem Sie mehr über diese Option erfahren können.

Nesha Zoric
quelle
-2

Könnten Sie umstrukturieren?

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

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

Wenn ich die Dokumentation richtig verstehe, sollte das funktionieren. Ich denke, der Grund, warum Sie versuchen, nicht zu funktionieren, ist, dass beim Parsen von @extend .item.compact nicht angezeigt wird, aber das ist eine nicht informierte Vermutung. Nehmen Sie das also mit einer Lastwagenladung Salz! :) :)

Jason M. Batchelor
quelle
Wie kompilierst du deinen SASS? Extern, mit JS oder mit einer serverseitigen Komponente?
Jason M. Batchelor
Es wird durch das Standard- rails-sassJuwel mit SASS v3.2.4 kompiliert
soundly_typed
1
Es sieht so aus, als ob die Möglichkeit, innerhalb von @ media-Abfragen zu erweitern, veraltet ist und in 3.3 gestrichen werden soll : chriseppstein.github.com/blog/2012/08/23/sass-3-2-is-released (lesen Sie den Bereich, in dem steht "Einschränkungen @extendin CSS-Richtlinien")
Jason M. Batchelor
Wenn ich diese Informationen richtig verstanden habe, könnte dies das Problem verursachen. Es würde mich interessieren, was Sie herausfinden!
Jason M. Batchelor