CSS @apply & @extend Rules Unas ideas interesantes

Dos ideas CSS interesantes de Tab Atkins: las CSS at rules @apply y @extend. Su estado, ejemplos de uso y alguna opinión y discrepancias personales en la sintaxis de su construcción y uso.

CSS @apply & @extend Rules Unas ideas interesantes

Por Kseso ✎ 3
CSS @apply Rule

Estos días está teniendo bastante eco la regla CSS @apply [ver CSS @apply Rule]. Posíblemente, a poco que te guste estar al día sobre CSS, también te haya llegado algo al respecto.

Y a poco curioso que hayas sido lo primero que habrás advertido es que en el corpus oficial de CSS no hay nada al respecto. Ni un simple borrador en todo el site del W3c.

Entonces, ¿de qué se está hablando?

Status CSS @apply Rule

Si vas al documento CSS @apply Rule lo primero que observarás es que su destino no es el consorcio W3c. Está alojado en github.io y su subtítulo ya da otra pista: A Collection of Interesting Ideas, 25 August 2015. Su autor o editor en la jerga CSS es Tab Atkins-Bittner (Google).

Su autor: Tab Atkins

Tab Atkins desde su trabajo en Google es uno de los editores de documentos CSS del W3c más prolíficos. Muy activo tanto en la redacción de múltiples especificaciones CSS como en la lista de correo de CSS así como en Twitter (@tabatkins).

Otro aspecto, para mi muy reseñable y de agradecer, es que es muy accesible. Esto es, si te diriges a él vía Twitter con alguna cuestión, duda o comentario oportuno tienes casi garantizada la respuesta. Y en la lista de correo de CSS igual.

Además de sus ediciones "oficiales" también publica (últimamente las aloja en github) lo que él mismo llama Collection of Interesting Ideas que inicialmente son eso, ideas interesantes. Estas ideas puede que tengan desarrollo y continuidad y verse incorporadas al corpus oficial o que por cualquier motivo se queden en eso, ideas interesantes, como las "element @queries".

CSS @apply Rule ¿qué son?

Así las define Tab Atkins en su "idea":

La regla CSS @apply permite a un autor almacenar un conjunto de declaraciones CSS en una variable `de autor´ (a named variable), para a continuación, hacer referencia a ellas (incluirlas) en otras reglas de estilo.

Pero seguro que expresado en forma de código CSS lo comprendemos mejor:

/* 1º */ :root { --toolbar-theme: { background-color: blue; border-radius: 4px; border: 1px solid var(--theme-color late); }; /* Observa el ; tras el } de cierre */ --toolbar-title-theme: { color: green; }; /* Observa el ; tras el } de cierre */ } /* 2º */ .toolbar { @apply --toolbar-theme; } .toolbar > .title { @apply --toolbar-title-theme; }
  1. Como ves, lo que tenemos en el punto 1º es básicamente una regla CSS con su selector :root y dos declaraciones CSS en las que las 2 propiedades son dos "custom property" y el valor (o equivalencia) de cada una es un bloque de declaraciones:
    • dos `custom properties´ --toolbar-theme y --toolbar-title-theme seguidas cada una de ellas por el carácter : (dos puntos).
    • El valor de cada una de ellas en vez de ser un valor CSS está formado por un bloque de declaraciones, incluidas las llaves de apertura y cierre: {...} y el "punto y coma" ; que indica el final de las declaraciones.
  2. En 2º tenemos dos reglas CSS normales y corrientes, en las que aplicamos (a semejanza de las custom properties tradicionales) la equivalencia realizado en el punto 1º. Pero a diferencia de las custom properties tradicionales en vez de usar la nomenclatura var(--nombre) se usa @apply --nombre para hacer lo mismo con todo el grupo de declaraciones.

Al igual que ocurre con las custom properties que su valor puede ser reescrito o acotado podemos hacer lo mismo con con la regla CSS @apply.

Un `toolbar´ en el elemento `warning´ ignorará el color verde de la declaración anterior y se mostrará con color rojo declarando:

.warning { --toolbar-title-theme: { color: red; font-weight: bold; }; }

CSS @apply Rule estado de la cuestión

Y por qué tanto revuelo con algo que no deja de ser una idea interesante que de momento (hasta donde yo conozco) no ha sido trasladada al corpus CSS.

Porque da la casualidad (o no, que su autor trabaja en Google) que el navegador Chrome en su última versión de Chrome Canary ya las soporta habilitando la opción Experimental Web Platform Features en chrome://flags.

CSS @apply Rule en Chrome Canary
CSS @apply Rule en Chrome Canary. Origen imagen

CSS @extend Rule

Ya metidos con ideas interesantes te presento otra del mismo autor: la regla CSS @extend. De ella dice su autor, también Tab Atkins, lo siguiente:

La regla CSS @extend permite que un elemento (del html) se comporte (estilice) como si fuese afectado por otro selector (css) diferente.

O lo que es lo mismo, permite añadir a un bloque de declaraciones de un selector todos los estilos declarados en cualquier otra regla CSS usando para ello el nombre de su selector.

En código, que es más sencillo de comprender y aplicar que explicar:

.error { color: red; border: thick dotted red; } .serious-error { @extend .error; font-weight: bold; }

El resultado de este código CSS será que un elemento del HTML con un valor serious-error en su atributo class además de mostrarse en negrita (`bold´) se le aplicarán los estilos declarados en el CSS para la regla del selector .error. Esto es, color rojo con el borde correspondiente.

Mi blog. Mi opinión

De entrada, para que no haya malas interpretaciones: me encantan todas las novedades de CSS y más aún poder jugar con ellas. Para ello es necesario que

  • 1º: que quienes saben ideen y pongan por escrito las novedades.
  • 2º: que haya al menos un solo navegador que las incorpore para explorar sus posibilidades y límites.
  • 3º: y con lo anterior a mi disposición compartir en el blog mis juegos y experiencias.

Pero como este juguete llamado EsCss es mio me voy a permitir meter mi opinión personal. Ya ves tú, un simple enredique amanuense de CSS que se viene arriba frente a toda una autoridad como Tab Atkins y un gigante como Google. Pero es que la ignorancia es muy atrevida.

Google Chrome

En primer lugar hay cosas del proceder de Chrome respecto a CSS que me tienen totalmente descolocado y que no acierto a comprender. Dos en particular:

  1. El sacar de su core soporte a novedades después de llevar un tiempo haciéndolo. Como con position: sticky o a las Regiones CSS.
  2. La inclusión y soporte de un sinfín de propiedades CSS ajenas por completo al corpus de CSS. Y no me refiero a las estándares a las que añade su prefijo privativo.

Me recuerda el proceder de Microsoft con sus IE´s cuando eran prácticamente monopolio (usados cuasi de forma universal) con sus filter´s y basuras por el estilo.

Esto supone romper la web. Volver a los tiempos salvajes donde el concepto "standard web" era un chiste, chascarrillo o sueño húmedo (dependiendo de quién lo invocase).

Además de este peligro ya estamos viendo otros efectos: la influencia que ejerce Google Chrome en otros equipos de desarrolladores de navegadores es tal que su mala praxis se extiende a ellos (incluyendo ellos también soporte al prefijo -webkit- y a esas propiedades no estándar.

Sintaxis @apply y @extend

Desde hace ya un tiempo hay un movimiento para uniformizar y mantener una sintaxis coherente a lo largo de todo el desarrollo de CSS. Un ejemplo de ellos es el uso del doble guión --* en todo aquello en nombrado (asignado nombre) por el usuario. Como las `custom properties´. Coherencia que se intenta extender también a lo que ya existía antes de esta idea, como el nombre de los contadores.

Hasta el momento en las reglas CSS de reglas (reglas @ o at rules) dicha sintaxis se venía respetando incluyendo aquellos casos en los que en una parte se define dicha regla y se hace uso en alguna otra regla.

Piensa en la similitud de @apply y @extend con las reglas @keyframes y la propiedad animation. En una parte se define y en otra se aplica.

Creo que @apply y @extend serían más coherentes en su sintaxis si:

  1. La regla CSS @apply

    A semejanza de las "custom properties" en su declaración de equivalencias como es una at rule de autor se identificase como tal: como "at rule" y como "custom named": @--*
    :root {
       @--miNombre {
         /*bloque declaraciones */
       };
     }
    .el {
     apply: var(@--miNombre);
     }
    y en el momento de su uso también se conservaría la coherencia de las declaraciones CSS y uso de una "custom named": propiedad: valor;
  2. La regla CSS @extend

    Aquí es el mismo caso que el segundo paso o uso de la regla @ de autor (custom at rule). De la forma que ahora está no hay concordancia a cómo se construyen las declaraciones CSS:
    propiedad: valor;
    Creo que sería más apropiado el uso de una la propiedad sin el símbolo @ en su nombre y como valor utilizar una función CSS. Esto es, el valor sería un identificador de la función y entre paréntesis el recurso a utilizar:
    .error {
      color: red;
    }
    
    .serious-error {
      extend: selector(.error);
      font-weight: bold;
    }
    A semejanza de los filtros CSS cuando se usa un id (filter: url(#id); o cualquier otro recurso (i.e. imágenes en los fondos).

Ahora te toca a ti decirnos qué te parecen estas dos "ideas interesantes" y además darme algún palito o colleja por mis opiniones al respecto de la forma en que están definidas sus sintaxis y forma de uso.

Adenda

Un signo de estos tiempos es que los comentarios a los artículos de cualquier blog o página se diluyen y dispersan mucho en las distintas redes sociales. Y aunque los usuarios de este blog son/sois (por lo general) parcos en las opiniones y discretos en nuestra relación de vez en cuando esto cambia.

En esta ocasión me parece más que interesante la conversación e intercambio de ideas con Lionel (aka @elrumordelaluz). La puedes ver aquí y su continuación aquí.

Ramajero Argonauta, Enredique Amanuense de CSS.
#impoCSSible inside
Dicen que, en español, EsCss es el mejor blog de CSS. Posíblemente exageren.
@Kseso EsCss Don Kseso Kseso

Comentarios: 3

  1. Si algo caracteriza a la comunidad de este blog es que mucha gente viene a verlo pero muy, muy pocos participan.

    No es mi caso, que vengo a molestar seguido. Y nada de opiniones originales, siempre vengo (tarde o temprano) a repetir lo mismo.

    Hace algunos años discutíamos sobre el uso a rajatabla de las especificaciones del W3C a modo de estándar. Mi posición nunca fue contraria a un reglamento patrón, como referencia; pero siempre aclaraba que esas recomendaciones no eran ni de lejos un estándar, porque la tecnología avanza y hay que ajustarlas todo el tiempo. Claro que ése era el menor de los problemas. La recomendación estaba dirigida a los fabricantes de aplicaciones, no a los diseñadores o programadores fron-end, muchísimo menos a los usuarios. Ninguno de nosotros puede hacer nada si un navegador no incorpora el soporte a una regla CSS ¿La vamos a escribir igual porque lo dice el Consortium? ¡Si no funciona!.
    Y no se termina ahí. Si la tecnología evoluciona y los fabricantes compiten entre sí por hacer el mejor (o más vendible) producto, nunca se van a dejar atar las manos por un supuesto estándar. Van a seguir incorporando sus inventos para ser superiores. Así funciona el negocio.

    Hoy parece evidente, pero hace 10 años era casi imposible hacer que la mayoría de los desarrolladores entendiera algo tan obvio.

    Critiqué mucho a Microsoft y su Internet Explorer, a pesar de que su producto no fuera realmente malo. Había una campaña contra el IE para atacar a su fabricante y sus prácticas lamentables, pero era innegable que inventaron primero todos los efectos que hoy (años y años después) recién se pueden ver en otros navegadores. Y algunos ni eso; sigo esperando la opacidad con gradiente y el filtro chroma-k, entre otros.

    Que Google haya tomado la posta no es sorpresa para nadie. En aquellos años no podíamos ponerle nombre, ni recuerdo si el buscador ya existía o aún todos usábamos Altavista; pero si no eran ellos, iba a ser otro. De cualquier forma, aquellas críticas y campañas contra las malas prácticas debieron servir de aviso. Todos estos inventos que incorpora Chrome lo está haciendo a través de Canary. Y están en su derecho, porque ya sabemos que es para pruebas, y tienen prerrogativa de hacer lo que quieran allí.
    No en nuestro Chrome de cada día, como hacía Microsoft con IExplorer.

    Luego de esta nada breve introducción, comento, sí, sobre @apply y @extend. Y sabiendo mucho, pero mucho menos que Kseso y Tab Atkins. (Aclaro por si cae alguien ahora y nunca leyó nada de lo que vengo garabateando en la web.)

    A primera vista no les encuentro más utilidad que a una combinación de selectores separados por comas. La regla que le sea particular a un selector, se agrega abajo.
    Ahora bien, el día que esto se incorpore y se pueda alcanzar con javascript, nos van a facilitar enormemente los inventos para dar formatos desde allí a los elementos de la página, que hoy terminan siendo bastante engorrosos. La mejor opción de que disponemos es crear las reglas en clases, y después aplicarlas en donde querramos cambiar un formato complejo.
    Así que no es una ayuda para CSS, sino para JS.

    Y ya que lo mencionamos, los formatos 'algo(argumento)' indican que detrás hay una función CSS. Siempre tuve dudas con 'url(ruta)', pero supongo que también será función. Hay que ver si en este caso la lógica se aplica, y de ser así también coincido con el articulista en su opinión para optimizar la sintaxis.

    ResponderEliminar
  2. Tanto SASS como Less soportan variables y extend, dos de las razones más importantes para tomar la decisión de usar CSS preprocessor. Que la W3C termine integrándolo de una forma u otra, será algo natural. Espero que no tarden.

    ResponderEliminar
    Respuestas
    1. JuniHH.
      Existen pero no son lo mismo.
      Por alguna parte del blog ya hemos comentado la gran diferencia entre las nativas de CSS y las "privativas de cada procesador"".

      Resumiendo:

      .-- las "privativas" desaparecen como tales al procesar el código la herramienta (Sass, Less, postC...) para mandar el resultado (código CSS "estandar") al navegador, que lo que recibe es un valor concreto. El navegador computa un valor concreto y preciso.

      .-- las nativas no se procesan. Esto es, permanecen como tales en el código CSS que recibe el navegador. Es el navegador el que computa (calcula el valor) todas y cada una de las veces que se encuentra con ella y dependiendo de dónde se la encuentre.

      Pero por encima de estas cuestiones está el hecho de que no es lo mismo las metodologías, formas, usos y costumbres de lenguajes "privados" que los que están sujetos a un proceso "público y bajo un estándar con el que cumplir".

      Un saludo.

      Eliminar

EsCss RSS del Blog RSSS Comentarios Humans.txt ᛯ Diseno por Kseso SiteMap