Have you ever find yourself struggling to use CSS selectors to style an element that is the first sibling of the nth
child of an element that contains an attribute with a specific value, or something like that? Well, if you have worked with dynamic layouts you have probably been through that.
This is intended to be a quick reference for CSS selectors, attributes, and pseudo-classes, presented with examples. I wanted to do this in a private document for personal use since there are tons of CSS cheat sheets out there. But, maybe I will get to put it in a different way, which can be more understandable to someone out there. So, why not share it with everyone?
For this post, there are a few basic concepts you must be aware of before continuing, those being selectors (type, attribute, id, class), pseudo-classes, pseudo-elements, and combinators.
Let's get started.
Selectors
Even though CSS tutorials often consider everything we are going to talk about here as CSS selectors, it is good to point that there is a specific term for each type of selectors in a CSS stylesheet.
Type selectors
These are selectors used to match elements in the DOM, such as p
, div
, span
, and even customized tags, like in the example below.
custom {
border: 1px solid black;
}
p {
color: green;
}
<custom>Custom element</custom>
<p>Paragraph</p>
Class selectors
These are used to select elements in the DOM that have a specific class as an attribute. For this, you have to add a .
to the beginning of the name you want to match.
.bordered {
border: 1px solid red;
}
<div class="bordered">
Bordered element.
</div>
Attribute selectors
These will match elements that have a specific attribute associated with it. This can be used to match both individual attributes and attributes associated with their values. For this type of selector, you must surround the attribute name with square brackets. Check the example below.
[name] {
background-color: green;
}
[name="age"] {
background-color: red;
}
<input type="text" name="name" placeholder="Your name" />
<input type="number" name="age" placeholder="Your age" />
In this example, you can notice that initially, we are creating a CSS rule for all the elements that have an attribute of name
. This will give you the two inputs showed in your HTML code since both of them have the attribute. However, after that, we are creating a more specific rule that tells the browser to use a red background for elements that have an attribute of name
with a value of age
, which will give you the last input.
You can also use different operators to match values, other than using =
. Check out them below.
~=
This operator matches a whitespace-separated list of words, in which one of the words is exactly the value passed.
[class~="bordered"] {
border: 3px solid green;
}
<button class="btn bordered">Click Here</button>
|=
This operator matches elements with attribute value being the exact string passed or starting with the string followed by -
.
[class|="primary"] {
color: green;
}
<button class="primary-btn">Click Here</button>
<p class="primary">Paragraph</p>
^=
This operator matches elements with attribute value starting with the string passed.
[class^="call"] {
color: green;
}
<button class="caller">Caller</button>
<button class="called">Called</button>
<button class="calling">Calling</button>
$=
This operator matches an element with attribute value ending with the string passed.
[class$="ed"] {
background-color: pink;
}
<div class="required">
<p>Required</p>
</div>
<div class="validated">
<p>Validated</p>
</div>
*=
This operator matches an element with attribute value containing the string passed, at least once.
[class*="prim"] {
background-color: pink;
}
<button class="btn-primary">Click here</button>
PS.: in order to perform those matches in a case-insensitive way, you can append an i
to the rule, e.g: [attr="value" i]
.
ID selectors
These will match elements with a specific identifier associated with it. For this type of selector, you have to use a #
before the ID you want to match. Check the example below.
#d123 {
font-weight: bold;
}
<div>block without ID</div>
<div id="d123">block with ID of d123</div>
Universal selector
This one is used to match all the elements in the page. It can be used to reset margins and paddings for all elements, for instance. However, it is not indicated since it can overload the rendering process of your page.
* {
border: 1px solid yellow;
}
<ul>
<li>
<a href="#">Item 1</a>
</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>
<span>Item 5</span>
</li>
</ul>
Pseudo-class
Pseudo-classes are used to match content in a more extensive way since they can refer to elements not directly represented in the DOM, in almost all cases. These type of selectors usually refer to the state of an element. Due to that, they can be dynamically accessed, based on user interaction. Good examples are the :link
and :visited
pseudo-classes, which are used to style links based on whether they have been visited or not. In order to use a pseudo-class, you have to add a :
to the beginning of the class name. As these selectors are hard to represent statically in this post, I think it is better to put them inside a JSFiddle so you can play a little with them if you want. There you can simply uncomment the part of CSS and HTML you want and see the results in the right side tab. Click here to check examples for the selectors listed below (some of them are explained below the table, some are just too intuitive and do not need to be clarified).
:focus
match elements that are currently focused, meaning when a user clicks to edit an input ortextarea
element, for instance.:active
match the moment when users click an element. The style will be applied for as long as a user holds the click over an element.:hover
match elements in which the mouse is currently over.:empty
match elements that do not have any child.:valid
match inputs that hold legal values according to each input type. One example is when you have an input for email values, so you can apply a style for when a user enters a valid email. Note that an input with no value set is considered being in a valid state.:checked
match checkbox inputs that are currently checked.:link
match unvisited links.:in-range
match input elements that hold values within a specific range.:not(selector)
match every element that is not the one passed as a parameter.:first-child
match the first child inside of a specific parent. For instance, if you dop:first-child
that will match the first paragraph inside of its parent.:first-of-type
match the first element of a given type. For instance, if you go simply:first-of-type
that will match every element that is the first of its type inside a specific parent.:lang(language)
match elements that have an attribute oflang
with a specific value.:nth-child(n)
match the element that is the nth element inside of a specific parent. For these rules in which you can specify an integer value for the index, you can pass something like2n
to get elements in every two index position, for instance.:nth-last-child(n)
same asnth-child
but start counting from the end.:nth-of-type(n)
match the element that is the nth element of a given type inside a specific parent.:nth-last-of-type(n)
same asnth-of-type
but start counting from the end.:only-of-type
match the element that is the only element of its type inside a specific parent. For instance, if you dop:only-of-type
it will match the only existing paragraph, if there are more than one it will not match anything.:only-child
match the element that is the only child of a specific parent. If there are more than one children within that parent, nothing will be matched.:optional
match input elements with norequired
attribute.:read-only
match elements with aread-only
attribute.:read-write
match elements with noread-only
attribute.:required
match elements with arequired attribute
.:root
match the document's root element. This selector is usually used to set global CSS variables.
Pseudo-element
Pseudo-elements can be used to refer to content that does not exist in the source code, i.e, content that is generated afterward. Let's take a look at them below. If you want to check examples for this section, check this fiddle.
::after
and::before
used to add and style elements that are respectively the last and first child of the selected element. This is usually used to add tooltips or icons to labels, inputs, etc.::first-letter
select the first letter of a text inside an element.::first-line
select the first line of a text inside an element.::selection
select the current text selected by the user.
Combinators
Combinators are, in my opinion, the most interesting part of CSS selectors. At this point, you will be able to gather everything you learned so far and associate it with combinators to get more complex CSS rules. Let's check the CSS combinators available. Check the examples here.
- Group of selectors
,
This can be used when you want to apply the same style to several elements, so instead of creating different blocks for each one you can simply list them using,
and write the rules once.
h1, h2, h3, h4, h5, h6 {
margin: 1rem;
text-decoration: underline;
}
The rules above apply margin
and a text-decoration
to all heading tags at once.
- Descendant selector
A blank space can be used to select elements that are within (descendant) a specific block.
.container .col {
padding: .5rem 1rem;
}
Above we are adding padding to all the elements with the class col
that are inside an element with the class container
- Child selector
>
This one selects immediate children of a specific element. It differs from the blank space combinator because with it you cannot select grandchildren of a given parent.
.container > ul {
border: 1px solid black;
}
Above we select all the ul
elements that are immediate children of the .container
block.
- Adjacent sibling selector
+
This combinator helps to select the adjacent sibling of a given element. Check the example below.
.item2 + li {
font-size: 2rem;
}
Here we are applying a font size of 2rem
to the li
that is the immediate sibling of the .item2
element. Note that this and the next combinator only look down the tree.
- General sibling selector
~
This combinator gives you all the siblings of a given element.
.item2 ~ li {
color: red;
}
Here we are selecting all the li
elements that are sibling of the .item2
element, again, looking down the tree.
And that's it for now! I hope this quick review helped you somehow :)
PS.: this is a living document, if you have any comments, tips or know about missing selectors, let me know in the comments and I will update it.
Top comments (4)
Thank you, this will be my goto page for CSS selector..
Great overview. Every time I dabble with CSS I get stuck with the selectors. This is exactly what I needed.
Yeah, I know how that feels. I'm happy this post helps you :)
Thanks for sharing this! So many, "I didn't realise you could do that moments"