Sass combina padre usando ampersand (&) con selectores de tipo

100

Tengo problemas para anidar en Sass. Digamos que tengo el siguiente HTML:

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

Cuando intento anidar mis estilos en lo siguiente, aparece un error de compilación:

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

¿Cómo hago referencia a un selector de tipo antes del selector principal cuando es parte del mismo elemento?

McShaman
fuente

Respuestas:

156

Como señala Kumar , esto ha sido posible desde Sass 3.3.0.rc.1 (Maptastic Maple).

La directiva @ at-root hace que una o más reglas se emitan en la raíz del documento, en lugar de anidarse debajo de sus selectores principales.

Podemos combinar la @at-rootdirectiva junto con la interpolación#{} para llegar al resultado deseado.

HABLAR CON DESCARO A

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

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

CSS de salida

.item {
    color: black;
}
a.item {
    color: blue;
}
Blaine
fuente
3
Esta debería ser la solución a esta pregunta.
Kayhadrin
Esto no funciona para mí ... la salida está saliendo .item a.itempor alguna razón. Intenté hacerlo a#{&}solo también y sigue siendo el mismo resultado.
Jaminroe
@jaminroe, ¿estás usando Libsass? Se solucionará en 3.3 .
Blaine
1
@jaminroe parece que está usando libsass (node-sass) debajo del capó. Si ese es el caso, deberá esperar hasta la 3.3.
Blaine
1
Tengo una versión un poco más difícil de resolver de esto , similar, pero con múltiples clases, que debe agregarse a una etiqueta , ¿alguien?
Frank Nocke
29

El @at-rootmétodo -only no resolverá el problema si tiene la intención de extender el selector más cercano en la cadena. Como ejemplo:

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

Se compilará para:

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

¿Qué sucede si necesita unir su etiqueta a en .elementlugar de #id?

Hay una función en Sass llamada selector-unify()que resuelve esto. Usando esto con @at-rootes posible apuntar .element.

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

Se compilará para:

#id > div.element {
    color: blue;
}
Ben Fleming
fuente
1
Esto no me dio el resultado esperado. En Sass 3.4.11, esta salida a #id > .element #id > div.element { color: blue; }. Otro enfoque sería usar selector_replace, #id { > .element { @at-root #{selector-replace(&,'.element', 'div.element')} { color: blue;}}}. Aquí hay una esencia para una mejor legibilidad.
Blaine
@Blaine Has detectado un error evidente, gracias. Edité mi respuesta con una solución funcional.
Ben Fleming
1
Dicho esto, selector-replacetambién es otra forma de hacerlo, pero requiere saber qué es el selector. El selector-unifymétodo tiene la ventaja de ser utilizado en mixins.
Ben Fleming
Respuesta impresionante.
Senthe
8

Para empezar, (al momento de escribir esta respuesta) no hay una sintaxis sass que use selector & . Si fuera a hacer algo así, necesitaría un espacio entre el selector y el ampersand. Por ejemplo:

.item {
    .helper & {

    }
}

// compiles to:
.helper .item {

}

La otra forma de usar el ampersand es probablemente lo que está buscando (incorrectamente):

.item {
    &.helper {

    }
}

// compiles to:
.item.helper {

}

Esto le permite extender los selectores con otras clases, ID, pseudo-selectores, etc. Desafortunadamente para su caso, esto teóricamente se compilaría en algo como .itema que obviamente no funciona.

Es posible que desee reconsiderar cómo está escribiendo su CSS. ¿Hay algún elemento principal que pueda utilizar?

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

De esta manera, podría escribir fácilmente su SASS de la siguiente manera:

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

(Nota al margen: debería echar un vistazo a su html. Está mezclando comillas simples y dobles Y poniendo atributos href en etiquetas p).

imjared
fuente
@ Lübnah Estoy de acuerdo, pero no estoy tratando de definir las mejores prácticas para obtener ganancias en el micro rendimiento. Estoy tratando de que alguien que está poniendo una hrefetiqueta en un pescriba CSS que funcione.
Publicado
No hay absolutamente ningún soporte para decir & .selector es una mala práctica en absoluto, hay toneladas de casos de uso exactamente como el que OP estaba publicando.
Mike Mellor
@MikeMellor OP escribió .item { a& }y no hay una sintaxis sass para eso (hasta donde yo sé, sugerí que probablemente estaba buscando algo como la sintaxis ampersand que describiste, que se usa con bastante regularidad en Sass. Sin embargo, basándose en el ejemplo de OP, .item { &a }es no válida y se compilará a.itema .. al igual que dije en mi respuesta es que hay algo que me falta?
imjared
OP quería .item { a& { ... } }que ahora se puede hacer como señala @Blaine con .item { @at-root a#{&} { ... } }. El punto es que si tiene una clase en el elemento, es fácil hacerlo, .item { &.class { ... } }¿por qué no debería poder hacer lo mismo con un elemento html sin formato? El hecho de que no hubiera forma de hacerlo en el momento en que OP publicó no significa que no haya sido correcto querer que la funcionalidad lo haga.
Mike Mellor
4

AFAIK En caso de que desee combinar el ampersand para la clase y las etiquetas al mismo tiempo, debe utilizar esta sintaxis:

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

se compilará para

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

Otros usos (como usar la clase antes @at-rooto usar múltiples @at-roots) conducirán a errores.

Espero que te sea de utilidad

Vahid
fuente
1
Acabo de usar esto, muy útil para mixins donde desea variar el comportamiento de los elementos span o div, por ejemplo
santiago arizti
wow - muy bueno :-) Así #{&}que básicamente está engañando al compilador, ¿¡o esto siempre funcionará en el futuro !?
Simon_Weaver
@Simon_Weaver con descaro, #{}se evalúa todo lo que hay dentro . También &significa selector de corriente. Por lo que #{&}se evalúa .c1.
Vahid
Pero lo estás engañando en el sentido de que & alone no funciona ;-)
Simon_Weaver
1
@Simon_Weaver vea este enlace para ver más ejemplos de&
Vahid
3

Esta función ha llegado a la versión más reciente de Sass, 3.3.0.rc.1(Maptastic Maple)

Las dos características estrechamente relacionadas que necesitará usar son el programable &, que puede interpolar dentro de estilos anidados para hacer referencia a elementos principales, y la @at-rootdirectiva, que coloca el selector o bloque de CSS inmediatamente siguiente en la raíz (no lo hará). tener padres en el css generado)

Consulte este problema de Github para obtener más detalles.

Kumarharsh
fuente