Websites are built by these three languages:
«Elements» are the building blocks of web pages, for example:
<h1> – Headings<p> – Paragraphs<a> – Links (a = anchor)<img> – Images<table> – Tables<input> – Input fields (text, number, date, etc.)<header>)href="…")<br>)Example: <div class="container"><p>Hello</p></div>
The hierarchy (a tree structure) matters for CSS:
<!DOCTYPE html>
<html>
<!-- non visible meta information in "head" -->
<head>
<meta charset="UTF-8">
<title>Page Title</title>
</head>
<!-- visible content belongs inside "body" -->
<body>
<main>
<p>Content goes here</p>
</main>
</body>
</html>
Most HTML elements have semantic meaning (keyword: «semantic HTML»). This provides context to the content and also allows parsing websites automatically (e.g. by screen readers).
CSS uses the hierarchy to define styling rules and relationships between elements.
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.
style attribute on any HTML element<style> tagAdd 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;
}
margin and padding instead of their specific
top, right, bottom, left versions
font to set font family, size, weight and styleborder for size, color and style of the border on all sidesAlso 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.
But, there's a better way …
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:
div, input, h1…
.red, .primary-button, …
#title, #submit, …
[type=radio], [href^="#"], …
:hover, :disabled, :last-child,
…
::before, ::placeholder, …
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.
px: size in exact pixelscm/mm: size in metric units (e.g. useful for
print)
rem: size relative to the root font size (<html>)
em: size relative to the font size of the element itselfrem?px this preference is ignoredrem everything can scale accordingly%: relative to another value, depending on where it's used
Units relative to the viewport (usually browser window size):
vh/vw: percentage of viewport, height and
width
1vh = 100% of viewport height)
vmax/vmin: the max, resp.
min, dimension of the viewport
sv*/lv*/dv*:
small, large and dynamic viewport sizes for dynamic browser
interfaces (i.e. address bar on mobile)
CSS offers a calc() function for basic math operations. It allows different
units:
div {
max-width: calc(80% - 100px);
height: calc(100vh / 3);
}