paint-brush
6 Awesome Tips To Help You With CSS Selectorsby@defoebrand
843 reads
843 reads

6 Awesome Tips To Help You With CSS Selectors

by Brandon DefoeJuly 26th, 2020
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

Brandon Defoe is an aspiring Full-Stack developer working through the Microverse program. He outlines some good CSS selectors to help you navigate the cascading landscape of style sheets. These are the essential building blocks of building CSS as much as building as a building of CSS blocks of. Just as much of a general styling block as a <div> as a semantic tag as a. semantic block of. semantic elements and. pseudo elements. Elements and pseudo elements such as h1, div, :before, and :after. Classes, attributes, and pseudo-classes such as #id or #search-bar.

Company Mentioned

Mention Thumbnail
featured image - 6 Awesome Tips To Help You With CSS Selectors
Brandon Defoe HackerNoon profile picture

Choosing the right CSS selectors can be a lot of trouble and there’s so much information out there that it can even be a little overwhelming at times. Words like “combinators” and “specificity” get thrown around a lot, you read how greater specificity increases efficiency but then how ID’s (the most specific) should be avoided like the plague, according to some. What’s a poor coder to do as he navigates the cascading landscape of style sheets? Hopefully by the end of this I will have been able to outline some good practices, and provide enough additional resources, to clear this issue up for good.

Let’s begin by examining combinators. At first, combinators sound like they should combine something but what they really do is allow us to select an element based on its relationship to other elements.

This creates a very rigid structure. For example, if I have used 

div a {}

to select all <a> elements inside of any <div> element because I want all links inside containers with associated text to be the same color, and I need to change one of my <div> containers to the more semantic <section> tag, then I will need to copy the CSS rules already written and create a new selector for this one <section>.

Similarly, if I have selected all <a> elements with the class ”link” inside a <div> with the class ”container” by using classes such as

 .container .link {} 

and for whatever reason I need to unwrap one of those <a> tags, it will no longer have the same style applied to it.

To be clear, I’m not implying never to use this format of selector. Let’s examine our code again. Perhaps we want every link on our page to have the same font color and size. We may put this in our CSS:

.link {
  color: purple;
  font-size: 12px;
}

but what if we want only the links in our <div> container to have no text decoration? That is a great time to use

.container .link {
  text-decoration: none;
}

because it will do exactly what we want. If a link is put in the container it will lose text-decoration and if it’s taken out it will get it back.

Since all the combinator selectors rely on the relationship between elements as they are found in the HTML document, any changes to the HTML document will require changes in the CSS to match. Instead of relying on positioning relationships, we can instead be specific about exactly which element we want to style, which brings us to specificity. 

Obviously, styles written inline with the HTML are going to be the most specifically applied as they point directly to the element they are written into. As this practice is generally frowned upon we will not be going over it in this article however it is important to keep in mind that it has the highest specificity (not counting !important) when it comes to applying styles but it is also very limiting in its capabilities, not to mention it only styles one element at a time and will greatly increase the amount of code necessary for you to write. Moving past inline styles we have three categories to examine, from least specific to most specific.

1. Elements and pseudo elements such as h1, div, :before, and :after

2. Classes, attributes, and pseudo-classes such as .container, [type=attribute], :hover, and :focus

3. IDs such as #id or #search-bar

Starting with the most general elements in your style sheet is a great way to build a nice framework of CSS code, one that incorporates standard styling code you may find yourself using most frequently and that can be applied to a wide range of sites. As you will only have one <body> element, it doesn’t necessarily need its own class or ID to be selected and you can use this element tag to begin styling your page immediately. If you wanted every button on your page to have the same background color, you wouldn’t want to style all of them individually but you can start out by setting a standard style for all of them using the element tag and then add a unique identifier to the one button that needs a slightly different look to it.

Once you have your HTML structured using semantic elements and have used as much general styling as possible, you will need to start being more specific about which elements you want to style.  That’s where classes and attribute selectors come in. These are the essential building blocks of CSS. Just as a <div> can be created in HTML and then styled in CSS, a class can be created in CSS and then applied to any element in the HTML.

Let’s think about those buttons again. On our page, we need all of them to have a blue background, one-quarter of them need to have no text-decoration, another quarter needs to be italicized, and half need both. One way we could accomplish this is by using the following code in our CSS:

button {
  background: blue;
}

.no-decoration-quarter {
  text-decoration: none;
}

.italicized-quarter {
  font-style: italic;
}

.combined-half {
  text-decoration: none;
  font-style: italic;
}

 We could then apply those classes to the appropriate button elements but this is definitely more code than we need. A simpler option would be to use the following:

button {
  background: blue;
}

.no-text-decoration {
  text-decoration: none;
}

.italicize {
  font-style: italic;
}

 With these two classes, not only can we apply them to whichever buttons need them, we can also use them in other places throughout our page. This can make both our HTML easier to read and our CSS more efficient as we can visually imagine the applied styles as we read the HTML and we’ve completely eliminated the need for one class in our CSS. That isn’t to say you should have a class for every type of style but the more generalized you can write and apply your code, the better.

Leaving our code as general as possible allows us plenty of room in the specificity hierarchy for when we need to include an ID but as a general rule of thumb for good clean CSS, don’t use IDs unless you need them and honestly, you need them far less than you think. Functionally, a class can do everything an ID can do and more because it can be applied as many times as needed. When using IDs in CSS you need to be certain that the element being given an ID is only going to appear once on your page. It is not there to be used as a quick fix for specificity issues. Using them can also help future developers looking at your code by telling them clearly “This is a unique item”. Now I’m not saying you shouldn’t use IDs in your HTML, because they are certainly useful, just less so in styling with CSS. They are great for anchoring a bookmark to a specific spot on the page, linking labels to form fields, or selecting an element in JavaScript.

For a more visual understanding of specificity, play with this specificity calculator.

It’s important to note here that CSS is interpreted by the style system from right to left (RTL) so while selecting everything found in a <div> container may be done by using div * {} it causes the system to examine EVERY element in your HTML first and then individually determine if any of these elements are inside of a <div>. It may seem very effective and easy to read/write for humans, it also causes the page to perform at unnecessarily slower speeds. Additionally, while they do have the same specificity, attribute selectors are way less efficient than class selectors because they cause the style system to examine every attribute of every element to find the right ones. To read about more ways to optimize your CSS, go here.

If you’re still with me, Whew! Right? It’s a lot to take in, so let’s summarize.

1. Using combinators can be useful but may create a very rigid page structure that could need a lot of reworking in both the HTML and CSS files if any changes are to be made.

2. Attribute selectors should usually be avoided but can be very useful for forms and inputs.

3. Using element tags for styling can be very useful for elements associated with page layout and unique elements don’t need their own class or ID, although there are cases where they can and should be applied.

4. Classes are the bread and butter of your CSS so use them often. Generalize them as much as possible, give multiple classes to your HTML elements as applicable, and be descriptive in naming them. It not only can increase the efficiency of the style system it is also a lot easier to read CSS with descriptive classes than it is to read

div div div a p {}

5. IDs have a lot of great uses in your HTML but have very few, very specific use cases in your CSS. 

6. Finally, due to the RTL read direction of the style system, the rightmost selector is your most important one and while div.container is more specific than .container, if you ever need to change the element from <div> to something else, it takes more work than simply changing it in the HTML.

So why should we care about choosing the right CSS selector? Flexibility. If you were to use an attribute selector with an element tag such as

input[type=submit] {}

to select 

<input type=’submit’ class=’submit’>

and need to later change the HTML element from ‘input’ to ‘button’ then you would need to update the CSS as well. On the other hand, if you were to have used a class selector to style your element then your style would be unaffected by the change in element type, ignoring for the moment any default attributes that may not have been redefined in your class style. The same thing goes for using an element tag with the class selector such as input.submit. While this may be useful in increasing specificity, it may be more trouble down the road than it’s worth.

Truthfully many of the points about optimization that I’ve mentioned may never cause any problem on your site. If writing a relatively small bit of HTML code, or creating a site that has no need for future updates, optimizing your CSS for flexibility may never matter. However, the more complex the design the more speed will matter, especially if it is a public site catering to clients/customers of any sort. At the end of the day, best practice is always best even if it's not always necessary.

If you’re interested in reading more about coding high-performance websites, Steve Souders’ blog is a great resource!

I am always learning more and appreciate different views so if I missed something or made a mistake, feel free to reach out to me!

Thank you to Kevin Alves and Eyüp Sercan Uygur for reviewing this article.

Don’t get left behind, follow me now before it becomes just the ‘cool’ thing to do!

And remember, always stay DRY!