Sass kombiniert Eltern mit kaufmännischem Und (&) mit Typselektoren

99

Ich habe Probleme mit dem Nisten in Sass. Angenommen, ich habe den folgenden HTML-Code:

<p href="#" class="item">Text</p>
<p href="#" class="item">Text</p>
<a href="#" class="item">Link</a>

Wenn ich versuche, meine Stile wie folgt zu verschachteln, wird ein Kompilierungsfehler angezeigt:

.item {
    color: black;
    a& {
        color:blue;
   }
}

Wie verweise ich auf einen Typselektor vor dem übergeordneten Selektor, wenn dieser Teil desselben Elements ist?

McShaman
quelle

Antworten:

155

Wie Kumar betont , ist dies seit Sass möglich 3.3.0.rc.1 (Maptastic Maple).

Die @ at-root-Direktive bewirkt, dass eine oder mehrere Regeln im Stammverzeichnis des Dokuments ausgegeben werden, anstatt unter ihren übergeordneten Selektoren verschachtelt zu sein.

Wir können die @at-rootDirektive zusammen mit der Interpolation#{} kombinieren , um zum beabsichtigten Ergebnis zu gelangen.

SASS

.item {
    color: black;
    @at-root {
        a#{&} {
            color:blue;
        }
    }
}

// Can also be written like this.
.item {
    color: black;
    @at-root a#{&} {
        color:blue;
    }
}

CSS ausgeben

.item {
    color: black;
}
a.item {
    color: blue;
}
Blaine
quelle
3
Dies sollte die Lösung für diese Frage sein.
Kayhadrin
Das funktioniert bei mir nicht ... die Ausgabe kommt aus .item a.itemirgendeinem Grund heraus. Ich habe a#{&}es auch alleine versucht und trotzdem das gleiche Ergebnis erzielt.
Jaminroe
@jaminroe benutzt du Libsass? Es wird in 3.3 behoben .
Blaine
1
@jaminroe sieht aus, als würde libsass (node-sass) unter der Haube verwendet. In diesem Fall müssen Sie bis 3.3 warten.
Blaine
1
Ich habe eine etwas schwierigere Version davon zu lösen, ähnlich, aber mit mehreren Klassen, die an ein Tag angehängt werden muss - jemand?
Frank Nocke
29

Die @at-rootMethode -only löst das Problem nicht, wenn Sie beabsichtigen, den nächstgelegenen Selektor entlang der Kette zu erweitern. Als Beispiel:

#id > .element {
    @at-root div#{&} {
        color: blue;
    }
}

Wird kompiliert zu:

div#id > .element {
    color: blue;
}

Was ist, wenn Sie Ihr Tag .elementanstelle von verbinden müssen #id?

Es gibt eine Funktion in Sass selector-unify(), die dieses Problem löst. Mit diesem @at-rootist es möglich zu zielen .element.

#id > .element {
    @at-root #{selector-unify(&, div)} {
        color: blue;
    }
}

Wird kompiliert zu:

#id > div.element {
    color: blue;
}
Ben Fleming
quelle
1
Dies gab mir nicht das beabsichtigte Ergebnis. In Sass 3.4.11 wird dies ausgegeben an #id > .element #id > div.element { color: blue; }. Ein anderer Ansatz wäre zu verwenden selector_replace, #id { > .element { @at-root #{selector-replace(&,'.element', 'div.element')} { color: blue;}}}. Hier ist ein Kern für eine bessere Lesbarkeit.
Blaine
@Blaine Du hast einen krassen Fehler entdeckt, danke. Ich habe meine Antwort mit einer funktionierenden Lösung bearbeitet.
Ben Fleming
1
Das heißt, es selector-replaceist auch eine andere Möglichkeit, dies zu tun, aber es erfordert zu wissen, was der Selektor ist. Das selector-unifyVerfahren hat den Vorteil, dass es in Mixins verwendet wird.
Ben Fleming
Tolle Antwort.
Senthe
8

Für den Anfang (zum Zeitpunkt des Schreibens dieser Antwort) gibt es keine Sass-Syntax, die Selector & verwendet . Wenn Sie so etwas tun würden, benötigen Sie ein Leerzeichen zwischen dem Selektor und dem kaufmännischen Und. Beispielsweise:

.item {
    .helper & {

    }
}

// compiles to:
.helper .item {

}

Die andere Art, das kaufmännische Und zu verwenden, ist wahrscheinlich das, wonach Sie (fälschlicherweise) suchen:

.item {
    &.helper {

    }
}

// compiles to:
.item.helper {

}

Auf diese Weise können Sie Selektoren mit anderen Klassen, IDs, Pseudo-Selektoren usw. erweitern. Leider würde dies in Ihrem Fall theoretisch zu etwas wie .itema kompiliert, was offensichtlich nicht funktioniert.

Vielleicht möchten Sie nur überdenken, wie Sie Ihr CSS schreiben. Gibt es ein übergeordnetes Element, das Sie verwenden könnten?

<div class="item">
    <p>text</p>
    <p>text</p>
    <a href="#">a link</a>
</div>

Auf diese Weise können Sie Ihren SASS einfach folgendermaßen schreiben:

.item {
    p {
        // paragraph styles here
    }
    a {
        // anchor styles here
    }
}

(Randnotiz: Sie sollten sich Ihr HTML ansehen. Sie mischen einfache und doppelte Anführungszeichen UND setzen href-Attribute auf p-Tags.)

imjared
quelle
@ Lübnah Ich stimme zu, aber ich versuche nicht, Best Practices für die Steigerung der Mikroleistung zu definieren. Ich versuche, jemanden, der ein hrefTag auf ein setzt, dazu pzu bringen, funktionierendes CSS zu schreiben.
Imjared
Es gibt absolut keine Unterstützung dafür, dass & .selector überhaupt eine schlechte Praxis ist. Es gibt Unmengen von Anwendungsfällen, genau wie die, die OP veröffentlicht hat.
Mike Mellor
@MikeMellor OP schrieb .item { a& }und es gibt keine sass Syntax für die (soweit ich bewusst bin. Ich schlug ihm wahrscheinlich so etwas wie die Ampersand Syntax war auf der Suche Sie beschrieben , die in Sass ziemlich regelmäßig verwendet wird. Allerdings baut auf OPs Beispiel .item { &a }ist ungültig und würde kompilieren.itema . Genau wie ich in meiner Antwort gesagt habe. Gibt es etwas, das mir fehlt?
Imjared
OP gesucht, .item { a& { ... } }was jetzt gemacht werden kann, wie @Blaine mit betont .item { @at-root a#{&} { ... } }. Der Punkt ist, wenn Sie eine Klasse für das Element haben, ist dies einfach. .item { &.class { ... } }Warum sollten Sie nicht in der Lage sein, dasselbe mit einem rohen HTML-Element zu tun? Nur weil es zum Zeitpunkt der Veröffentlichung von OP keine Möglichkeit gab, dies zu tun, heißt das nicht, dass er falsch war, wenn er wollte, dass die Funktionalität es tatsächlich tut.
Mike Mellor
4

AFAIK Wenn Sie kaufmännisches Und für Klasse und Tags gleichzeitig kombinieren möchten, müssen Sie folgende Syntax verwenden:

.c1 {
  @at-root h1#{&},
    h2#{&}
    &.c2, {
    color: #aaa;
  }
}

wird zu kompilieren

h1.c1,
h2.c1,
.c1.c2 {
  color: #aaa;
}

Andere Verwendungen (wie die Verwendung der Klasse vor @at-rootoder mehrere @at-roots) führen zu Fehlern.

Hoffe es wird nützlich sein

Vahid
quelle
1
Ich habe dies gerade verwendet, sehr nützlich für Mixins, bei denen Sie beispielsweise das Verhalten für
span-
wow - sehr cool :-) Das betrügt also im #{&}Grunde den Compiler - oder wird das in Zukunft immer funktionieren?
Simon_Weaver
@ Simon_Weaver in Sass, alles im Inneren #{}wird ausgewertet. Bedeutet auch &Stromauswahl. So #{&}wird ausgewertet .c1.
Vahid
Aber du betrügst es in dem Sinne, dass & alleine nicht funktioniert ;-)
Simon_Weaver
1
@ Simon_Weaver siehe diesen Link für weitere Beispiele von&
Vahid
3

Diese Funktion ist in der neuesten Version von Sass gelandet. 3.3.0.rc.1(Maptastic Maple)

Die beiden eng verwandten Funktionen, die Sie verwenden müssen, sind die Skriptfunktion &, die Sie in verschachtelten Stilen interpolieren können, um auf übergeordnete Elemente zu verweisen, und die @at-rootDirektive, die den unmittelbar folgenden Selektor oder CSS-Block im Stammverzeichnis platziert (dies ist nicht der Fall) habe irgendwelche Eltern in der ausgegebenen CSS)

Weitere Informationen finden Sie in dieser Github-Ausgabe

kumarharsh
quelle