¿Puede CSS detectar la cantidad de hijos que tiene un elemento?

304

Probablemente estoy respondiendo mi propia pregunta, pero tengo mucha curiosidad.

Sé que CSS puede seleccionar hijos individuales de un padre, pero ¿hay soporte para diseñar los hijos de un contenedor, si su padre tiene una cierta cantidad de hijos?

por ejemplo

container:children(8) {
  // style the parent this way if there are 8 children
}

Sé que suena extraño, pero mi gerente me pidió que lo revisara, no encontré nada por mi cuenta, así que decidí recurrir a SO antes de finalizar la búsqueda.

Brodie
fuente
2
Consulta de cantidad SCSS Mixin: codepen.io/jakob-e/pen/wgGpeP
Jakob E

Respuestas:

695

Aclaración:

Debido a una frase anterior en la pregunta original, algunos ciudadanos de SO han expresado su preocupación de que esta respuesta pueda ser engañosa. Tenga en cuenta que, en CSS3, los estilos no se pueden aplicar a un nodo primario en función del número de elementos secundarios que tiene. Sin embargo, los estilos se pueden aplicar a los nodos secundarios en función de la cantidad de hermanos que tengan.


Respuesta original:

Increíblemente, esto ahora es posible únicamente en CSS3.

/* one item */
li:first-child:nth-last-child(1) {
/* -or- li:only-child { */
    width: 100%;
}

/* two items */
li:first-child:nth-last-child(2),
li:first-child:nth-last-child(2) ~ li {
    width: 50%;
}

/* three items */
li:first-child:nth-last-child(3),
li:first-child:nth-last-child(3) ~ li {
    width: 33.3333%;
}

/* four items */
li:first-child:nth-last-child(4),
li:first-child:nth-last-child(4) ~ li {
    width: 25%;
}

El truco es seleccionar el primer hijo cuando también es el enésimo desde el último hijo. Esto selecciona efectivamente en función del número de hermanos.

El crédito por esta técnica es para André Luís (descubierto) y Lea Verou (refinada).

¿No te encanta CSS3? 😄

Ejemplo de CodePen:

Fuentes:

Matthemattics
fuente
77
Muy útil. Escribí un mix de SASS que hace uso de esta técnica: codepen.io/anon/pen/pJeLdE?editors=110
SimpleJ
1
@ IanSteffy Acabo de probar esto en Chrome 45.0.2454.85 (64 bits) y funciona bien ...?
Matthemattics
2
Si funciona en codepen pero no con mi proyecto, entonces definitivamente es mi culpa. Culpa mía. Esta respuesta es correcta! ¡Correcto, digo!
Ian S
3
Podría ser bueno agregar por qué esto funciona, para personas que no están acostumbradas a múltiples pseudo-selectores (como lo estaba hasta ahora;). Lo que está sucediendo aquí es que esto selecciona al niño que es al mismo tiempo niño x desde el inicio / arriba y niño y desde el final. Y así, esto solo selecciona algo si hay exactamente x + y hijos.
Legolas
77
Tenga en cuenta que en lugar de :first-child:nth-last-child(1)usted también puede usar :only-child.
Adam Reis
40

No. Bueno, en realidad no. Hay un par de selectores que pueden acercarte un poco, pero probablemente no funcionarán en tu ejemplo y no tienen la mejor compatibilidad del navegador.

:only-child

Este :only-childes uno de los pocos selectores de conteo verdadero en el sentido de que solo se aplica cuando hay un elemento secundario del elemento primario del elemento. Usando su ejemplo idealizado, actúa como children(1)probablemente lo haría.

:nth-child

El :nth-childselector podría llevarte a donde quieres ir dependiendo de lo que realmente estés buscando hacer. Si desea diseñar todos los elementos si hay 8 niños, no tiene suerte. Sin embargo, si desea aplicar estilos a los elementos 8 y posteriores, intente esto:

p:nth-child( n + 8 ){
    /* add styles to make it pretty */
}

Desafortunadamente, estas probablemente no son las soluciones que estás buscando. Al final, es probable que necesites usar un poco de magia de Javascript para aplicar los estilos basados ​​en el recuento; incluso si usaras uno de estos, deberías analizar detenidamente la compatibilidad del navegador antes de utilizar un sistema puro. Solución CSS

W3 CSS3 Spec en pseudo-clases

EDITAR Leí su pregunta de manera un poco diferente: hay otras dos formas de diseñar a los padres , no a los hijos. Permítanme lanzar algunos otros selectores en su dirección:

:empty y :not

Esto diseña elementos que no tienen hijos. No es tan útil por sí solo, pero cuando se combina con el :notselector, puede diseñar solo los elementos que tienen elementos secundarios:

div:not(:empty) {
    /* We know it has stuff in it! */
}

No puede contar cuántos niños están disponibles con CSS puro aquí, pero es otro selector interesante que le permite hacer cosas interesantes.

Derekerdmann
fuente
Vale la pena señalar que la pregunta original fue editada, haciendo que el "No" inicial sea un poco engañoso (solo para tu información)
Matthemattics
18

NOTA: Esta solución devolverá los elementos secundarios de conjuntos de ciertas longitudes, no el elemento principal como usted ha pedido. Con suerte, sigue siendo útil.

Andre Luis ideó un método: http://lea.verou.me/2011/01/styling-children-based-on-their-number-with-css3/ Desafortunadamente, solo funciona en IE9 y versiones posteriores.

Básicamente, combina: nth-child () con otras pseudo clases que se ocupan de la posición de un elemento. Este enfoque le permite especificar elementos de conjuntos de elementos con longitudes específicas .

Por ejemplo, :nth-child(1):nth-last-child(3)coincide con el primer elemento de un conjunto y al mismo tiempo es el tercer elemento desde el final del conjunto. Esto hace dos cosas: garantiza que el conjunto solo tiene tres elementos y que tenemos el primero de los tres. Para especificar el segundo elemento del conjunto de tres elementos, usaríamos :nth-child(2):nth-last-child(2).


Ejemplo 1: seleccione todos los elementos de la lista si set tiene tres elementos:

li:nth-child(1):nth-last-child(3),
li:nth-child(2):nth-last-child(2),
li:nth-child(3):nth-last-child(1) {
    width: 33.3333%;
}

Ejemplo 1 alternativa de Lea Verou:

li:first-child:nth-last-child(3),
li:first-child:nth-last-child(3) ~ li {
    width: 33.3333%;
}


Ejemplo 2: objetivo del último elemento del conjunto con tres elementos de lista:

li:nth-child(3):last-child {
    /* I'm the last of three */
}

Ejemplo 2 alternativa:

li:nth-child(3):nth-last-child(1) {
    /* I'm the last of three */
}


Ejemplo 3: objetivo del segundo elemento del conjunto con cuatro elementos de lista:

li:nth-child(2):nth-last-child(3) {
    /* I'm the second of four */
}
ifugu
fuente
1
de nuevo, este es el número de hermanos, no niños
TMS
@TMS ver la edición de la respuesta aceptada: la pregunta del OP se formuló incómodamente
ifugu
Este enfoque es perfecto para cuando cada elemento necesita un estilo diferente en función de su posición en la lista, por ejemplo, para obtener incluso transformaciones circulares: li:nth-child(3):nth-last-child(1) { transform: rotate(120deg); } li:nth-child(2):nth-last-child(2) { transform: rotate(240deg); }y así sucesivamente ...
Greg Smith
11

Trabajando fuera de la solución de Matt, utilicé la siguiente implementación de Compass / SCSS.

@for $i from 1 through 20 {
    li:first-child:nth-last-child( #{$i} ),
    li:first-child:nth-last-child( #{$i} ) ~ li {
      width: calc(100% / #{$i} - 10px);
    }
  }

Esto le permite expandir rápidamente la cantidad de elementos.

mwtidd
fuente
44
En lugar de esto, podrías usar Flexbox fácilmente ...
Michał Miszczyszyn
6

sí, podemos hacer esto usando nth-child así

div:nth-child(n + 8) {
    background: red;
}

Esto hará que el octavo niño div se vuelva rojo. Espero que esto ayude...

Además, si alguien dice "oye, no se puede hacer con estilo usando css, ¡usa JS!" dudar de ellos de inmediato. CSS es extremadamente flexible hoy en día

Ejemplo :: http://jsfiddle.net/uWrLE/1/

En el ejemplo, los primeros 7 niños son azules, luego 8 en adelante son rojos ...

AlanFoster
fuente
1
¿Quizás agregar una nota sobre la desafortunada falta de apoyo ?
benesch
2
No creo que esto sea exactamente lo que Brodie está preguntando: esto estilizará a los niños después de una cantidad determinada, pero no puede seleccionar el elemento ancestro / que contiene en función del número de sus hijos.
Ben Hull
Sin embargo, esta es realmente una información bastante buena, gracias Alan, pero la abeja tiene razón, estaba tratando de decir "si un elemento tiene tantos niños con este estilo" Si no me equivoco, su método daría estilo al octavo niño, pero el Los primeros 7 estarían solos y desnudos.
Brodie
@primatology: el único navegador que no admite nth-child es IE <9. Todos los demás lo han estado apoyando dos versiones atrás o más.
Rob el
-1 ¡Esto no hará que el div div sea rojo, sino que hará que el div rojo se base en su número dentro de sus hermanos ! ¡No está relacionado con el hijo de div de ninguna manera!
TMS
5

¡Si lo vas a hacer en CSS puro (usando scss) pero tienes diferentes elementos / clases dentro de la misma clase padre, puedes usar esta versión!

  &:first-of-type:nth-last-of-type(1) {
    max-width: 100%;
  }

  @for $i from 2 through 10 {
    &:first-of-type:nth-last-of-type(#{$i}),
    &:first-of-type:nth-last-of-type(#{$i}) ~ & {
      max-width: (100% / #{$i});
    }
  }
Juan Sebastián Contreras Aceve
fuente
-1

No, no hay nada como esto en CSS. Sin embargo, puede usar JavaScript para calcular el número de hijos y aplicar estilos.

Niet the Dark Absol
fuente
1
@ Lübnah ¿Puedes explicar por qué no es cierto?
Gabriel Santos