What are CSS Selectors & How Do They Work?

Afzal PashaAfzal Pasha
8 min read

CSS Selectors are used to select or target an HTML Element or group of elements based on the selector we are using. Selectors are backbone of CSS.

Selectors are used in internal or external CSS. After selector name, a declaration block, i.e. curly brackets {} are used. Within {}, CSS code for targeted element is written with key:value pair. Sometimes multiple values are there for single key, so white space is used as separator. After Property:value, semi-colon ; is used to add next property and value.

Basic Selectors

  1. * Universal Selector
* {
 margin: 0;
 padding: 0;
}

The star symbol will target every single element on the page. Many developers will use this trick to zero out the margins and padding. While this is certainly fine for quick tests. The * can also be used with child selectors.

#container * {
 border: 1px solid black;
}

This will target every single element that is a child of the #container div.

2.# Id Selector

#container {
   width: 960px;
   margin: auto;
}

Prefixing the hash symbol to a selector allows us to target by id.

3.. Class Selector

.error {
  color: red;
}

Select elements with that class

4.a ul div Type Selector

a { color: red; }
ul { margin-left: 0; }
div { padding: 0 20px;}

What if you want to target all elements on a page, according to their type, rather than an id or classname? Keep it simple, and use a type selector. If you need to target all unordered lists, use ul {}.

Combinator Selectors

1.li a Descendant Selector

li a {
  text-decoration: none;
}

The descendant selector. When you need to be more specific with your selectors, you use these. For example, what if, rather than targeting all anchor tags, you only need to target the anchors which are within an unordered list? This is specifically when you'd use a descendant selector.

2.ul + p Adjacent Sibling Selector

ul + p {
   color: red;
}

It will select only the element that is immediately preceded by the former element. In this case, only the first paragraph after each ul will have red text.

3.X > Y Direct Child Selector

div#container > ul {
  border: 1px solid black;
}

The difference between the standard X Y and X > Y is that the latter will only select direct children. For example, consider the following markup.

<div id="container">
   <ul>
      <li> List Item
        <ul>
           <li> Child </li>
        </ul>
      </li>
      <li> List Item </li>
      <li> List Item </li>
      <li> List Item </li>
   </ul>
</div>

A selector of #container > ul will only target the uls which are direct children of the div with an id of container. It will not target, for instance, the ul that is a child of the first li.

4.X ~ Y General Sibling

ul ~ p {
   color: red;
}

This sibling combinator is similar to X + Y, but it's less strict. While an adjacent selector (ul + p) will only select the first element that is immediately preceded by the former selector, this one is more generalized. It will select, referring to our example above, any p elements, as long as they follow a ul.

Attribute Selectors

1.X[title] Has Attribute

a[title] {
   color: green;
}

Referred to as an attributes selector, in our example above, this will only select the anchor tags that have a title attribute. Anchor tags which do not will not receive this particular styling. But what if you need to be more specific? Check out the next example!

2.X[href="foo"] Exact Attribute

a[href="https://learncodeonline.in"] {
  color: #83b348; /* Envato green */
}

The snippet above will style all anchor tags which link to https://learncodeonline.in; they'll receive our branded green color. All other anchor tags will remain unaffected.

3.X[href*="foo"] Substring Attribute

a[href*="LCO"] {
  color: #83b348; /* Envato green */
}

There we go; that's what we need. The star designates that the proceeding value must appear somewhere in the attribute's value.

4.X[href^="http"] Begins With Attribute

a[href^="http"] {
   background: url(path/to/external/icon.png) no-repeat;
   padding-left: 10px;
}

Ever wonder how some websites are able to display a little icon next to the links which are external? I'm sure you've seen these before; they're nice reminders that the link will direct you to an entirely different website.

5.X[href$=".jpg"] Ends With Attribute

a[href$=".jpg"] {
   color: red;
}

Again, we use a regular expressions symbol, $, to refer to the end of a string. In this case, we're searching for all anchors which link to an image—or at least a URL that ends with .jpg. Keep in mind that this won't capture GIF and PNG images.

Pseudo Selectors

  1. a:link { color: red; }
    a:visited { color: purple; }
    
    We use the :link pseudo-class to target all anchor tags which have yet to be clicked on. Alternatively, we also have the :visited pseudo class, which, as you'd expect, allows us to apply specific styling to only the anchor tags on the page which have been clicked on, or "visited".

2.X:checked

input[type=radio]:checked {
   border: 1px solid black;
}

This pseudo class will only target a user interface element that has been checked—like a radio button or checkbox. It's as simple as that.

3.X:after

.clearfix:after {
    content: "";
    display: block;
    clear: both;
    visibility: hidden;
    font-size: 0;
    height: 0;
    }

.clearfix { 
   *display: inline-block; 
   _height: 1%;
}

This hack uses the :after pseudo class to append a space after the element, and then clear it. It's an excellent trick to have in your tool bag, particularly in the cases when the overflow: hidden; method isn't possible.

4.X:hover

div:hover {
  background: #e3e3e3;
}

Oh come on. You know this one. The official term for this is "user action pseudo class". It sounds confusing, but it really isn't. Want to apply specific styling when a user hovers over an element? This will get the job done!

5.X:not(selector)

div:not(#container) {
   color: blue;
}

The negation pseudo class is particularly helpful. Let's say I want to select all divs, except for the one which has an id of container. The snippet above will handle that task perfectly.

6.X::pseudoElement

p::first-line {
   font-weight: bold;
   font-size: 1.2em;
}

We can use pseudo elements (designated by ::) to style fragments of an element, such as the first line or the first letter. Keep in mind that these must be applied to block-level elements in order to take effect.

Target the First Letter of a Paragraph

p::first-letter {
   float: left;
   font-size: 2em;
   font-weight: bold;
   font-family: cursive;
   padding-right: 2px;
}

This snippet is an abstraction that will find all paragraphs on the page, and then sub-target only the first letter of that element.

This is most often used to create newspaper-like styling for the first letter of an article.

Nth Child and Type Selectors

  1. X:nth-child(n)
li:nth-child(3) {
   color: red;
}

Remember the days when we had no way to target specific elements in a stack? The nth-child pseudo class solves that!

Please note that nth-child accepts an integer as a parameter, but this is not zero-based. If you wish to target the second list item, use li:nth-child(2).

We can even use this to select a variable set of children. For example, we could do li:nth-child(4n) to select every fourth list item.

2.X:nth-last-child(n)

li:nth-last-child(2) {
   color: red;
}

What if you had a huge list of items in a ul, and you only needed to access, say, the third to last item? Rather than doing li:nth-child(397), you could instead use the nth-last-child pseudo class.

This technique works almost identically to number 16 above. The difference is that it begins at the end of the collection, and works its way back.

3.X:nth-of-type(n)

ul:nth-of-type(3) {
   border: 1px solid black;
}

There will be times when, rather than selecting a child, you instead need to select according to the type of element.

Imagine markup that contains five unordered lists. If you wanted to style only the third ul, and didn't have a unique id to hook into, you could use the nth-of-type(n) pseudo class. In the snippet above, only the third ul will have a border around it.

4.X:nth-last-of-type(n)

ul:nth-last-of-type(3) {
   border: 1px solid black;
}

And yes, to remain consistent, we can also use nth-last-of-type to begin at the end of the selectors list and work our way back to target the desired element.

5.X:first-child

ul li:first-child {
   border-top: none;
}

This structural pseudo class allows us to target only the first child of the element's parent. You'll often use this to remove borders from the first and last list items.

For example, let's say you have a list of rows, and each one has a border-top and a border-bottom. Well, with that arrangement, the first and last item in that set will look a bit odd.

Many designers apply classes of first and last to compensate for this. Instead, you can use these pseudo classes.

6.X:last-child

ul > li:last-child {
   color: green;
}

The opposite of first-child, last-child will target the last item of the element's parent.

Conclusion

CSS selectors enable you to maintain precise control over your customization process and code when building a site from scratch. While there might be a learning curve, you should invest the time in learning and testing different types of CSS selectors.

Don't forget to share this post!

0
Subscribe to my newsletter

Read articles from Afzal Pasha directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Afzal Pasha
Afzal Pasha