paint-brush
How to Write CSS Advanced Selectors Like a Proby@Akram
700 reads
700 reads

How to Write CSS Advanced Selectors Like a Pro

by MohabSeptember 21st, 2020
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

A guide for structuring CSS advanced selectors as a pro. The guide explains how to organize your code and write cleaner, less CSS code. The CSS toolbox offers a lot of selectors like: child selectors, sibling selectors and class selectors. With these tools in your toolbox, you’re going to write a clean CSS code, and when combining all of them you end up writing less code. Let me know if you have any comments or anything to add in Community.

Companies Mentioned

Mention Thumbnail
Mention Thumbnail
featured image - How to Write CSS Advanced Selectors Like a Pro
Mohab HackerNoon profile picture

Having 3 years of experience as a freelance front-end developer, I thought there is nothing new I could learn about CSS. However, studying at Microverse gave me the chance to actually go deep into things that I took my knowledge on for granted like CSS selectors.

How to choose the perfect selector?

Here is my guide for structuring CSS advanced selectors as a pro. Following this mental model made it very easy for me to write short effective CSS selectors.

First step: what level of specificity do you need for this element?

CSS Specificity is a very important concept to understand because it helps you understand why your styles are not being applied.

But the major benefit here and what I actually like about it is that it helps you organize your code and write cleaner, less CSS code.

I break it down like this:

1. General specificity: which corresponds to the lowest specificity level in CSS which is the element selector like this:

/* this good for basic general style re-use because this color will be applied to 
all paragraphs across the page and can still be easily overridden for specific cases. */
p {
  color:red;
}

2. Medium specificity: which is a class selector

/* a class selector is useful when you want to reuse styles for more than one type of elements */
.red {
  color:red;
}

3. A specific selector: which is the highest level of specificity that we should take in mind while planning our CSS structure which corresponds to ID selector in which it will override any tag or class selector and will be only overwritten by an inline style or properties that have the important keyword.

/* ID selector is a unique selector in which we use to give a specific element some properties with no intent to re-use it again. */
#nav-bar {
  color:red;
}

Now that you made a specificity hierarchy for your web page style, it’s the time to dive deep into what CSS has to offer beside classes and IDs to select elements.

Second Step: get to know your advanced selectors

Let’s imagine that we have a certain paragraph element that we are going to experiment with.

The CSS toolbox offers a lot of selectors like:

Child selectors: in which you can select a child of our paragraph element in two useful ways

/* Child */

/* Descendant Selector: The descendant selector matches all elements that are descendants of a specified element.*/
p span {
  color:green;
  /* so any code written here will be applied to all span elements inside any paragraph element. */
}


/* Direct Child Selector: It matches only those elements matched by the second selector that are the direct children of elements matched by the first. */
p > span {
  color:white;
  /* will be applied to all direct span child elements of our paragraph element */
}

So when we want to select a child of an element we can choose between descendant or direct child depending on our case.

Sibling Selectors: in which we select elements depending on what comes before them and knowing that they have a common parent.

/* Sibling Selectors */

/* General Sibling Selector: matches the second element only if it follows the first element (though not necessarily immediately), and both are children of the same parent element. */
p ~ h2 {
  ...;
  /* this is a general sibling selector that looks for h2 elements that follow, and share the same parent, of any p elements.
 In order for a h2 element to be selected it must come after any p element. */
}


/* Adjacent Sibling Selector: matches the second element only if it immediately follows the first element, and both are children of the same parent element. */
p + h2 {
  ...;
  /* h2 that come immediately after any paragraph */
}

Attribute Selectors: in which we select elements with their attributes.

/* Attribute Selectors */

/* Attribute Present Selector */
a[target] {
  ...;
}

/* Attribute Equals Selector */
a[href="http://google.com/"]
{
  ...;
}

/* Attribute Contains Selector */
a[href*="login"] {
  ...;
}

/* Attribute Begins With Selector */
a[href^="https://"]
{
  ...;
}

/* Attribute Ends With Selector */
a[href$=".pdf"] {
  ...;
}

/* Attribute Spaced Selector */
a[rel~="tag"] {
  ...;
  /* At times attribute values may be spaced apart, in which only one of the words needs to be matched in order to make a selection.
 In this event using the tilde character, ~, within the square brackets of a selector between the attribute name and equals sign denotes an attribute value that should be whitespace-separated, with one word matching the exact stated value. */
}


/* Attribute Hyphenated Selector */
a[lang|="en"] {
  ...;
}

Pseudo-classes: in which we select regular elements but under certain conditions, like when their position relative to siblings or when they’re under a particular state.

/* Pseudo-classes */


/* Link Pseudo-classes */
a:link {
  ...;
/*   It matches every unvisited <a>, <area>, or <link> element that has an href attribute. */
}
a:visited {
  ...;
/* all visited links */
}

/* For normal links and when a link is clicked based on the user history */

/* User Action Pseudo-classes */
a:hover {
  ...;
}
a:active {
  ...;
}
a:focus {
  ...;
}

/* User Interface State Pseudo-classes */
input:enabled {
  ...;
}
input:disabled {
  ...;
}

/* Mainly used with Inputs in forms */

input:checked {
  ...;
}

input:indeterminate {
  ...;
}

/* For checkboxs and radio inputs */

/* Structural & Position Pseudo-classes */

/* :first-child, :last-child, & :only-child */
li:first-child {
  ...;
}
li:last-child {
  ...;
}
div:only-child {
  ...;
}
/* Here the selector li:first-child identifies the first list item within a list, while the selector li:last-child identifies the last list item within a list, thus lines 2 and 10 are selected.
The selector div:only-child is looking for a division which is the single child of a parent element, without any other other siblings.
In this case line 4 is selected as it is the only division within the specific list item. */

/* :first-of-type, :last-of-type, & :only-of-type */
p:first-of-type {
  ...;
}
p:last-of-type {
  ...;
}
img:only-of-type {
  ...;
}

/* :nth-child(n) & :nth-last-child(n) */
li:nth-child(3n) {
  ...;
}

/* :nth-of-type(n) & :nth-last-of-type(n) */
p:nth-of-type(3n) {
  ...;
}

/* Target Pseudo-class */
section:target {
  ...;
}

/* , if a user would visit a page with the URI fragment identifier of #hello, the section with that same ID attribute value would be stylized accordingly using the :target pseudo-class.
 If the URI fragment identifier changes, and matches the ID attribute value of another section, that new section may be stylized using the same selector and pseudo-class from before. */

/* Empty Pseudo-class */
div:empty {
  ...;
}

/* Negation Pseudo-class */
div:not(.awesome) {
  ...;
}

:not(div) {
  ...;
}

Pseudo-elements: effectively create new elements that are not specified in the markup of the document and can be manipulated much like a regular element. This introduces huge benefits for creating cool effects with minimal markup, also aiding significantly in keeping the presentation of the document out of the HTML and in CSS where it belongs.


/* Pseudo-elements */

/* Textual Pseudo-elements */
.alpha:first-letter,
.bravo:first-line {
  color: #ff7b29;
  font-size: 18px;
}

/* Generated Content Pseudo-elements */
a:after {
  color: #9799a7;
  content: " (" attr(href) ")";
  font-size: 11px;
}

/* Fragment Pseudo-element */
::selection {
  background: #ff7b29;
}

/* Basically a pseudo-class is a selector that assists in the selection of something that cannot be expressed by a simple selector, for example :hover.
 A pseudo-element however allows us to create items that do not normally exist in the document tree, for example ``::after`. */

With these awesome tools in your toolbox, you’re going to write a clean CSS code, and when combining all of them you’re going to find that actually you end up writing less CSS code.

Let me know if you have any comments or anything to add in Community.