sass css: classe de parent cible de l'enfant
j'utilise sass et j'ai trouvé un problème. Ceci est un exemple de ce que je suis en train de faire:
.message-error {
background-color: red;
p& {
background-color: yellow
}
}
Prévue css:
.message-error {
background-color: red;
}
p.message-error {
background-color: yellow ;
}
L'idée: tous les éléments .message d'erreur s'affichera en rouge, sauf si elle est p.message d'erreur. Ce n'est pas une situation réelle, juste pour montrer un exemple.
SASS n'est pas capable de compiler ceci, j'ai même essayé la concaténation des chaînes. Y a-t-il un plugin qui fera exactement la même chose?
NOTE: Je sais que je peux mettre un autre css définition de la forme
p.message-error{....}
sous, mais je voudrais éviter cela et utiliser un endroit pour tous .message-définitions d'erreur.
Merci.
10 réponses
à partir de sass 3.4, ceci est maintenant pris en charge. La syntaxe ressemble à ceci:
.message-error {
background-color: red;
@at-root p#{&} {
background-color: yellow
}
}
Notez le @at-root
la directive et la syntaxe d'interpolation sur l'ampli. Le défaut d'inclure les @at-root
la directive entraînera un sélecteur .message-error p.message-error
plutôt que p.message-error
.
Natalie Weizenbaum (le lead designer et développeur de Sass) dit qu'il ne sera jamais pris en charge:
Actuellement
&
est syntaxiquement identique à un sélecteur d'éléments, donc il ne peut pas apparaître aux côtés de l'un. Je pense que cela aide à clarifier où il peut être utilisé; par exemple,foo&bar
ne serait jamais un valide sélecteur (ou serait peut-être équivalent àfoo& bar
oufoo &bar
). je ne pense pas que cette utilisation l'affaire est suffisamment solide pour justifier un changement que.
Source:#282 – Élément.sélecteur parent
à ma connaissance, il n'y a pas de solution possible.
La meilleure chose à faire serait probablement ceci (en supposant que vous avez un peu plus dans votre .message d'erreur classe que juste la couleur d'arrière-plan.
.message-error {
background-color: red;
}
p.message-error {
@extend .message-error;
background-color: yellow
}
cette approche n'offre pas ce regroupement étroit, mais vous pouvez simplement les garder proches les uns des autres.
je pense que si vous voulez les garder regroupés par parent sélecteur, vous pouvez avoir besoin d'ajouter un parent commun:
body {
& .message-error {background-color: red;}
& p.message-error {background-color: yellow}
}
bien sûr, body
peut être remplacé par un autre parent commun, tels que #Content
ou un autre div
qui contiendra tous les messages d'erreur.
mise à JOUR (une Autre Idée)
Si vous utilisez @ et listes alors il semble que cela devrait fonctionner (ce que je ne sais pas est si la liste permettra à l' .
(période).
@for $i from 1 to 3 {
nth(. p. ul., #{$i})message-error {
background-color: nth(red yellow cyan, #{$i}));
}
}
devrait se compiler à quelque chose comme:
.message-error {
background-color: red;}
p.message-error {
background-color: yellow;}
ul.message-error {
background-color: cyan;}
La clé est l'espace avant le '&':
.message-error {
background-color: red;
p & {
background-color: yellow
}
}
au lieu de:
.message-error {
background-color: red;
p& {
background-color: yellow
}
}
j'ai couru dans cette avant que. Bootstrap 3 gère cela en utilisant un hack de sélecteur parent. Je l'ai légèrement modifié pour mes propres besoins...
@mixin message-error() {
$class: '.message-error';
#{$class} {
background-color: red;
}
p#{$class} {
background-color: yellow;
}
}
@include message-error();
wheresrhys utilise une approche similaire ci-dessus, mais avec quelques sass erreurs. Le code ci-dessus vous permet de le gérer comme un bloc et le réduire dans votre éditeur. L'imbrication de la variable le rend également local de sorte que vous pouvez réutiliser $class pour toutes les instances où vous devez appliquer ce hack. Voir ci-dessous pour un travail échantillon...
j'ai fait un mixin qui résout ce problème.
https://github.com/imkremen/sass-parent-append https://codepen.io/imkremen/pen/RMVBvqUtilisation (scss):
.ancestor {
display: inline-flex;
.grandparent {
padding: 32px;
background-color: lightgreen;
.parent {
padding: 32px;
background-color: blue;
.elem {
padding: 16px;
background-color: white;
@include parent-append(":focus", 3) {
box-shadow: inset 0 0 0 8px aqua;
}
@include parent-append(":hover") {
background-color: fuchsia;
}
@include parent-append("p", 0, true) {
background-color: green;
}
}
}
}
}
Résultat (css):
.ancestor {
display: inline-flex;
}
.ancestor .grandparent {
padding: 32px;
background-color: lightgreen;
}
.ancestor .grandparent .parent {
padding: 32px;
background-color: blue;
}
.ancestor .grandparent .parent .elem {
padding: 16px;
background-color: white;
}
.ancestor:focus .grandparent .parent .elem {
box-shadow: inset 0 0 0 8px aqua;
}
.ancestor .grandparent .parent:hover .elem {
background-color: fuchsia;
}
.ancestor .grandparent .parent p.elem {
background-color: green;
}
j'ai eu le même problème j'ai donc fait un mixin.
@mixin tag($tag) {
$ampersand: & + '';
$selectors: simple-selectors(str-replace($ampersand, ' ', ''));
$main-selector: nth($selectors, -1);
$previous-selectors: str-replace($ampersand, $main-selector, '');
@at-root {
#{$previous-selectors}#{$tag}#{$main-selector} {
@content;
}
}
}
Pour le faire fonctionner, vous aurez besoin d'un fonction de remplacement de chaîne (à partir de Hugo Giraudel):
@function str-replace($string, $search, $replace: '') {
$index: str-index($string, $search);
@if $index {
@return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
}
@return $string;
}
Comment cela fonctionne:
SCSS
.foo {
color: blue;
@include tag(p) {
color: red;
}
}
Sortie
.foo {
color: blue;
}
p.foo {
color: red;
}
cas D'utilisation
Cette méthode fonctionne avec imbriqué sélecteurs mais pas composé de pentecôte .
cette tricherie pourrait marcher
{
$and: .message-error;
#{$and} {
background-color: red;
}
p#{$and} {
background-color: yellow
}
}
Vous pouvez même être en mesure d'utiliser $&
comme votre nom de variable mais je ne suis pas sûr à 100% qu'il ne lancera pas une erreur.
et SASS a intégré la détermination de la portée, ce qui élimine la nécessité de se soucier de la valeur de $and
fuite pour le reste de votre feuille de style
les Variables ne sont disponibles qu'au niveau des sélecteurs imbriqués où elles sont définies. Si ils sont définis en dehors de toutes les sélecteurs, ils sont disponible partout.
dans la version actuelle: Selective Steve (3.4.14) c'est maintenant possible, il suffit de mettre à jour un peu votre code:
.message-error {
background-color: red;
p &{
background-color: yellow
}
}
cela ne fonctionne que si vous êtes d'un niveau imbriqués, par exemple, il ne fonctionne pas si vous avez quelque chose comme ceci:
.messages{
.message-error {
background-color: red;
p &{
background-color: yellow
}
}
}