Selector Css por valor de Atributo: simplifica la hoja de estilos y el Html 23.2.16
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
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.
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:
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:
<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 atributosde 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 elementoa
. 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áctamentevalor
. - [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 exactamentevalor
.
Si el valor indicado en el selector contiene algún espacio en blancouno 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 cadenavalor
o por esa cadena de texto seguida de un guión mediovalor-
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 valorvalor
. 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 cadenavalor
. 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 fuesemayorvalor super
no aplicaría. Debería sersuper mayorvalor
. - [att*='valor']
- Apunta a todos los elementos cuyo atributo
attr
contenga la cadenavalor
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:
- 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]
- 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 lenguajecase-sensitive
el selectorattr='valor']
no afectaría al elemento con atributoATTR
o cuyo valor fueseattr='VALOR'
Para evitar estas situaciones, añade el uso del modificadori
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]
Kseso
the obCSServer ᛯ 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 Kseso
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.
ResponderEliminarSaludos.
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.
ResponderEliminarYa sé que para separar en cadenas reconocibles existen los guiones, pero ¿y si yo uso camelcase? ¿no me estarían discriminando?.
Ya es posible. Como puse en el post.
EliminarAdemá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'] {...}
ah! Se me olvidaba.
EliminarY 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.
Preparé este ejemplo, y no sé cómo hacer para que los items con una clase que termina en "Yanky" tengan fondo verde.
Eliminar[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]
Me pillaste con las gafas recién limpias xD
EliminarNo como las tuyas :P
Se te coló un ~ en [class~$="Yanky"]
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.
EliminarAprovecho 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.
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!
ResponderEliminarDisculpa... 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?
ResponderEliminarSupongamos 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
(Perdón, quise decir body, no #body)
EliminarEs 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.
EliminarVas 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.
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.
EliminarNo 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
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.
EliminarNo sé si era necesario, pero lo quería aclarar.
Un abrazo.
Sí, sí, Furoya, totalmente innecesario xD =P
EliminarYo también uso el verbo "parecer" y otros similares como "emular" con la misma intención.
Un saludo