Use CSS Sibling Selector Combinators in lieu of :nth-child for IE8 Support

Wow just the title of this blog post is a mouthful.  Just wait, it will get worse.  This post was inspired by one of my students who wanted to hide the second and third search scopes (Result Sources in SharePoint 2013) in the drop down in the SharePoint user interface AND needed to provide support for IE8. Using CSS this can be done really quickly.

To make things easier, I will refer to the search scopes/result sources as just “search scopes”.

Sample problem: Hide a few options in the search scope drop down

If you use a browser inspector tool like Firebug, you will see that the HTML source code for the drop down box is straightforward but lacks unique identifiers for each scope:

<div id="ctl00_PlaceHolderSearchArea_SmallSearchInputBox1_csr_NavDropdownList" class="ms-qSuggest-list" style="width: 249px;">
	<div class="ms-qSuggest-listItem">Everything</div>
	<div class="ms-qSuggest-listItem">People</div>
	<div class="ms-qSuggest-listItem">Conversations</div>
	<div class="ms-qSuggest-listItem">This Site</div>
</div>

If you want to target the first nested DIV (the Everything scope) then you could add the following CSS style statement to your site. Please note that the ID is included to target result sources and avoid catching query suggestions.

/* Hide the "Everything" Scope */
#NavDropdownListContainer .ms-qSuggest-list div:first-child {
 	display:none;
}

End result:

Hide the Everything scope

 

The first-child pseudo element selector offers good browser support. If you want to target the second scope (People), third scope (Conversations) or fourth scope (This Site), then you could use a nth-child pseudo element selector, which was introduced in CSS3.  Here is a style statement using the nth-child in place of first-child.

/* Hide the "People" Scope */
#NavDropdownListContainer .ms-qSuggest-list div:nth-child(2) {
 	display:none;
}

End result:

Hide People search scope

 

For the Conversations scope you would change it to :nth-child(3) and for the This Site scope, :nth-child(4). It is neat and tidy, and not supported in Internet Explorer 8.

I still have to support IE8, so what do I do?

Booze helps.

No really, there is a solution (at least in addition to the booze).

One of the often ignored selectors in CSS2 is the sibling combinator selector.  It comes in two flavors, adjacent and any sibling.  For an adjacent combinator you use a plus sign (+) between two selectors and it requires that the two elements are adjacent to each other.  For the any sibling (or general sibling) combinator, you use a tilde (~) instead and it dictates that the elements have to be siblings, but not adjacent. For example:
Sample sibling combinators

Using sibling selectors, the second, third and/or fourth search scopes can be targeted. And better yet, it is supported by IE8. The only issue is that it is not as neat and tidy as the nth-child selector.

Let’s walk back through the same examples as above, this time using sibling selectors.  The first example doesn’t need to change since IE8 does support the first-child pseudo element. We are going to take advantage of this and use it again to target other scopes.

/* Hide the "Everything" Scope */
#NavDropdownListContainer .ms-qSuggest-list div:first-child {
 	display:none;
}

To target the second scope (People), third scope (Conversations) or fourth scope (This Site), we are going to start what we did for the Everything scope and add a sibling selector to pinpoint a specific sibling starting from the first DIV (Everything scope).

/* Hide the "People" Scope */
#NavDropdownListContainer .ms-qSuggest-list div:first-child + div {
 	display:none;
}

End result:

Hide People search scope

 

To hide the Conversations scope, you can use this:

/* Hide the "Conversations" scope */
#NavDropdownListContainer .ms-qSuggest-list div:first-child + div + div {
 	display: none;
}

And for the This Site scope, use this:

/* Hide the "This Site" scope */
#NavDropdownListContainer .ms-qSuggest-list div:first-child + div + div + div {
 	display: none;
}

As an alternative if you want to hide all of the scopes except for the Everything scope, you can use the any sibling selector instead:

/* Only show the "Everything" scope */
#NavDropdownListContainer .ms-qSuggest-list div:first-child ~ div {
 	display: none;
}

End result:

Hide 2, 3, and 4th scope options

 

It is important to note that these style statements have been created to provide support for IE8, but all major browsers will support them.  You can add these styles in an IE8 specific CSS file, or just use these instead of nth-child selectors.

A different application, the SharePoint Ribbon

Last week I posted CSS for hiding SharePoint ribbon elements.  Some of the selectors in that post use nth-child pseudo element selectors. If you want to hide these elements in IE8, then you need to use sibling selectors instead.

For example, to hide the Heading 2 Alternate style in the ribbon Styles section, you could add this to your CSS file:

#Ribbon\.EditingTools\.CPEditTab\.Paragraph\.ElementWithStyle\.Menu\.Styles\.Gallery tr + tr td:nth-child(2) {
	display: none;
}

The backslashes embedded in the style statement escape the periods used in the ID, which would normally signal a class name in CSS.

Hide a style in the Ribbon

For IE8, you would need to use the following style statement instead:

/* Hide "Heading 2 Alternate" from Styles */
#Ribbon\.EditingTools\.CPEditTab\.Paragraph\.ElementWithStyle\.Menu\.Styles\.Gallery tr + tr td:first-child + td {
	display: none;
}

To hide the Heading 4 Alternate from Styles, the CSS style statement would be updated to the following:

/* Hide "Heading 2 Alternate" from Styles */
#Ribbon\.EditingTools\.CPEditTab\.Paragraph\.ElementWithStyle\.Menu\.Styles\.Gallery tr + tr td:first-child + td + td + td {
	display: none;
}

Wrapping Up

Sibling selectors can get you out of some tight spots with IE8, but they can’t help you with some variations of the nth-child selectors, such as targeting all of the odd or all of the even elements. For that you will need to turn to jQuery.