CSS Selectors
Learning outcomes:
- What are selectors in CSS
- Different kinds of selectors — type, class, universal, ID, and attribute.
- Simple and compound selectors
- Grouping selectors together (using
,
)
What are selectors?
Before we can style elements on an HTML document, we have to first select them. Whether it's to style all the paragraphs, or just a tiny anchor element in the footer, we have to perform selection.
And to select elements in CSS, we have what we call selectors.
The elements selected all meet a given criteria established by the selector, for e.g. all elements having a particular type, or having a particular class, or a particular attribute, etc.
Before we move any further, I urge you to think about the various traits of HTML elements that we know which can help us in selecting them. To give you a headstart, we know about the type of different elements, e.g. <h1>
or <p>
or <a>
, and so on.
Well, we know quite a lot of stuff regarding HTML elements. To name a few, we know their types; their classes; their IDs; their attributes, plus given values of these attributes; and so on.
And with so much knowledge about HTML elements, it isn't surprising at all to know that we have a lot to CSS selectors!
There are different kinds of selectors in CSS. Some will be discovered in this chapter while the rest in the next one.
The ones we'll be covering in this chapter are:
- Universal selector,
*
- Type selector,
type
- Class selector,
.class
- ID selector,
#id
- Attribute selector,
[name="value"]
Let's explore each of these one-by-one...
Different kinds of selectors
Type selector
Perhaps, the simplest of all kinds of CSS selectors is a type selector.
The type here is basically just the name of the element. For example, the type selector p
selects all <p>
elements in the HTML document.
To denote a type selector, we don't need to do anything special — just enter the name of the desired element to select, and voila!
Thus far in this course, all the selectors that we've dealt with were type selectors.
Let's consider another example to review a type selector. In the following HTML document, we wish to give a blue color to all paragraphs.
<p>This is a paragraph</p>
<p>This is another paragraph</p>
Alright. This is really easy — just select all <p>
elements using the type selector p
and apply the color
property:
p {
color: blue;
}
This is a paragraph
This is another paragraph
Ain't that simple?
Write CSS to color all links in an HTML document as blueviolet
and all <span>
elements as gold
.
To select all links, which is basically all <a>
elements, we use the selector a
. To select all <span>
s, we trivially use the selector span
.
With this decided, the styling is just a matter of seconds, using the color
property and the given color values:
a {
color: blueviolet;
}
span {
color: gold;
}
Class selector
Multiple elements in an HTML document can fall under the same class, given by the class
attribute. CSS can then be used to select these groups of elements using a class selector.
The general form of a class selector is .class
, where class
represents the class name of the elements to select.
Let's take an example to better understand the class selector.
In the following HTML, we have a paragraph with multiple <span>
elements falling under the class highlight
:
<p>
I am <span class="highlight">highlighted</span>.
I am not highlighted.
I am <span class="highlight">highlighted</span>.
I am <span class="highlight">highlighted</span> too.
</p>
Just by reading the name of the class, we can reason about its purpose, i.e. to highlight the underlying element. In particular, we want all .highlight
elements to have a yellow background (to give that typical highlighted look).
Alright. Let's do this using the class selector:
.highlight {
background-color: yellow;
}
I am highlighted. I am not highlighted. I am highlighted. I am highlighted too.
And there we have it!
You are working with a team of developers and designers making the next award-winning website. The group of developers coding the markup has set up the HTML with different classes.
Three of these classes are given below together with the purpose they serve:
disabled
: gives a grey colorlarge
: gives a 30px font-sizestroked
: gives a 1px solid black border.
Your task is to write the CSS code to implement these given class specifications.
The question is pretty straightforward. We just need to use the aforementioned classes and declare the desired rules for each of them.
.disabled {
color: grey;
}
.large {
font-size: 30px;
}
.stroked {
border: 1px solid black;
}
Universal selector
Ever thought of selecting all elements in an HTML document?
Well, the creators of CSS did so and, consequently, provided us with the universal selector.
The latter case here, that is, selecting all elements within elements matched by a previous selector, requires us to first learn about combinators in CSS. We shall do so in the next chapter.
The universal selector is denoted using an *
(asterisk).
Time for an example:
<div>
<p>This is a paragraph</p>
<div>This a div with a <span>span</span></div>
<p>This is another paragraph with <b>bold</b> text.</p>
</div>
Here we have a purposefully complex markup, with elements nested inside of elements. The reason for this complexity is so that we can clearly visualize the effect of the universal selector.
Let's now style this markup using the selector:
* {
border: 1px solid red;
}
This is a paragraph
This is another paragraph with bold text.
Notice how each single element here has the border around it, courtesy of the universal selector.
ID selector
As you may already know, HTML elements can be assigned unique IDs in a document using the id
attribute. This allows the elements to be used as destination anchors of given hyperlinks.
But another utility of IDs is to allow us to conveniently select a specific element in CSS for styling. This is precisely where the ID selector comes in.
The general form of an ID selector is #id
where id
is the ID of the element to select.
Consider the HTML below containing a <p>
element with ID p1
, which we'll now refer to compactly as #p1
(following the CSS selector syntax).
<p id="p1">A paragraph with ID 'p1'</p>
<p>Another paragraph</p>
We want to color this paragraph blue. Of course, one option is to go right in the HTML markup and use the style
attribute on the paragraph to specifically style it. But we're here to explore the ID selector so let's leverage the ID already assigned to this paragraph in order to style it:
#p1 {
color: blue;
}
A paragraph with ID 'p1'
Another paragraph
Perfect!
ID selector matches multiple elements!
As per the standard rules of HTML, IDs must be unique in a document. This means that ID selectors in CSS should match one and only one element in the underlying document.
However, probably for backwards compatibility, this is NOT the case. That is, an ID selector would match multiple elements if they all have that ID set on them.
Here's a concrete illustration:
<p>Paragraph with ID 'p1'</p>
<p>Another paragraph with ID 'p1'</p>
We have two paragraphs with the exact same ID. Let's see what happens after applying the following rule:
#p1 {
color: green;
}
Paragraph with ID 'p1'
Another paragraph with ID 'p1'
And there you have it. Both the paragraphs get styled, which means that #p1
selects both the paragraphs.
So is this a quirk in CSS? Well, I personally don't think so.
It's rather a quirk in our document's markup. As stated earlier, it's non-conforming to the standard to have an HTML document with non-unique IDs.
In case we don't abide by this rule of HTML, CSS doesn't care either.
Here's a quick task for you to quickly exercise what you've learnt about the ID selector.
Consider the HTML below:
<p id="p1">A sandybrown background</p>
<p id="p2">A seagreen color</p>
<p id="p3">A sandybrown background and 20px font-size</p>
Write CSS code to style this HTML such that it looks as follows:
A sandybrown background
A seagreen color
A sandybrown background and 20px font-size
(The desired styles for each element are given in its content.)
We ought to select and style the three elements individually using their respective IDs, i.e. using the selectors #p1
, #p2
and #p3
:
#p1 {
background-color: sandybrown;
}
#p2 {
color: seagreen;
}
#p3 {
background-color: sandybrown;
font-size: 20px;
}
Attribute selector
To base the criterion of selection of elements upon their attributes, we can leverage attribute selectors.
There are numerous variations of attribute selectors following from the numerous ways in which we might want to select elements containing given attributes.
For example, we might want to select elements that only have a particular attribute set on them, regardless of the value of that attribute. Or we might want to select elements that have an exact attribute-value pair.
In this section, we'll only concern ourselves with these two kinds, i.e. attribute's existence and attribute-value pair. We'll explore other variations in the upcoming chapters.
The general format of the first variation, where we check for an attribute's existence, is [name]
where name
is the name of the attribute.
The general format of the second variation, where we check for an exact attribute-value pair, is [name="value"]
, where name
is the attribute's name and value
is its value.
Let's consider examples for each variant.
Here's the HTML markup:
<button data-key="1">Button 1</button>
<button data-key="2">Button 2</button>
<button>Button 3</button>
First, let's select only the first button based on the value of its data-key
attribute and style it:
[data-key="1"] {
background-color: pink;
}
Perfect!
Now, let's select both the buttons with the attribute (irrespective of their individual values):
[data-key] {
background-color: pink;
}
Compound selectors
So now, by this point, we can easily select all HTML elements of a given type, belonging to a given class, having a given attribute, or having that attribute with a specific value, and so on.
These are all individual conditions that we can apply to select different elements.
But what if we wish to combine them together and further restrict the matching criteria?
For example, what if we want to select all <p>
elements that have the class intro
? Or what if we want to select all <a>
elements with the title
attribute set?
This is where compound selectors enter the game.
But what's a simple selector?
Well, it's the exact opposite of a compound selector:
All the selectors that we saw above are instances of simple selectors because they can't be broken further down.
For example, p
is a simple selector. There is no opportunity for further division in it. So is .intro
. So is [data-tooltip]
. And so on and so forth.
Coming back to the topic, a compound selector is what we get when we join together these simple selectors. Essentially, a compound selector is a means of applying multiple selection conditions for selecting given elements (each simple selector imposing a given condition).
Let's consider an example following from a question asked earlier.
Suppose we wish to select all <p>
elements with the class intro
in the following HTML:
<p>A paragraph</p>
<p class="intro">An intro paragraph</p>
<p class="intro">Another intro paragraph</p>
<div class="intro">An intro div</div>
Certainly the selector p
won't work because it selects all <p>
elements, some of which might not have the intro
class.
Similarly, the selector .intro
won't help here because it selects all elements with the class intro
, some of which might not be <p>
elements.
What we really need is to combine both these selectors together. The selector desired here is p.intro
:
p.intro {
background-color: yellow;
}
Notice how .intro
is joined with p
without any space in between. It means that we're imposing an additional condition before selecting <p>
elements, i.e. the <p>
elements must have the intro
class as well.
A paragraph
An intro paragraph
Another intro paragraph
The rules for writing compound selectors are pretty simple:
- If we need to include a type or universal selector, it must be at the very beginning.
- Type and universal selectors can appear at most once.
- There must be no space in between the selectors.
Let's take a bunch of examples to understand how to pair up multiple simple selectors together.
Suppose we wish to select all <a>
elements with the attribute data-tooltip
set (irrespective of its value). The following selector does this: a[data-tooltip]
. Notice the individual selectors a
and [data-tooltip]
.
Now, suppose we wish to select all <a>
elements with the class intro
and with the data-tooltip
attribute. The compound selector would therefore be: a.intro[data-tooltip]
.
If the attribute must be data-tooltip
with the exact value "-"
, then the selector would be: a.intro[data-tooltip="-"]
.
Try experimenting around with different compound selectors and creating different kinds of HTML documents to entertain them.
Universal selectors are mostly redundant in compound selectors!
While it's possible to combine the universal selector with other selectors to produce a compound selector, it often isn't required.
For example, the selector *[data-tooltip]
is precisely the same thing as [data-tooltip]
. Similarly, *.intro
is the same thing as .intro
.
In this respect, it won't be wrong to say that in most cases — in fact, almost always — using the universal selector in a compound selector is redundant.
Grouping selectors
Suppose we have to apply the exact same styles to all <h1>
, <h2>
, <h3>
, <h4>
, <h5>
, and <h6>
elements.
As a more concrete example, here's the rule for <h1>
:
h1 {
background-color: blue;
color: white;
padding: 10px;
}
Now should we repeat this same style for each of the six heading elements?
The good news is: NO!
Using the idea of grouping selectors, we can get the same declaration block to apply to multiple selectors, without having to redefine that declaration block multiple times.
,
(comma) character is used to group multiple selectors together.For example, h1, h2
matches all <h1>
and <h2>
elements. Similarly, p, .intro
matches all <p>
elements and all .intro
elements.
A group of selectors, for e.g. h1, h2
, is sometimes also referred to as a selector list in CSS.
Here's the problem stated above solved:
h1, h2, h3, h4, h5, h6 {
background-color: blue;
color: white;
padding: 10px;
}
The long selector h1, h2, h3, h4, h5, h6
matches all heading elements and keeps us from having to repeat the declaration block for each heading element.
Invalid selectors in selector lists
An important thing to note while working with selector lists is that even if one of the selectors in a selector list is invalid, CSS would skip the entire rule.
This is undoubtedly something to watch out for!
Consider the following example:
<p>This is a paragraph</p>
<p>This is another paragraph</p>
<div>This is a div</div>
p, div, 67 {
background-color: yellow;
}
We deliberately have an invalid selector in the group of selectors, p, div, 67
— that is, 67
is the culprit here. As a consequence, the entire ruleset is skipped by CSS.
This is a paragraph
This is another paragraph
Removing the 67
resolves the issue:
p, div {
background-color: yellow;
}
This is a paragraph
This is another paragraph
Spread the word
Think that the content was awesome? Share it with your friends!
Join the community
Can't understand something related to the content? Get help from the community.