1

This should be a simple thing but I can't seem to find what I'm after. I've got a parent div with sub-parents and children inside.

<div class="parent">
  <div class="subparent1">
    <div class="foo">foo1 </div>
    <div class="bar">bar1 </div>
  </div>
  <div class="subparent2"> 
    <div class="foo">foo2 </div>
  </div>
  <div class="subparent3">
    <div class="bar">bar2 </div>
    <div class="foo">foo3 </div>
    <div class="bar">bar3 </div>
  </div>
</div>

I want to hide all '.foo' classes apart from the first one. How do I use CSS3 to select all the rest of '.foo' apart from the first?

PS -- number of '.foo' is dynamic and will change.

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
Allen S
  • 3,471
  • 4
  • 34
  • 46
  • `.parent .foo {display:none;}` and `.parent .foo:first {display:block;}` ? – mshsayem Feb 12 '13 at 08:55
  • @mshsayem: There is no `:first` in CSS. – BoltClock Feb 12 '13 at 08:56
  • oh i see; in that case: `.parent > .foo {display:none;}` and `.parent>.foo:first-of-type {display:block;}` ? – mshsayem Feb 12 '13 at 09:03
  • @mshsayem: That will indeed work, but BoltClock's solution is much simpler and will also work in nasty old browsers like IE7/8. Your idea will result in all `.foo` being hidden in browsers that don't support CSS3 selectors. – thirtydot Feb 12 '13 at 09:09
  • @thirtydot: That won't work as intended in modern browsers anyway - `:first-of-type` doesn't mean first of class. You probably already know this, but for other readers, see [this answer](http://stackoverflow.com/questions/2717480/css-selector-for-first-element-with-class/8539107#8539107) for an explanation. – BoltClock Feb 12 '13 at 09:28
  • @BoltClock: It did "work" due to `.foo` being the first `div` anyway, but yeah. I'm bad. – thirtydot Feb 12 '13 at 09:37

1 Answers1

3

A situation like this depends on prior knowledge of the HTML structure; there's no way to do it using CSS alone without having predictable HTML, because CSS doesn't have the ability to select the first grandchild of a certain kind, only the first child.

For example, if you know that the first .foo will always occur in the first subparent, you may be able to get away with selecting any .foo to display as a block, then selecting all subsequent subparents and .foos using the general sibling combinator ~ and hiding them:

.parent > .subparent1 > .foo {
    display: block;
}

.parent > .subparent1 > .foo ~ .foo, /* .foo after the first in .subparent1 */
.parent > .subparent1 ~ div > .foo { /* .foo in subparents after .subparent1 */
    display: none;
}

If .subparent1 may not contain any .foo elements at all, and you want to select the first very .foo regardless of its subparent, I don't think it's possible with CSS selectors alone. You may have to find a different way, e.g. by assigning an extra class to the first .foo since it's dynamically generated, or using JavaScript to apply styles instead.

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
  • Thank you very much and that works, but now I have a different problem. What if the '.parent' class has subparents that contains '.foo'? http://jsfiddle.net/kucF5/ – Allen S Feb 12 '13 at 09:08
  • @user1775598: Do you want to hide all `.foo` except foo1? Perhaps you should edit your question or post a new one. – BoltClock Feb 12 '13 at 09:12
  • And I've edited my answer. Unfortunately your situation is much more complicated and may not always have a pure CSS solution. I've explained it in my answer. – BoltClock Feb 12 '13 at 09:26
  • Thank you very much - fortunately in this situation I know the name of the subparent which will always have the child in it. I tried your solution and it worked, thanks! – Allen S Feb 12 '13 at 19:41