CSS - Other Selectors
In our previous article Introduction to CSS Selectors, we discussed commonly used selectors such as element selectors, ID selectors, and class selectors. In this tutorial, we will cover other kinds of selectors often used when styling HTML elements with CSS rules. We will cover the following selectors:
- Universal selector
- Attribute selectors
- Pseudo-classes
- Pseudo-elements
- The combinator selectors
The universal selector
The universal selector uses the asterisk symbol (*) to represent and select all the elements on a page. The general syntax is:
* {
declaration_1;
declaration_2;
}
For example, to create a rule that sets margins and padding to zero for all the elements on our web page, we can use the universal selector:
* {
margin: 0;
padding: 0;
}
Attribute selectors
An attribute selector is used to select only those elements on our page that have a certain attribute with a given value. The general syntax for an attribute selector is:
element[attribute_name="attribute_value"] {
declaration_1;
declaration_2;
}
To target all the div elements that have the class="my-class" attribute and value, we write:
div[class="my-class"] {
color: blue;
}
This selector will target all div elements having the class attribute with the value of "my-class". This selector will target all of the following elements on our page:
<div class="my-class">This is the first div.</div>
<div id="my-id" class="my-class">This is the second div.</div>
<div role="button" class="my-class">This is the third div.</div>
And apply a blue text color to all of them, because all these div elements have the required class attribute with the specified "my-class" value. These divs can also have other attributes as well, and they will still be targeted by our CSS rule.
If we want to target all the div elements that have an id attribute with the value of "my-id", in our stylesheet we write the following CSS selector:
div[id="my-id"] {
color: red;
}
To target all the p elements that have a data-name attribute with a value of "my-value", we use the following CSS attribute selector:
p[data-name="my-value"] {
color: red;
}
We can also use the attribute selector that selects all elements having a certain attribute, regardless of the attribute's value. The general syntax is:
element[attribute_name] {
declaration_1;
declaration_2;
}
For example, to target all the div elements that have a role attribute, regardless of that attribute's value (which might or might not be present), we write the following CSS rule:
div[role] {
color: blue;
}
To target all the div elements having the id attribute, regardless of the attribute's value, we write:
div[id] {
color: red;
}
Pseudo-classes
Our HTML elements can be in certain states, and we can use pseudo-classes to target those elements, based on these states. A pseudo-class starts with a colon symbol (:) followed by a predefined pseudo-class name. The general syntax is:
element:pseudo-class-name {
declaration_1;
declaration_2;
}
For example, to target the element that is being hovered over, we use the :hover pseudo-class. Usually, an anchor link element can be hovered over, so we use the :hover pseudo-class added to the <a> element:
a:hover {
text-decoration: underline;
}
Now, all links being hovered over will have their text styled with an underline.
The :visited pseudo-class name can be used to target previously visited elements, usually the link elements:
a:visited {
color: blue;
}
The :focus pseudo-class targets the element that currently has focus. For example, we can use this pseudo class to target an input element that currently has focus:
input:focus {
background-color: lightgreen;
}
If we want to target a button element that is in the hover state, we would write the following CSS:
button:hover {
background-color: gray;
}
To select the first child element in a container/group, we use the selector:first_child pseudo-class. For example, to target the first child that is the li element inside the ul container, we write:
ul li:first-child {
background-color: green;
}
This selector selects the first child li element in the ul container. To target a specific element that is the first child, we specify the element name followed by a ::first_child pseudo class. For example, if we have the following HTML code snippet:
<ul>
<li>This is the first list item.</li>
<li>This is the second list item.</li>
<li>This is the third list item.</li>
</ul>
And we use the following CSS code:
li:first_child {
background-color: green;
}
This selector will select only the first <li> item element that is the first child of its parent container.
Pseudo elements
Pseudo-elements are used to style specific parts of an HTML element, rather than the whole HTML element. Pseudo-elements exist only as a part of a regular HTML element.
For example, an HTML element can have a part that comes before the element's content, after the element, a part that is the first line of text, a part that is a selected text and so on. For all these different parts of our HTML element, there are dedicated pseudo element names that start with a double colon ::, followed by a predefined pseudo-element name.
In this article, we will look at the two, most-widely used pseudo elements: ::before, and ::after.
The ::before pseudo-element
The ::before pseudo-element creates the part of the element which comes before the element's content. To style the ::before part of our element, we specify a CSS selector, followed by a pseudo-element name:
selector_name::before {
declaration_1;
declaration_2;
}
When we use the ::before pseudo element, we create an inline box that is part of our main element. And that box is positioned before the remaining content of our element.
We can use it on a list item li to specify a bullet point image, usually using the content CSS property, which populates the actual content of the element:
li::before {
content: url('images/my-image.png');
margin-right: 10px;
}
Note: Replace my-image.png with your image name.
Now, all list items will have the specified image of my-image.png acting as a bullet point in front of all list item elements.
We can also style the ::before pseudo-element to add additional characters to a link element:
a::before {
content: "«";
margin-right: 10px;
}
This rule adds a left-pointing double arrow character before our link element. This can be useful when styling Previous buttons or links.
The ::after pseudo-element
The ::after pseudo-element creates/represents the inline box that comes after the element's contents. It represents the rectangular area within our HTML element, a last child of our HTML element. The general syntax is:
selector_name::after {
declaration_1;
declaration_2;
}
To style the link element's after box (the end of the link element) using the ::after pseudo-element, we write:
a::after {
content: "»";
margin-left: 10px;
}
This rule adds a right-pointing double angle quotation mark character to our link's ::after element (to the end of our link's content). It is the content that is positioned at the end of our a link element. This can be useful when styling the Next navigation buttons or links.
Pseudo-elements and CSS classes
We can also apply a pseudo-element to an element that has a certain CSS class. The general syntax is:
.css_class_name::pseudo_element {
declaration_1;
declaration_2;
}
For example, if we have the following HTML snippet:
<a class="my-class" href="https://www.example.com">example.com</a>
And we want to style the element's ::before pseudo-element, we would write:
.my-class::before {
content: "▶";
margin-right: 10px;
}
In production, when styling the Previous and Next buttons, you will often see CSS rules for both the ::before and ::after pseudo-elements:
.my-class::before {
content: "‹";
margin-right: 10px;
}
.my-class::after {
content: "›";
margin-left: 10px;
}
The combinator selectors
The combinator selector combines several selectors such as parent (ancestor) selectors and child (descendant) selectors and selects the right-most selector element if it fits into the hierarchy of specified parent selectors. The general syntax is:
parent_selector combinator_symbol child_selector {
declaration_1;
declaration_2;
}
Here, we will explain two CSS selector combinators used to select elements that are direct or indirect child elements of their parent/ancestor elements. These combinators are:
- Descendant combinators: (
) - Direct child combinators: (
>)
Descendant combinator
The descendant combinator is a space symbol placed between the selectors, usually between the parent selector and a child selector. It selects a child element, represented by a right-most selector, only if it is a direct or indirect child/descendant of an ancestor element. The general syntax is:
parent_selector child_selector {
declaration_1;
declaration_2;
}
An example of a CSS rule that selects all p elements that are direct or indirect descendants of an element with a .my-class class is:
.my-class p {
declaration_1;
declaration_2;
}
The above code will select all child p elements in the following HTML snippet:
<div class="my-class">
<p>This paragraph will be selected by the descendant CSS combinator.</p>
<p>This paragraph will also be selected by the descendant CSS combinator.</p>
</div>
The descendant combinator also targets indirect child p elements, as shown in the following HTML snippet:
<div class="my-class">
<div class="other-class">
<p>This paragraph will be selected by the descendant CSS combinator.</p>
<p>This paragraph will also be selected by the descendant CSS combinator.</p>
</div>
</div>
To select all direct or indirect child p elements inside an article element, we write:
article p {
declaration_1;
declaration_2;
}
This selector targets all p elements inside an article element, whether they are direct children of the article element:
<article>
<p>This paragraph will be selected by the descendant CSS combinator.</p>
<p>This paragraph will also be selected by the descendant CSS combinator.</p>
</article>
Or indirect children of the article element, as in the snippet below:
<article>
<div class="some-class">
<p>This paragraph will be selected by the descendant CSS combinator.</p>
<p>This paragraph will also be selected by the descendant CSS combinator.</p>
</div>
</article>
Or a combination of the two:
<article>
<p>This paragraph will be selected by the descendant CSS combinator.</p>
<div class="some-class">
<p>This paragraph will also be selected by the descendant CSS combinator.</p>
</div>
</article>
We can also specify several parents and target the child elements for a given element hierarchy. Example:
body article p {
/* ... */
}
The code above targets only paragraphs nested directly or indirectly inside an article element, which is in turn nested inside a body element. Example:
<body>
<article>
<p>This paragraph will be selected for styling.</p>
<p>This paragraph will also be selected for styling.</p>
</article>
</body>
The above CSS rule also targets p elements that are indirect children of the <body> - <article> hierarchy, meaning they are deeply nested inside these elements:
<body>
<article>
<p>This paragraph will be selected for styling.</p>
<div>
<p>This paragraph will also be selected for styling.</p>
</div>
</article>
</body>
The article element does not have to be a direct child of the body element, but it must be a child element, and all the p elements inside it will still be selected as in the following HTML snippet:
<body>
<div>
<article>
<p>This paragraph will be selected for styling.</p>
<p>This paragraph will also be selected for styling.</p>
</article>
</div>
</body>
The child combinator (>)
The child combinator symbol > can be placed between the parent and the child selector, and it will only select the child elements that are direct children of a given parent element (selector). The general syntax is:
parent_selector > child_selector {
declaration_1;
declaration_2;
}
For example, to select all child p elements that are direct children of an element with the my-class class, we write:
.my-class > p {
declaration_1;
declaration_2;
}
This code will select only the direct children p elements wrapped inside an element/container with a my-class class:
<div class="my-class">
<p>This paragraph will be selected by the direct child CSS combinator.</p>
<p>This paragraph will also be selected by the direct child CSS combinator.</p>
</div>
But it will not select the p elements that are not direct children of the parent element, elements that are deeply nested:
<div class="my-class">
<p>This paragraph will be selected.</p>
<p>This paragraph will also be selected.</p>
<div>
<p>This paragraph will not be selected.</p>
<p>This paragraph will not be selected.</p>
</div>
<p>This paragraph will also be selected.</p>
</div>
To target only direct p children of an article element, we write:
article > p {
/* ... */
}