CSS :before and :first-child combined

Css

Css Problem Overview


I'm using the following code to add separators between my menu items:

#navigation_center li:before {

	content: "| ";
	color: #fff;

}

Now I want the first item not to have a separator in front of it, so I figured out the following code:

#navigation_center li:before:first-child {

	content: none;

}

but that's not doing anything. Is it possible to combine :before and :first-child?

Css Solutions


Solution 1 - Css

Try

#navigation_center li:first-child:before {
    content: '';
}

Edit: I wanted to expand on this answer with comments made by FelipeAls. The original question used :first which is not a valid CSS selector. Instead, use :first-child. Also the order of the pseudo-selectors is important. The first child selector must come first.

I tend to think of :before as a kind of modifier to a selector. It does not actually select an element only the space just before the selected element.

Solution 2 - Css

Although hradac's answer should do the trick i thought it would be best to run through some possible permutations to help newcommers.

.works:first-child:before
{
	color: green;
	content: 'working ';
}
.works:not(:first-child):after
{
	color: green;
	content: ' is working';
}


.broken:before:first-child
{
	color: red;
	content: 'this will never show up';
}
.broken:after:not(:first-child)
{
	color: red;
	content: 'and this will not show up either';
}

works:
<div>
	<div class='works'>
	 something
	</div>
	<div class='works'>
	 something
	</div>
	<div class='works'>
	 something
	</div>
</div>
<hr/>
broken:
<div>
	<div class='broken'>
	 something
	</div>
	<div class='broken'>
	 something
	</div>
	<div class='broken'>
	 something
	</div>
</div>

Let's take this apart:

  • Three div.works are inside a div

  • Three div.broken are also inside a div

  • The first rule of CSS adds a green text "working " before. It does so by selecting the first-child and then selecting the empty space right before it.

  • The second rule adds " is working" after each block that comes after first, by analogy it first selects each block that doesn't fall under the first-child definition, and then selects the empty space before them.

  • The following two rules, will not find a block to attack themselves to. The :before:first-child attempts to select an empty space, but then tests if it is a first-child and it is not (since technically it's not yet in the DOM tree), the similar problem is with :not(:first-child).

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJeffreyView Question on Stackoverflow
Solution 1 - CsshradacView Answer on Stackoverflow
Solution 2 - Cssv010dyaView Answer on Stackoverflow