Cascading Style Sheets (CSS) allow you to transform the appearance of your web pages. From fonts and colors to spacing and general layout, all sorts of design tools are at your fingertips. Although CSS is a complicated language in its entirety, there are only two basic concepts you need to understand to get started.
It all starts with identifying the exact part of a page you want to style.
CSS = Selectors + Declarations
A CSS file contains a series of rules describing how an HTML file should be formatted. Each rule consists of two parts: what to style and how to style it. The first part is controlled using a series of terms called “selectors”.
The examples in this article include style declarations, but they aren’t the focus: the selectors themselves are.
Historically, there were three CSS selector levels (or versions) with varying degrees of browser support. In 2020, according to Can I use, they are all available to more than 99% of users worldwide.
Level 1 selectors
Level 1 introduced the four fundamental types of selectors which cover a large number of cases even today.
Diagram | matches |
---|---|
E |
all E-elements |
.c |
all elements with class=”c” |
#myid |
the element with id=”myid” |
E F |
an F element inside an E element |
Pseudo-classes | |
E:link |
a hyperlink to a page that has not been visited before |
E:visited |
a hyperlink to a previously visited page |
E:active |
a currently selected hyperlink |
Pseudo-elements | |
E::first-line |
the first formatted line of an E element |
E::first-letter |
the formatted first letter of an E element |
Type selector
The simplest selector is the “type selector”. It targets all instances of an element, such as a paragraph or bold text:
p { margin-bottom: 0; }
b { font-family: sans-serif; }
Class selector
The class attribute allows additional semantics to be added to an HTML element, such as a specific type of paragraph. These elements can be selected in CSS as follows:
.intro { font-weight: bold; }
This selector would correspond to:
…
But note that this would also match:
…
If you want it to only apply to introductory paragraphs, you can combine the type selector and the class selector:
p.intro { font-weight: bold; }
ID selector
The HTML id attribute must be unique within a document, for example if you have:
…
This should be the only element with a “content” id. An ID selector lets you target that specific element in a document:
#contents { color: #333; }
Down selector
Strictly, a “combiner”, because this selector concerns the space between two others. HTML is hierarchical, as explained in our DOM overview. A descendant selector identifies an element by its context within another element:
table b { font-weight: normal; }
Pseudo classes and elements
Pseudo selectors target classes or elements that don’t explicitly exist but are still available. Think of them as special content bonuses:
p::first-line { text-transform: uppercase; }
Selector lists
Use a comma to combine selectors in a list if you want to apply the same set of rules to each. In the place of:
th { padding: 1em; }
td { padding: 1em; }
You can write:
th, td { padding: 1em; }
Specificity
A style sheet is a series of rules that use a selector to match an element, but what happens when multiple rules match a given element? The resulting behavior is governed by “specificity” which defines which rule is used in a case such as:
p.intro { color: black; }
p { color: gray; }
In such cases, the priority rule is defined by its specificity, as follows:
- The ID selectors (`#contents`) are the most specific.
- Class selectors (`.author`) are less specific.
- Type selectors (`p`) are the least specific.
When calculating specificity, each level is only considered if two selectors have the same score at the higher level, so “#contents” is more specific than “article.news p.author.special” because the first ” wins” on ID selectors.
Level 2 selectors
The next revision of CSS selectors introduced attribute selectors, expanded pseudo-classes and pseudo-elements, and added two new combinators.
Diagram | matches |
---|---|
* |
any element |
E > F |
an F element child of an E element |
E + F |
an F element immediately preceded by an E element |
Attribute selectors | |
E[foo] |
an E element with a “foo” attribute |
E[foo="bar"] |
an E element whose “foo” attribute is exactly “bar” |
E[foo~="bar"] |
an E element whose “foo” attribute is a space-separated list of values, one of which is “bar” |
E[foo|="en"] |
an E element whose “foo” attribute has a hyphen-separated list of values beginning with “en” |
Pseudo-classes | |
E:first-child |
an element E, first child of its parent |
E:lang(fr) |
an E-type element in “fr” language |
Pseudo-elements | |
E::before |
content generated before the content of an E element |
E::after |
content generated after the content of an E element |
Universal Selector
The “*” matches any element. This isn’t often very useful, but if you want to reset default margins, for example, you can do this:
* { margin: 0; }
Attribute selectors
Attribute selectors allow very specific targeting of styles, filtered by an element’s attribute:
aHow to Target Part of a Web Page Using CSS Selectors { text-decoration: underline dotted; }
Child Combinator: one element immediately inside another
Similar to the descendant combinator, but this only matches immediate children, not descendants further down the tree. For example, “ul > li” will only match the text “Section 1” here, not “Section 1.1”:
Section 1
- Section 1.1
- Section 1.2
Combinator of adjacent siblings: the next sibling
h1 + p { font-weight: bold; }
Often useful for controlling margins, or a specific classless introductory paragraph, this selector matches an element only if it immediately follows another. In the example, only the first paragraph here will be matched, not the second:
Contents
some extra text
Introductory paragraph
Following paragraph
Note that this selector only considers the elements, not the text, to decide which is the next sibling.
Heritage
Some CSS properties inherit their value from an ancestor element. In practice, this means, for example, that setting the font of the “body” element means that every paragraph, table, etc. also uses this same font.
Sure, that’s exactly what you’d expect, but consider a property that doesn’t inherit: “margin”, for example. You wouldn’t want each individual paragraph or piece of bold text to have the same margin as the whole document.
A good rule of thumb is to target items as broadly as possible. Don’t target each element individually when a simple “body” selector will suffice.
Level 3 selectors
Many other pseudo-classes have been added at this level, as well as attribute selectors and a new combinator.
Diagram | matches |
---|---|
E ~ F |
an F element preceded by an E element |
Attribute selectors | |
E[foo^="bar"] |
an E element whose “foo” attribute begins with the string “bar” |
E[foo$="bar"] |
an E element whose “foo” attribute ends with the string “bar” |
E[foo*="bar"] |
an E element whose “foo” attribute contains the substring “bar” |
Pseudo-classes | |
E:root |
an element E, document root |
E:nth-child(n) |
an element E, the n-th child of its parent |
E:nth-last-child(n) |
an element E, the n-th child of its parent, starting from the last |
E:nth-of-type(n) |
an element E, the n-th sibling of its type |
E:nth-last-of-type(n) |
an element E, the n-th sibling of its type, from the last |
E:last-child |
an element E, last child of its parent |
E:first-of-type |
an element E, first sibling of its type |
E:last-of-type |
an element E, last sibling of its type |
E:only-child |
an element E, unique child of its parent |
E:only-of-type |
an element E, the only sibling of its type |
E:empty |
an E element that has no children (including text nodes) |
E:target |
an element E being the target of the referrer URI |
E:enabled |
a user interface element E which is activated |
E:disabled |
a UI element E that is disabled |
E:checked |
a UI element E that is checked |
E:not(s) |
an element E that does not match the simple selector s |
Attribute selectors
You can select elements with an attribute starting with a given value: a[href^="https:"]
, ends with a given value: img[src$=".gif"]
, or contains a value: a[*="value"]
.
Pseudo-classes
Additional pseudo-classes include “:last-child”, “:empty” (to match an element with no content), and “:checked” which matches an element as a checkbox input, but only when it is checked.
General Sibling Combinator: A Next Sibling
Similar to the level 2 adjacent sibling combiner, this matches any sibling that comes after the other, not just the next one:
h1 ~ p { font-size: 110%; }
CSS selectors and how to use them
You now know pretty much everything there is to know about how to select part of a webpage using CSS. You are now ready to style your pages with the wide variety of CSS properties that cover everything from colors to layout.
Image Credit: Pankaj Patel/Unsplash
Read more
About the Author