15

Should this work am I going crazy?

.project.work:first-child:before {
  content: 'Projects';
}
.project.research:first-child:before {
  content: 'Research';
}
<div class="project work">
  <p>abcdef</p>
</div>
<div class="project work">
  <p>abcdef</p>
</div>
<div class="project work">
  <p>abcdef</p>
</div>
<div class="project research">
  <p>abcdef</p>
</div>

projects:first-child works fine, research:first-child doesn't stick. Any ideas?

Demo It doesn't work, but whats the best way to achieve this?

Mo.
  • 26,306
  • 36
  • 159
  • 225
uriah
  • 2,485
  • 5
  • 28
  • 40

3 Answers3

15

:first-child only selects the first child of its parent. Nothing else.

As mentioned in a few of my other answers on the site (1 2 3 4), there is no :first-of-class pseudo-class. If you are looking to apply styles to the first of each class of your div elements, a solution is to apply the styles to all children of that class, and a general sibling selector to undo the styles from subsequent siblings.

Your CSS would then look like this:

.project.work:before {
    content: 'Work';
}

.project.research:before {
    content: 'Research';
}

.project.work ~ .project.work:before, 
.project.research ~ .project.research:before {
    content: none;
}
Community
  • 1
  • 1
BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
  • There isn't a way in pure CSS to apply this dynamically (i.e. without having to hardcode the extra classes if you decide to add more later on), though. Once you add more classes, you have to add them to your CSS manually in this pattern. – BoltClock Dec 16 '11 at 14:49
  • Perfect, apply to all and undo siblings. Thanks @boltclock So if I if have add another class like `.project.photography` it wont work? – uriah Dec 16 '11 at 14:51
  • [fiddle](http://jsfiddle.net/VvwYD/3/) It repeats the **Photo** :first-child have I done something wrong? – uriah Dec 16 '11 at 14:57
  • @uriah: Your last selector should be `.project.work ~ .project.work:before, .project.photo ~ .project.photo:before, .project.research ~ .project.research:before`, you had an extra `.project.work ~` in the Photo part. The `~` selector doesn't limit itself to adjacent siblings, unlike `+`, so you don't need the extra work selector. – BoltClock Dec 16 '11 at 14:59
  • Sorry, should [this](http://jsfiddle.net/VvwYD/4/) work? Shouldn't Photo only appear once? – uriah Dec 16 '11 at 15:03
  • @uriah: Oops, you also have to remove the first `:before`. This is why I hate having to write long selectors :) [Updated fiddle.](http://jsfiddle.net/VvwYD/5/) – BoltClock Dec 16 '11 at 15:04
  • my mistake too, I should have seen that. Thanks! Saved me a headache, do you know what levels of IE support this method? – uriah Dec 16 '11 at 15:06
  • @uriah: It's a lot harder to get it wrong if you split the selector into multiple lines: http://jsfiddle.net/thirtydot/VvwYD/7/. This will work in IE8 and greater. It won't work in IE7 due to the use of `:before`. – thirtydot Dec 16 '11 at 15:07
  • IE8 is fine, many thanks to @boltclock for explaining everything to clearly. – uriah Dec 16 '11 at 15:15
  • @T.J. Crowder: This is, like, the fourth time I've used this technique to answer a question. I feel like I need a canonical answer to point future questions to... – BoltClock Dec 16 '11 at 15:36
  • :-) (I've felt the same way about some JavaScript topics.) This add-to-all-then-remove-from-siblings trick is *definitely* going in my toolkit. – T.J. Crowder Dec 16 '11 at 15:38
  • @T.J. Crowder: Found an old question that could use a bit of help, so I chipped in :) http://stackoverflow.com/a/8539107/106224 – BoltClock Dec 16 '11 at 19:28
1

From the specification:

Same as :nth-child(1). The :first-child pseudo-class represents an element that is the first child of some other element.

.project.research is not the first child of its parent.

thirtydot
  • 224,678
  • 48
  • 389
  • 349
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
0

I believe you want this CSS:

.project.work p:first-child:before {content:'Projects';}
.project.research p:first-child:before {content:'Research';}

or

.project.work > p:first-child:before {content:'Projects';}
.project.research > p:first-child:before {content:'Research';}

Updated fiddle

That matches the first child of an element with the classes "project" and "work" (or "project" and "research"). You don't have to use p:first-child if it may not be a p element, you could use *:first-child instead.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Thanks! I would only like to select the first of its kind and apply the CSS not every element. This select all of them. – uriah Dec 16 '11 at 14:47
  • @uriah: Ah. I don't think you can do that without changing your markup. I don't think even CSS3 selectors have a way of selecting the first element in a container with a given pair of class names. Even `:first-of-type` would apply to the element type, irrespective of class. – T.J. Crowder Dec 16 '11 at 14:58