Ampliación de selectores desde dentro de las consultas de medios con Sass

86

Tengo una clase de elemento y una clase compacta de "modificador":

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

Esto esta bien. Sin embargo, me gustaría agregar una @mediaconsulta que obligue a la .itemclase a ser compacta cuando la pantalla es lo suficientemente pequeña.

A primera vista, esto es lo que intenté hacer:

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

Pero esto genera el siguiente error:

No puede @extender un selector externo desde dentro de @media. Solo puede @extender selectores dentro de la misma directiva.

¿Cómo podría lograr esto usando SASS sin tener que recurrir a copiar / pegar estilos?

soundly_typed
fuente
Fyi, aquí hay un problema que haría que el ejemplo que dio funcionara correctamente: github.com/sass/sass/issues/1050
Ajedi32

Respuestas:

112

La respuesta simple es: no puedes porque Sass no puede (o no quiere) componer el selector para ello. No puede estar dentro de una consulta de medios y extender algo que está fuera de una consulta de medios. Ciertamente sería bueno si simplemente tomara una copia en lugar de intentar componer los selectores. Pero no es así, así que no puedes.

Usa un mixin

Si tiene un caso en el que va a reutilizar un bloque de código dentro y fuera de las consultas de medios y aún desea que pueda extenderlo, escriba una clase mixin y una extensión:

@mixin foo {
    // do stuff
}

%foo {
    @include foo;
}

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

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

Extienda el selector dentro de una consulta de medios desde el exterior

Esto realmente no ayudará a su caso de uso, pero es otra opción:

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

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

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

.bar {
  @extend %bar;
}

Espere hasta que Sass elimine esta restricción (o parcheela usted mismo)

Hay una serie de discusiones en curso sobre este tema (no contribuya a estos hilos a menos que tenga algo significativo que agregar: los mantenedores ya saben que los usuarios desean esta funcionalidad, es solo una cuestión de cómo implementarla y qué la sintaxis debería ser).

cimmanon
fuente
@mindeavor ¿Esto funcionó para usted? ¿Pudiste usar la clase extendida en una consulta de medios? ¿En Sass 3.2?
Yahreen
1
%fooes innecesario, .foopuede directamente @include foo.
phil294
En mi caso, acabo de usar% placeholder con consultas de medios externas extendidas. Luego, dentro de la consulta de medios, mi selector acaba de agregar extender% marcador de posición. Veré si las discusiones vienen con algo útil. Gracias Cimmanon.
keypaul
11

Para que conste, así es como terminé resolviendo el problema con solo duplicar los estilos generados una vez:

// 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
fuente
2

Creo que SASS / SCSS no admite la @extenddirectiva dentro de una consulta de medios. http://designshack.net/articles/css/sass-and-media-queries-what-you-can-and-cant-do/

Es posible que deba utilizar un mixin en su lugar, aunque la hinchazón del código debe compararse con su objetivo.

JHogue
fuente
Un enlace a una solución es bienvenido, pero asegúrese de que su respuesta sea útil sin él: agregue contexto alrededor del enlace para que sus compañeros usuarios tengan una idea de qué es y por qué está allí, luego cite la parte más relevante de la página. volver a enlazar en caso de que la página de destino no esté disponible. Las respuestas que son poco más que un enlace pueden eliminarse.
dippas
1

Esta es la solución parcial más limpia que he encontrado. Aprovecha @extend donde sea posible y recurre a mixins cuando se realizan consultas de medios.

Directivas de @extend de consulta de Cross-Media en Sass

Consulte el artículo para obtener todos los detalles, pero la esencia es que llama a un 'marcador de posición' de mezcla que luego decide si generar @extend o @include.

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

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

En última instancia, puede que no sea mejor que simplemente usar mixins, que actualmente es la respuesta aceptada.

Tom Genoni
fuente
0

Yo uso puntos de interrupción, pero es la misma idea:

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

Cómo usarlo:

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

Hay un texto sobre mixins donde puede encontrar más información sobre esta opción.

Nesha Zoric
fuente
-2

¿Podrías reestructurar?

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

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

Si entiendo la documentación correctamente, debería funcionar. Creo que la razón por la que la forma en que lo intentas no funcionará es que no ve .item.compact cuando analiza el @extend, pero esa es una suposición desinformada, ¡así que tómalo con un montón de sal! :)

Jason M. Batchelor
fuente
¿Cómo estás compilando tu SASS? ¿Externamente, con JS o con un componente del lado del servidor de algún tipo?
Jason M. Batchelor
Se está compilando a través de la rails-sassgema estándar , usando SASS v3.2.4
soundly_typed
1
Parece que la capacidad de extender las consultas de @media dentro de @media está obsoleta y se eliminará en 3.3: chriseppstein.github.com/blog/2012/08/23/sass-3-2-is-released (lea el área que dice "Limitaciones @extenden directivas CSS")
Jason M. Batchelor
Si entendí esa información correctamente, eso podría ser lo que está causando el problema. ¡Me interesaría saber qué averiguas!
Jason M. Batchelor