Selector de CSS "(A o B) y C"?

176

Esto debería ser simple, pero tengo problemas para encontrar los términos de búsqueda.
Digamos que tengo esto:

<div class="a c">Foo</div>
<div class="b c">Bar</div>

En CSS, ¿cómo puedo crear un selector que coincida con algo que coincida con "(.a o .b) y .c"?

Sé que podría hacer esto:

.a.c,.b.c {
  /* CSS stuff */
}

Pero, suponiendo que voy a tener que hacer mucho este tipo de lógica, con una variedad de combinaciones lógicas, ¿hay una mejor sintaxis?

Josh
fuente
Tenga cuidado si tiene que soportar Internet Explorer 6, ya que simplemente ignorará más de un nombre de clase en un selector CSS.
fforw
24
Afortunadamente, para este proyecto, puedo decirles a los usuarios de IE6 que se actualicen ellos mismos.
Josh
12
En aras de la claridad, trato de poner siempre una nueva línea después de las comas, o al menos un espacio.
ANeves
2
@ANeves +1 para nueva línea. Este es el mejor enfoque en mi opinión, especialmente cuando se usa el control de fuente.
Curt

Respuestas:

149

¿hay una mejor sintaxis?

No. El oroperador CSS ( ,) no permite agrupaciones. Es esencialmente el operador lógico de precedencia más baja en los selectores, por lo que debe usarlo .a.c,.b.c.

Matt Ball
fuente
25

Todavía no, pero existe la función experimental de :matches()pseudo-clase que hace exactamente eso:

:matches(.a .b) .c {
  /* stuff goes here */
}

Puedes encontrar más información aquí y aquí . Actualmente, la mayoría de los navegadores admiten su versión inicial :any(), que funciona de la misma manera, pero será reemplazada por :matches(). Solo tenemos que esperar un poco más antes de usar esto en todas partes (seguramente lo haré).

Codificador de metal
fuente
No es razonable culpar a IE por no implementar algo en lo que simplemente nunca pensaron y para empezar no estaba en ningún borrador. :-moz-any()y :-webkit-any()apareció mucho antes de que Mozilla lo sugiriera para los Selectores 4 (lo que lleva a su encarnación actual como :matches()).
BoltClock
1
Es igualmente irracional esperar que cualquier proveedor implemente una característica de un borrador inestable, independientemente de cuánto tiempo haya estado disponible (esto es para tener en cuenta el hecho de que Selectores 4 permanece inestable y en gran medida no implementado más de tres años después de su FPWD) .
BoltClock
@BoltClock, culparon a IE6 durante toda una década de cosas que no existían en 2001. La gente solo quiere culpar a alguien.
GetFree
Una palabra sobre las experimentales es que no desea comenzar a confiar en ellas a menos que se implemente oficialmente. Si bien podría parecer una gran solución, la posibilidad de que desaparezca es lo que personalmente me impide implementarlo en mis proyectos. Incluso hacer un seguimiento de una pseudo clase experimental no me hace sentir segura. Lo más probable es que se use en más de un lugar en el proyecto y, en caso de que tenga más de uno donde lo use, de alguna manera debe realizar un seguimiento de todo. Seguramente puede tener retrocesos y aún lograrlo, pero eso no suena limpio
Alexey Shevelyov
¿Soy el único que recibe un Uncaught DOMException: Failed to execute 'querySelector' on 'Document': ':any(.a .b)' is not a valid selector.error? 🤔
thomas
12

Si tienes esto:

<div class="a x">Foo</div>
<div class="b x">Bar</div>
<div class="c x">Baz</div>

Y solo desea seleccionar los elementos que tienen .xy ( .ao .b), podría escribir:

.x:not(.c) { ... }

pero eso es conveniente solo cuando tiene tres "subclases" y desea seleccionar dos de ellas.

Seleccionando solo una subclase (por ejemplo .a):.a.x

Seleccionar dos subclases (por ejemplo .ay .b):.x:not(.c)

Selección de las tres subclases: .x

Šime Vidas
fuente
66
Cualquier cláusula lógica del formulario a or b or c or des la misma que not(not(a) and not(b) and not(c) and not(d))'o' en realidad es solo una función de conveniencia. En teoría, debería ser posible sobrevivir sin él en todos los casos. En el caso del OP (.a or .b) and .c->:not(:not(.a):not(.b)).c
Max Murphy
2
@MaxMurphy ¿Has probado esto?
Šime Vidas
44
A partir de las cinco de la mañana, ¡sí! Tengo js que escupe lógica de primer orden, con selectores en las hojas, dando resultados como :not(:not([data-status="ACT"]):not([data-status="ISS"]):not([data-status="COR"]))[data-month="08"]. El código no es lo suficientemente limpio para la lectura pública, sin embargo, de lo contrario lo publicaría. Probé en Chrome, Safari y un teléfono Android de gama baja.
Max Murphy
2
@MaxMurphy Tiene un gran punto, pero creo que ha invocado una definición bastante torturada de "función de conveniencia". Cualquier cosa que pueda hacer una computadora digital se puede descomponer en puertas NAND, pero no llamaría al resto de la ingeniería de software "un montón de funciones de conveniencia". Las diferencias de grado se convierten rápidamente en diferencias de tipo de hecho cuando se pueden combinar construcciones.
Sarah G
1
@MaxMurphy Me costó mucho descubrir que estabas bromeando. :( La negación CSS pseudo-clase,: no (X), es una notación funcional de tomar un sencillo selector X como un argumento Coincide con un elemento que no está representado por el argumento X.. No debe contener otro selector negación . (De
Documentos de
5

No. CSS estándar no proporciona el tipo de cosas que estás buscando.

Sin embargo, es posible que desee mirar MENOS y SASS .

Estos son dos proyectos que tienen como objetivo extender la sintaxis CSS predeterminada mediante la introducción de características adicionales, que incluyen variables, reglas anidadas y otras mejoras.

Le permiten escribir código CSS mucho más estructurado, y cualquiera de ellos seguramente resolverá su caso de uso particular.

Por supuesto, ninguno de los navegadores admite su sintaxis extendida (especialmente porque los dos proyectos tienen diferentes sintaxis y características), pero lo que hacen es proporcionar un "compilador" que convierte su código MENOS o SASS en CSS estándar, que luego puede implementar en su sitio.

Spudley
fuente
En ese punto, también podría usar la impresión PHP "Content-type: text / css"
Josh