soy Kseso y esto EsCSS

Selector Css por valor de Atributo: simplifica la hoja de estilos y el Html

Explicación a fondo del selector Css por valor de atributo: todas sus posibles variaciones y las novedades del último documento. Con aplicación práctica a la mejora de la hoja de estilos y el Html de Bootstrap

Selector Css por valor de Atributo: simplifica la hoja de estilos y el Html

Por Kseso ✎ 14
Selector Css por valor de Atributo: simplifica la hoja de estilos y el Html

El selector Css. Guía a fondo para iniciados y novatos en Css es un artículo de este blog de consulta obligada para comprender los selectores Css... si necesitas información sobre ellos, claro.

Hay un viejo recurso para poder declarar conjuntamente, en una sola regla Css, las declaraciones comunes y compartidas por varios elementos del Html marcados con un valor distinto en su atributo class.

Es el uso de un selector múltiple. Esto es, hacer una relación con todos y cada uno de dichos valores (selectores de clase) separados por comas ,

Recurso que sigue funcionando de forma satisfactoria. Es funcional al 100% y es totalmente válido (según las especificaciones).

Sin embargo, pese a todo lo anterior, no deja de tener sus pequeños inconvenientes. Inconvenientes que hace ya un tiempo que pueden obviarse utilizando el selector por atributo y/o su valor en lugar de esa larga relación de valores dispares.

Las más significativas serían sin extendernos demasiado:

  • Hace interminable la hoja de estilos.
  • Propenso a cometer algún error de omisión o de teclado.
  • En caso de tener que añadir algún otro elemento a esa relación debes modificar la hoja obligatoriamente para ingluirlo.

Por si la descripción anterior no resulta clara, me estoy refiriendo a lo que ves en la imagen de abajo. Dos reglas Css. La primera afecta a 12 elementos distintos del html y la segunda a 48.

Regla Css con selector múltiple
Reglas Css con selectores múltiples de clase

Bonita relación. Y no. No es algo que me haya inventado para ilustrar el artículo. Proviene del framework[1] Bootstrap, referente a la construcción de su grilla.

La solucción: selector por atributo

No pierdas de vista la imagen anterior con su ristra de selectores y compárala con la siguiente:

Reglas Css con selector único por atributo
Reglas Css con selector único por atributo

No hay color. Donde antes necesitábamos de 60 selectores en dos reglas (12 y 48) para otros tantos elementos, ahora lo hemos reducido a uno sólo en cada regla. Si no ves las ventajas, allá tú. No pienso explayarme en ellas ;-) xD

Bueno, sólo recordaré el axioma por antonomasia: Hazlo simple

Html más simple con el Selector Css por atributo

El uso de selectores por atributo, además de los beneficios en las hojas de estilos, tienen una ventaja añadida. Facilitan un marcado más simple en el Html.

Como ya tenía cargada la página de Bootstrap y el inspector de código lanzado, vuelvo a utilizarla como ejemplo:

múltiples nombres de clases <div class='col-md-3 col-md-offset-6'> </div> <div class='col-md-3 col-md-offset-3'> </div>

Como ves, sus creadores añaden un segundo nombre de clase (valor) col-md-offset-6 y col-md-offset-3 a cada div con vistas a aplicarles estilos propios y diferenciadores de cada col-md-offset-Nº.

Esta necesidad de añadir valores de clases se puede obviar teniendo en mente los selectores Css por atributo. Como vemos, en la generación de los nombres de clases los autores de Bootstrap siguen una metodología lógica. Así que podrían reducirles la clase a lo siguiente:

<div class='col-md-3-offset-6'> </div> <div class='col-md-3-offset-3'> </div>

Con este código Html podremos y deberíamos utilizar el selector de atributo con el combinador $='' que significa que termina exáctamente con la cadena de texto indicada entre las comillas:

[class$='-offset-1'] {...} [class$='-offset-2'] {...} [class$='-offset-3'] {...} [class$='-offset-4'] {...} [class$='-offset-5'] {...} [class$='-offset-6'] {...}

Selector Css por Atributo y combinadores

La especificación Selectors Level 3 [W3C Recomendation 29/09/1011] divide a los selectores Css por atributo en tres grupos. División que se mantiene en el siguiente desarrollo Selectors Level 4 [W3C Editor´s Draft 12/08/2014]

La sintaxis general y común es la siguiente: [attr='valor'], cuyos términos significan:

[ ]
El corchete de apertura y cierre identifica a este tipo de selector. Son obligados.
attr
El nombre del atributo por el que queremos seleccionar los elementos. tales como class, type, id... incluidos los atributos de autor data-algo
'valor'
La cadena o subcadena de texto que ha de tener el valor del atributo (en el html) indicado para que se le aplique la regla Css.

El uso o no de comillas dobles (" ") o simples (' ') en el valor del selector es opcional. Pero aconsejable su uso tras la aparición del identificador i que los hace case-insensitive.

Selector por atributo presente y por valor

En esta primera división de los selectores de atributo la especificación engloba los siguientes:

[attr]
Selecciona a todos los elementos que tengan declarado el atributo indicado, independientemente de que tenga o no algún valor y cuál(es) sean.
Así el selector [href] sería equivalente al selector de elemento a. Apunta a todos los enlaces (porque es obligado que tengan dicho atributo).
[attr='valor']
Selecciona cualquier elemento que tenga el atributo attr y cuyo valor sea exáctamente valor.
[att~='valor']
Representa a los elementos que. teniendo el atributo attr, su valor está formado por dos o más cadenas de texto (valores) separados por espacio en blanco y una de esas cadenas (valores) es exactamente valor.
Si el valor indicado en el selector contiene algún espacio en blanco uno dos o es una cadena vacía el selector es nulo. La regla no aplicará a ningún elemento.
[att|='valor']
Representa a los elementos cuyo atributo attr comienza exactamente por la cadena valor o por esa cadena de texto seguida de un guión medio valor-

Selector Css por subcadena textual del atributo

Junto a los anteriores, hay otro grupo de selectores Css por valor de atributo, que a diferencia de ellos, son utilizados para identificar elementos no por un valor del atributo sino por una parte o subcadena textual.

[att^='valor']
Representa a los elementos en los que uno de los valores del atributo valor comienza por el valor valor. La diferencia con el selector [att|='valor'] es que éste debe comenzar su atributo por dicho valor (estar a continuación del signo '=').
[att$='valor']
Selecciona al elemento cuyo atributo attr termina exactamente con la cadena valor. No que uno de los posibles valores (texto separado por espacio en blanco) sino el final del valor del atributo. Por ejemplo, si el valor del atributo fuese mayorvalor super no aplicaría. Debería ser super mayorvalor.
[att*='valor']
Apunta a todos los elementos cuyo atributo attr contenga la cadena valor con independencia de en qué parte del valor del atributo se encuentre.

Selector Css de atributo por espacio de nombres (namespace)

Si en tus documentos haces uso de espacios de nombres o namespace [ver wikipedia] y [css namespaces] Css también permite discriminar elementos según el "espacio de nombre" en el que se encuentre el elemento.

Selector de atributo Css por varios valores

Como el uso de espacios en blanco anula al selector y de momento (ver más abajo) no estaba contemplado el uso de comas para separar varios valor en el selector, quizás te preguntes cómo formar un selector de atributo que tenga esto presente.

Pues igual que se hace con el uso del selector de clase para aquellos elementos que tienen declaradas dos en el atributo class. Un [...] tras otro [...] y tantos como necesites:

span[hello="Marte"][goodbye="Luna"] {...}

Cadeneta de selectores que también es posible con las pseudoclases. Especialmente interesante el uso de las pseudoclases lógicas:

.universo[hello="Marte"]:not([goodbye="Luna"]) {...}

Cambios en el selector Css por Atributo

Respecto a documentos anteriores, dos son las novedades que acompañan al último desarrollo:

  1. Se plantea (consulta) la posibilidad de una sintaxis de múltiples valores separados por comas en el valor del selector: [rel ~= next, prev, up, first, last]
  2. Pese a que los lenguajes Css y Html no son case-sensitive (no diferencian entre mayúsculas y minísculas: es lo mismo 'AA' = 'Aa' = 'aA' = 'aa') hay otros que sí lo son. Así que pese a que los selectores en el ámbito de Css no distingan entre el uso de mayúsculas y minúsculas, si dicho Css se aplica a algún lenguaje case-sensitive el selector attr='valor'] no afectaría al elemento con atributo ATTR o cuyo valor fuese attr='VALOR'
    Para evitar estas situaciones, añade el uso del modificador i para solventarlo. Este modificar ha de colocarse justo antes del corchete de cierre:
[frame="hsides" i] {}

Ver el artículo "Selector atributo [case-insensitive i]"

Soporte por navegadores al Selector Css por Atributo

UNIVERSAL. No debería preocuparte a estas alturas que los IE8 y anteriores tengan alguna insuficiencia también con los selectores por atributo: [ver canIuse.com]

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: 14

  1. Buen aporte y muy bien explicado. Yo suelo usar los selectores por tipo de atributo y nombre de atributo y muy de vez en cuando, pero muy de vez en cuando también los secundarios (para elementos que pueden aumentar dinámicamente) o adyacentes. Todo depende de la estructura de la página.

    Saludos.

    ResponderEliminar
  2. Estaba pensando en esa nueva flag 'i' (case insensitive) ¿no convendría agregar también una como 'm', no ya para texto de varias líneas (porque los valores de atributo van sin salto, y si lo tienen es ignorado) sino para valores múltiples en un mismo atributo? Así se podrían usar los filtros por subcadena inicial y final en cada uno de los valores de 'class', por ejemplo.

    Ya sé que para separar en cadenas reconocibles existen los guiones, pero ¿y si yo uso camelcase? ¿no me estarían discriminando?.

    ResponderEliminar
    Respuestas
    1. Ya es posible. Como puse en el post.

      Además del uso (propuesto en forma de consulta en la especificación) de múltiples valores separados por comas tienes la opción de enlazar varios selectores, con la ventaja de que puedes usar distintos combinadores e incluso atributos:


      [class*='un'][class*='any'][data-me*='otro'] {...}

      Eliminar
    2. ah! Se me olvidaba.
      Y en caso de que en vez de ser por coincidencia (tener cierto valor o parte de él) sea por ausencia (no tenerlo), ahí está el amigo :not() para intercalarlo al gusto.

      Eliminar
    3. Preparé este ejemplo, y no sé cómo hacer para que los items con una clase que termina en "Yanky" tengan fondo verde.

      [code]
      <!DOCTYPE html>
      <html lang="es-ar">
      <head>
      <meta charset="utf-8" />
      <style type="text/css">
      [class^="Delta"] {background-color: pink; }
      [class$="Whisky"] {background-color: lightblue; }
      [class~$="Yanky"] {background-color: lime; } /*no anda, ni debería*/
      </style>
      </head>
      <body>
      <ol>
      <li class="AlfaZulu DeltaYanky">AlfaZulu DeltaYanky</li>
      <li class="BravoZulu DeltaRayoX">BravoZulu DeltaRayoX</li>
      <li class="CharlyZulu EcoWhisky">CharlyZulu EcoWhisky</li>
      <li class="FoxtrotYanky AlfaZulu">FoxtrotYanky AlfaZulu</li>
      <li class="DeltaRayoX BravoZulu">DeltaRayoX BravoZulu</li>
      <li class="EcoWhisky CharlyZulu">EcoWhisky CharlyZulu</li>
      </ol>
      </body>
      </html>
      [/code]

      Eliminar
    4. Me pillaste con las gafas recién limpias xD
      No como las tuyas :P

      Se te coló un ~ en [class~$="Yanky"]

      Eliminar
    5. En realidad no se coló, eso sería "otra forma" de filtrar en valores múltiples. Forma que nunca va a ser aceptada, es medio impresentable. Si ya incorporaron las flags, a mí me parecen mucho mejores.

      Aprovecho a hacer una sugerencia aquí, aunque no tenga que ver realmente con CSS sino con HTML5. Debe haber entre los colaboradores de este blog alguien que se maneje con expresiones regulares. No estaría mal hacer un artículo orientado al atributo 'pattern', que sí está emparentado con CSS a través de pseudos como ':required:valid' o ':invalid', y mostrar algo de su lógica.
      En principio fueron hechas para lenguajes de programación, pero como vemos, parte de su sintaxis se terminó incorporando a CSS y HTML.

      Yo conocía a varios que manejaban muy bien las RegEx en un foro donde colaboraba (había una chica que siempre me humillaba interpretándolas a primera vista, cosa que yo no podría hacer jamás), pero como no ando más por ahí no te puedo recomendar a nadie.

      Eliminar
  3. Estoy un poco atrasada en el estudio(!), dado este caso, te agradezco enormemente todo el trabajo que venís haciendo con tu blog, siempre es el más claro y conciso! Saludos!

    ResponderEliminar
  4. Disculpa... Si quisiera hacer algo, solo con CSS, como por ejemplo... Cambiar el color del fondo al hacer hover en un elemento cómo sería?

    Supongamos que tengo un HTML con la siguiente hoja de estilos

    #body{background:#fff;}
    .cambiarColor{top:0;bottom:0;left:0;right:0;margin:auto;width:15vh; height:15vh; padding:.5vh; overflow:hidden; box-sizing:border-box; position:fixed; background:#ddd; font-size:2vh;}
    .cambiarColor:hover{background:#eee;}
    .cambiarColor:hover ~ body{background:#1af;}


    Y un elemento P de clase "cambiarColor", el cual dice: Hazme "Hover" para cambiar el color del fondo

    El problema es que al aplicarlo no me funciona, no sé que estoy haciendo mal... Por lo que veo un elemento sucesor no puede afectar a un antecesor (ya lo probé con etiquetas "a", haciendo que la segunda afecte el color de la primera y tampoco funcionó, a no ser que la primera la pusiera después de la segunda, y conservando el css tal cual lo había hecho) :/ pero quisiera hacerlo, y me gustaría ver si es posible hacerlo sólo con CSS

    ResponderEliminar
    Respuestas
    1. (Perdón, quise decir body, no #body)

      Eliminar
    2. Es que no se puede (aún) modificar el formato de un elemento padre desde un hijo. Y el body es padre del párrafo, seguro.
      Vas a tener que usar javascript, porque los trucos CSS son más que nada un experimento para casos de laboratorio. Sólo "parece" que funcionan, y en este blog hay uno o dos ejemplos.

      Eliminar
    3. Jesús, como bien te indica Furoya, con CSS no hay forma de remontar el DOM. No hay un selector de precedente ni de ancestro.

      No obstante "lo que CSS no da, la imaginación lo presta".

      Ya he dedicado varios artículos a emular el selector de padre o ancestro. Sólo tienes que hacer una búsqueda en el blog por ese término y ver si alguna de las demos te es de utilidad.

      Un saludo

      Eliminar
    4. Perdón, Kseso, releo mi último párrafo en el comentario anterior y de alguna forma parece que estoy desmereciendo los aportes que en su momento hiciste con esos artículos. No era mi intención, todo lo contrario, para mí un "truco", un código creativo son muy valiosos; lo que quise advertir antes de que alguien empezara la búsqueda es que no son algo común para una página "industrial". Antes de usarlos hay que sopesar eso.

      No sé si era necesario, pero lo quería aclarar.

      Un abrazo.

      Eliminar
    5. Sí, sí, Furoya, totalmente innecesario xD =P

      Yo también uso el verbo "parecer" y otros similares como "emular" con la misma intención.

      Un saludo

      Eliminar

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