Blog

The Unsung Heroes of CSS Selectors

Posted by in Web Development tagged with


Some lesser-known CSS selectors can help create a better user experience for site visitors and admins alike.

Website administrators have varying proficiencies when it comes to coding. Not every company or organization has the resources to have a developer on staff. Often, the person who manages the website has some knowledge of HTML, but is not versed in CSS or JavaScript. If this is the case, it helps if a developer can pare down HTML files so they do not contain elements that can live in a CSS file. CSS selectors are elements of code that name the HTML content you want to style; they are the link between CSS and HTML. The better a developer is at using the multitude of selectors that exist, the less code has to exist in your HTML file and the easier it is for a non-developer to read and update it.

This blog post will introduce you to a few of the lesser-known CSS selectors, to give developers improved tools for writing CSS that removes unnecessary code from HTML.

What CSS Does for HTML

Think of a webpage like the poster for a concert. HTML is like the basic content of a poster. The HTML might read:

  • Sigur ros
  • Thursday, June 12
  • Kansas City, Missouri
  • Uptown Theatre
  • Presented by Mammoth

Unstyled HTML is about as aesthetically pleasing and visually interesting as the list above. While the information it presents is relevant and helpful, it doesn’t really grab your attention. Cascading Style Sheets (CSS) are what drive the look and feel of a website. They dictate the layout, colors, and sizes of elements on a page. CSS converts that boring, unstyled HTML into something visually compelling.

The Usual Suspects

CSS selectors are what connect the styles (font size, color, width, etc.) you defined in your CSS file to HTML elements on the webpage. Even if you’re new to CSS, there are a number of selectors you’re probably familiar with. You can select HTML elements using:

  • The element itself. The CSS to select <p>Any paragraph</p> is:
     p { font-size: 16px; }
  • Classes applied to an element. The css for <p class=”small”>Tiny text</p> is:
     .small { font-size: 12px; }
  • The ID of an element. The CSS for <form id=”mailchimp-form”>Sign up</form> would be:
     #mailchimp-form { border: none; }
  • Pseudo-selectors. The css for when you interact with <a href=”/”>Home</a> is:
     a:hover, a:visited, a:active { text-decoration: underline; }
  • Descendents. To select only the <input>’s inside <form id=”mailchimp-form”><input /></form>, the css is:
     #mailchimp-form input { background: #FFFFFF; }

All of these selectors date back to the late ‘90s and are widely used for creating CSS. They should look somewhat familiar even if you’ve only tinkered with CSS.

New Kids on the Block

With the advent of CSS3 a variety of new selectors were introduced in 2011 that make writing CSS easier, including:

  • :last-child
  • :nth-child()
  • :nth-of-type()
  • :checked
  • :not()

Let’s say you have a table and you want rows to alternate colors between white and grey. Before CSS3, you would have to add a class to every other row like this:

<style>
tr.grey { background: #CCCCCC; }
</style>
<table>
<tr><td>White Row</td></tr>
<tr class="gray"><td>Grey Row</td></tr>
<tr><td>White Row</td></tr>
<tr class="gray"><td>Grey Row</td></tr>
</table>

Now with CSS3 you can just use the :nth-of-type pseudo-selector like this:

<style>
td:nth-of-type(odd)
</style>

CSS3 selectors have been widely adopted. However, they don’t always work in older browsers, so to be safe, it’s best to check http://caniuse.com/ if this is a concern.

The Unsung Heroes

CSS3 is great and adds much-needed abilities to CSS. However, there are a couple selectors that often go unnoticed or under-appreciated. They hail back to the days of CSS 2.1, but are incredibly useful:

  • :first-child
  • +
  • >

The :first-child selector is a pseudo-selector, meaning that it will select a subset of the given selector. The + and > selector only select an element if it has a specific relationship to another element. Of the three :first-child seems to be the mostly widely known and used.

First Child

The :first-child pseudo-selector will only select an element if it is the first element within a group of elements. For example:

<style>
p:first-child { color: #FF0000; }
</style>
<div class="main-item">
<p>I’m the first HTML element in this div!</p>
<p>I’m not the first</p>
<div class="sub-item">
<h1>I’m a heading, not a paragraph</h1>
<p>I’m the not the first</p>
</div>
</div>

So in this example, the first paragraph in <div.main-item> is red because it is the first <p> element in that div. However the first <p> in <div.sub-item> is not red, and neither is the <h1>, because p:first-child only selects <p> elements if they are the the first html element in their parent element. If we wanted to select both the first <p> and the <h1> we could do one of these:

  • p:first-child, h1:first-child
  • *:first-child
  • :first-child

Adjacent Sibling

The + selector only selects elements that are preceded by another element. It’s called the “adjacent sibling” selector, but that only works in one direction. It will only select an element if it is directly adjacent to and preceded by a specified element. For example:

<style>
img + p { color: #FF0000; }
</style>
<p>You don’t need to see his identification.</p>
<p>These aren’t the droids you’re looking for.</p>
<img src="r2-d2.jpg" />
<p>Beep-beep-boowoop</p>
<p>He can go about his business.</p>
<div class="storm-trooper">Confused</div>
<p>Move along.</p>

In this example the only paragraph that is red is the <p> immediately following the <img> tag.

Child

The > selector only selects elements that are children (not descendents) of parent element. This means they have to be directly inside the other element. For example:

<style>
.fruits > p.apples { color: #FF0000; }
</style>
<div class="plants">
<p class="apples">Red light</p>
<div class="fruits">
<div class="edible">
<p class="apples">Red light again</p>
</div>
<p class="apples">Green light</p>
</div>
</div>

In this example only the last paragraph is red. The first <p.apples> isn’t a descendent of <div.fruits>. The second <p.apples> is a descendent <div.fruits>, but since it’s inside <div.edible> it’s not a child of <div.fruits>. Only the last <p.apples> is a direct child of <div.fruits>.

If we wanted to select the second and third <p.child>’s we could use either:

  • .parent p.child
  • .parent > p.child, .cousin > p

Bringing it Together

A multi-level interactive menu with drop-downs and submenus is easy to build using JavaScript, but not everyone knows JavaScript. Surprisingly, we can accomplish everything we’re trying to do using CSS. This jsfiddle demonstrates how this might be accomplished using only CSS. All of the interactive components for this menu can be handled using 5 declarations (and it doesn’t even make use of CSS3!) Check it out:

#menu > li:first-child a { /* Only the first, top-level menu item will be highlighted */
color: #FF0000;
}
#menu ul { /* Submenus are hidden by default */
display: none;
}
#menu li:hover > ul { /* When hovering on the parent menu item, the direct child will disappear */
display: block;
}
#menu p { /* Descriptions are hidden by default */
display: none;
}
#menu :hover + p { /* Descriptions show when hovering on the item before them */
display: block;
}

Do More with :first-child, + and >

Multi-level menus are one of the best ways to demonstrate these selectors. However if you want to see another cool implementation, check out the interactive circle on UPIC Health. It’s got some crazying chaining (ol li:first-child + li + li + li) going on.

Cleaner Code, Better Experience

Doing all this ultimately leads to cleaner, more intelligible code. Not only is cleaner code a more sustainable practice, it makes updating the website safer and easier for less technically inclined site admins.

Mightybytes is a Chicago-based digital agency and Certified B Corporation. Connect with us on Twitter or get in touch via our contact form.