O CSS pode detectar o número de filhos de um elemento?

304

Provavelmente estou respondendo minha própria pergunta, mas estou extremamente curiosa.

Eu sei que o CSS pode selecionar filhos individuais de um pai, mas há suporte para estilizar os filhos de um contêiner, se seu pai tiver uma certa quantidade de filhos.

por exemplo

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

Sei que parece estranho, mas meu gerente me pediu para verificar, não encontrei nada sozinho, então decidi mudar para SO antes de encerrar a pesquisa.

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

Respostas:

695

Esclarecimento:

Por causa de uma redação anterior na pergunta original, alguns cidadãos de SO levantaram preocupações de que essa resposta pudesse ser enganosa. Observe que, no CSS3, os estilos não podem ser aplicados a um nó pai com base no número de filhos que ele possui. No entanto, os estilos podem ser aplicados aos nós filhos com base no número de irmãos que eles têm.


Resposta original:

Incrivelmente, isso agora é possível apenas no 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%;
}

O truque é selecionar o primeiro filho quando ele também for o nono-desde o último filho. Isso efetivamente seleciona com base no número de irmãos.

O crédito por essa técnica é dado a André Luís (descoberto) e Lea Verou (refinado).

Você não ama CSS3? 😄

Exemplo de CodePen:

Fontes:

Matthemattics
fonte
7
Muito conveniente. Eu escrevi um mixin SASS que faz uso desta técnica: codepen.io/anon/pen/pJeLdE?editors=110
SimpleJ
1
@IanSteffy Acabei de testar isso no Chrome 45.0.2454.85 (64 bits) e funciona bem…?
Matthemattics
2
Se funcionar no codepen, mas não no meu projeto, é definitivamente minha culpa. Foi mal. Esta resposta está correta! Correto, eu digo!
Ian S
3
Pode ser bom acrescentar por que isso funciona, para pessoas que não estão acostumadas a vários pseudo-seletores (como eu era até agora;). O que está acontecendo aqui é que isso seleciona o filho que é ao mesmo tempo filho x desde o início / início e filho y desde o final. E, portanto, isso só seleciona algo se houver exatamente x + y filhos.
Legolas
7
Observe que, em vez de :first-child:nth-last-child(1)você também pode usar :only-child.
Adam Reis
40

Não. Bem, na verdade não. Existem alguns seletores que podem te aproximar um pouco, mas provavelmente não funcionará no seu exemplo e não possui a melhor compatibilidade com o navegador.

:only-child

O :only-childé um dos poucos seletores de contagem verdadeiros, no sentido de que é aplicado apenas quando há um filho do pai do elemento. Usando seu exemplo idealizado, ele age como children(1)provavelmente faria.

:nth-child

O :nth-childseletor pode realmente levá-lo aonde você quer ir, dependendo do que realmente deseja fazer. Se você quiser estilizar todos os elementos, se houver 8 filhos, não terá sorte. Se, no entanto, você deseja aplicar estilos aos elementos 8 e posterior, tente o seguinte:

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

Infelizmente, essas provavelmente não são as soluções que você está procurando. No final, você provavelmente precisará usar algumas habilidades de Javascript para aplicar os estilos com base na contagem - mesmo que você use um deles, precisará verificar com atenção a compatibilidade do navegador antes de usar uma linguagem pura. Solução CSS.

W3 CSS3 Spec em pseudo-classes

EDIT Eu li sua pergunta um pouco diferente - existem algumas outras maneiras de estilizar os pais , não os filhos. Deixe-me jogar alguns outros seletores do seu jeito:

:empty e :not

Isso estiliza elementos que não têm filhos. Não é útil por si só, mas quando emparelhado com o :notseletor, você pode estilizar apenas os elementos que têm filhos:

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

Você não pode contar quantas crianças estão disponíveis com CSS puro aqui, mas é outro seletor interessante que permite fazer coisas legais.

derekerdmann
fonte
É importante notar a pergunta original foi editado, tornando a inicial "Não" um pouco enganosa (apenas fyi 😛)
Matthemattics
18

NOTA: Esta solução retornará os filhos de conjuntos de determinados comprimentos, não o elemento pai, como você pediu. Felizmente, ainda é útil.

Andre Luis criou um método: http://lea.verou.me/2011/01/styling-children-based-on-their-number-with-css3/ Infelizmente, ele funciona apenas no IE9 e acima.

Essencialmente, você combina: enésimo filho () com outras pseudo classes que lidam com a posição de um elemento. Essa abordagem permite especificar elementos de conjuntos de elementos com comprimentos específicos .

Por exemplo, :nth-child(1):nth-last-child(3)corresponde ao primeiro elemento de um conjunto e também é o terceiro elemento do final do conjunto. Isso faz duas coisas: garante que o conjunto tenha apenas três elementos e que tenhamos o primeiro dos três. Para especificar o segundo elemento do conjunto de três elementos, nós usaríamos :nth-child(2):nth-last-child(2).


Exemplo 1 - Selecione todos os elementos da lista se o conjunto tiver três 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%;
}

Exemplo 1 alternativa de Lea Verou:

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


Exemplo 2 - segmente o último elemento do conjunto com três elementos da lista:

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

Exemplo 2 alternativa:

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


Exemplo 3 - segmente o segundo elemento do conjunto com quatro elementos da lista:

li:nth-child(2):nth-last-child(3) {
    /* I'm the second of four */
}
ifugu
fonte
1
novamente, este é o número de irmãos, não crianças
TMS
@TMS ver edição de resposta aceito - pergunta do OP foi desastradamente formulada
ifugu
Esta abordagem é perfeito para quando cada elemento precisa ser decorados de forma diferente com base na sua posição na lista, por exemplo, para obter transforma mesmo circulares: li:nth-child(3):nth-last-child(1) { transform: rotate(120deg); } li:nth-child(2):nth-last-child(2) { transform: rotate(240deg); }e assim por diante ...
Greg Smith
11

Trabalhando com a solução de Matt, usei a seguinte implementação do 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);
    }
  }

Isso permite expandir rapidamente o número de itens.

mwtidd
fonte
4
Em vez disso, você pode facilmente usar o Flexbox…
Michał Miszczyszyn
6

sim, podemos fazer isso usando o enésimo filho assim

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

Isso fará com que o filho da 8ª divisão avante fique vermelho. Espero que isto ajude...

Além disso, se alguém disser "ei, eles não podem ser estilizados usando CSS, use JS !!!" duvide deles imediatamente. CSS é extremamente flexível hoje em dia

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

No exemplo, os 7 primeiros filhos são azuis e 8 em diante são vermelhos ...

AlanFoster
fonte
1
Talvez adicione uma nota sobre a infeliz falta de apoio ?
Benesch
2
Eu não acho que isso é exatamente o que Brodie está perguntando - isso estilizará os filhos após uma determinada quantidade, mas não será possível selecionar o elemento ancestral / contendo com base no número de filhos.
Ben Hull
Esta é realmente uma informação muito boa, porém, graças a Alan, mas Bee está certa, eu estava tentando dizer "se um elemento tem tantos filhos para nós desse estilo". os primeiros 7 seriam solitários e nus.
Brodie
@primatology - O único navegador que não suporta o enésimo filho é o IE <9. Todos os outros têm apoiado duas versões anteriores ou mais.
Rob
-1 Isso não fará com que div child fique vermelho, isso fará com que div div fique vermelho com base no número de irmãos ! Não está relacionado ao filho de div de forma alguma!
TMS
5

Se você for fazer isso em CSS puro (usando scss), mas tiver diferentes elementos / classes dentro da mesma classe pai, poderá usar esta versão !!

  &: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 Sebastian Contreras Aceve
fonte
-1

Não, não há nada como isso no CSS. No entanto, você pode usar o JavaScript para calcular o número de filhos e aplicar estilos.

Niet, o Escuro Absol
fonte
1
@ Lübnah Você pode explicar por que não é verdade?
Gabriel Santos