Aplicar estilos CSS a un elemento en función de sus elementos secundarios

203

¿Es posible definir un estilo CSS para un elemento, que solo se aplica si el elemento coincidente contiene un elemento específico (como elemento secundario directo)?

Creo que esto se explica mejor con un ejemplo.

Nota : Estoy tratando de diseñar el elemento primario , dependiendo de los elementos secundarios que contiene.

<style>
  /* note this is invalid syntax. I'm using the non-existing
   ":containing" pseudo-class to show what I want to achieve. */
  div:containing div.a { border: solid 3px red; }
  div:containing div.b { border: solid 3px blue; }
</style>

<!-- the following div should have a red border because
     if contains a div with class="a" -->
<div>
  <div class="a"></div>
</div>

<!-- the following div should have a blue border -->
<div>
  <div class="b"></div>
</div>

Nota 2 : Sé que puedo lograr esto usando JavaScript, pero me preguntaba si esto es posible usando algunas características CSS desconocidas (para mí).

M4N
fuente
1
Es posible que desee actualizar la pregunta para indicar, tal vez con texto en negrita parpadeante, que está tratando de diseñar el div PADRE, no sus hijos. Sé que la información está en la pregunta en sí, pero a menos que desee obtener un montón de respuestas incorrectas, probablemente valga la pena el esfuerzo.
Seth Petry-Johnson
Gracias @Seth. Traté de mejorar el título y el texto de la pregunta. Edite la pregunta si cree que aún no está clara.
M4N
3
posible duplicado de ¿Hay un selector padre CSS?
James Donnelly
Este es el ejemplo perfecto de por qué este tipo de soporte en CSS sería ideal: ol < li:nth-child(n+10) { margin-left: 2rem; } ol < li:nth-child(n+100) { margin-left: 3rem; } ol < li:nth-child(n+1000) { margin-left: 4rem; }en un mundo ideal, esto aumentaría el margen del oldependiente en la cantidad de lihijos contenidos para que el margen de la izquierda solo sea tan ancho como sea posible. necesitaba ser.
Jonmark Weber

Respuestas:

124

Hasta donde sé, diseñar un elemento primario basado en el elemento secundario no es una característica disponible de CSS. Es probable que necesite secuencias de comandos para esto.

Sería maravilloso si pudieras hacer algo como div[div.a]odiv:containing[div.a] como dijiste, pero esto no es posible.

Es posible que desee considerar mirar jQuery . Sus selectores funcionan muy bien con tipos 'que contienen'. Puede seleccionar el div, en función de su contenido secundario y luego aplicar una clase CSS al padre, todo en una línea.

Si usa jQuery, algo similar podría funcionar (no probado pero la teoría está ahí):

$('div:has(div.a)').css('border', '1px solid red');

o

$('div:has(div.a)').addClass('redBorder');

combinado con una clase CSS:

.redBorder
{
    border: 1px solid red;
}

Aquí está la documentación para el selector jQuery "tiene" .

KP.
fuente
15
Nota :hasal margen : para un mejor rendimiento, la página de jQuery doc para el selector aconseja utilizar el .has()método ( api.jquery.com/has ) => aplicado a la pregunta actual que daría, por ejemplo$('div').has('div.a').css('border', '1px solid red');
Frosty Z
Para que esto funcione, habría que utilizar observador mutación, a comprobado si el niño lo cambió de estado ...
Leyendas
Esto realmente no responde a la pregunta que es "¿Hay alguna manera de hacer esto con CSS". Establece claramente: "Sé que puedo lograr esto usando javascript, pero me preguntaba si esto es posible usando algunas características CSS desconocidas (para mí)".
SunshinyDoyle
developer.mozilla.org/en-US/docs/Web/CSS/:has , creo que este :hasselector puede funcionar pero está en versión borrador y ningún navegador lo admite.
AliF50
62

Básicamente no. Lo siguiente sería lo que buscabas en teoría:

div.a < div { border: solid 3px red; }

Lamentablemente no existe.

Hay algunos relatos en la línea de "por qué demonios no". Una bien desarrollada por Shaun Inman es bastante buena:

http://www.shauninman.com/archive/2008/05/05/css_qualified_selectors

Justin Wignall
fuente
34
solo una actualización 8 años después: todavía no hay soporte para este método selector.
Kraang Prime
1
Hay un borrador de trabajo para esta característica en forma de :has()pseudo-clase, pero solo podremos usarlo en CSS4. A partir de ahora (finales de 2019), JS sigue siendo la única forma de lograr esta funcionalidad.
zepp.lee
Creo que esto no habilitará los estilos CSS, aún necesitará JavaScript para usar el selector. ¿A menos que esto haya cambiado?
Justin Wignall
3
¿9 años y piensan que esta característica es innecesaria?
Loi Nguyen Huynh
1

Además de la respuesta de @ kp:

Estoy lidiando con esto y, en mi caso, tengo que mostrar un elemento secundario y corregir la altura del objeto principal en consecuencia (el dimensionamiento automático no funciona en un encabezado de arranque por alguna razón, no tengo tiempo para depurar) .

Pero en lugar de usar JavaScript para modificar el elemento primario, creo que agregaré dinámicamente una clase CSS al elemento primario y mostraré CSS de manera selectiva a los elementos secundarios en consecuencia. Esto mantendrá las decisiones en la lógica y no se basará en un estado CSS.

tl; dr; aplicar los estilos ay bal padre <div>, no al niño (por supuesto, no todos podrán hacerlo; es decir, los componentes angulares toman sus propias decisiones).

<style>
  .parent            { height: 50px; }
  .parent div        { display: none; }
  .with-children     { height: 100px; }
  .with-children div { display: block; }
</style>

<div class="parent">
  <div>child</div>
</div>

<script>
  // to show the children
  $('.parent').addClass('with-children');
</script>
Mauricio Morales
fuente
0

En mi caso, tuve que cambiar el relleno de celda de un elemento que contenía una casilla de entrada para una tabla que se representaba dinámicamente con DataTables:

<td class="dt-center">
    <input class="a" name="constCheck" type="checkbox" checked="">
</td>

Después de implementar el siguiente código de línea dentro de la función initComplete , pude producir el relleno correcto, que solucionó la visualización de las filas con una altura anormalmente grande

 $('tbody td:has(input.a)').css('padding', '0px');

Ahora, puede ver que los estilos correctos se están aplicando al elemento padre:

<td class=" dt-center" style="padding: 0px;">
    <input class="a" name="constCheck" type="checkbox" checked="">
</td>

Esencialmente, esta respuesta es una extensión de la respuesta de @ KP, pero cuanta más colaboración implemente esto, mejor. En resumen, ¡espero que esto ayude a alguien más porque funciona! Por último, ¡muchas gracias @KP por guiarme en la dirección correcta!

millas
fuente