HTML was never intended to include formatting. It is used to describe the structure and content of a web page.
CSS was introduced to allow style formatting.
Three main categories:
We have different options on how to add styling.
Add a link tag to the HTML head with the href pointing to the CSS file:
CSS is a rule-based language: you define the rules by specifying groups of styles that should be applied to particular elements.
One rule consists of selector and declaration block:
selector { /* <- e.g. class name */
property: value; /* <- declaration */
}
Some specific properties can be grouped with a shorthand version.
div {
background-image: url('logo.png');
background-position: top left;
background-repeat: no-repeat;
}
Can be simplified with the background shorthand:
div {
background: url('logo.png') top left no-repeat;
}
Also known as "CSS Variables", these allow to easily reuse values:
:root {
--primary-color: yellow; /* declare it, prefixed with double dash */
}
p {
color: var(--primary-color); /* access value with var() */
}
We can use the style attribute to define styles for our HTML elements, using the following syntax:
Paragraph text in red.
Paragraph text in red.
We write a meaningful name into the class attribute:
Paragraph text in red.
Then we can reference this class in CSS prefixed with a dot:
Elements can have multiple classes, which applies multiple rules:
Paragraph text in red.
What happens if we combine classes and inline styles?
Is it red or blue?
It's blue!
Inline styles take precedence.
Why use classes instead of inline styles?
Classes aren't our only way to target elements. We can use different identifiers from our HTML as selector:
We can list multiple selectors separated with comma to apply the same rule to different elements:
p, li {
color: red;
}
Some elements should look different based on where they are.
/* span that are descendants of a li */
li span {
color: red;
}
red text
red text
Use > to style only direct child elements.
/* span that are direct children of a li */
li > span {
color: red;
}
other text
red text
Select next adjacent siblings following an element with +.
/* p that are adjacent siblings following a ul */
ul + p {
color: red;
}
some paragraph content
...
red text
some more paragraph content
We can combine selectors to target more specific elements:
div.banner a
form#upload button:enabled
ul > li
section p + p
Since December 2023 all major browsers support CSS nesting.
Nesting (along with variables) used to be a major argument for preprocessors and has now finally found it way into the CSS standard.
ul {
font-size: 1.2rem;
li {
color: red;
}
}
is parsed as:
ul {
font-size: 1.2rem;
}
ul li {
color: red;
}
The new & nesting selector is used to explicitly specify the relationship between parent and child.
a {
&:hover {
color: red;
}
}
turns into:
a:hover { /* without "&" it would be: a *:hover { … } */
color: red;
}
The nesting selector doesn't have to be at the start:
h2 {
color: blue;
.highlight & {
color: red;
}
}
turns into:
h2 {
color: blue;
}
.highlight h2 {
color: red;
}
Nesting helps with readability and maintainability of CSS. It can also be used with "at-rules" such as media or container queries.
It's especially helpful to override special cases like hover states or responsive behaviour.
But: don't nest just because you can. Don't bloat the selector unnecessarily.
There are plenty more examples and in-depth explanations in the CSS nesting section on MDN.
Specifies a size in exact pixels
rem: specifies a size relative to the root font size
em: specifies a size relative to the font size of the element being styled
CSS offers a calc() function for basic math operations. It allows different units:
div {
max-width: calc(80% - 100px);
height: calc(100vh / 3);
}