HTML & CSS: the essential parts
ARTICLE — last updated:This is somewhat of a reference of all the stuff I had to gather, from various sources, about HTML5 and CSS.
Introduction
If you know nothing about HTML and/or CSS, thankfully the web provides a lot of great tutorials. (See also: Khan Academy, MDN.)
The two major references on tags, attributes, and other info you might want when building a site are:
- The Mozilla Developer Network, aka MDN. It’s usually thorough, but the presentation is clumsy.
- W3Schools. Some people hate this site because it used to present out of date information, or because it doesn’t use the latest trendy design. It’s a bit lighter than MDN on the details, but the site itself loads very fast, which is useful on a bad connection. For HTML stuff, which doesn’t change every Sunday morning, I’ve found it a valuable reference.
HTML
The latest version of HTML is called HTML5, and it’s the one you should use, as it brings several interesting features that makes it easier to create documents. (Together with CSS3.) We’ll go through an overview of some of the interesting features.
First, let’s have a look at a minimal HTML5 document:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="//example.com/css/style.css">
<title>Title</title>
</head>
<body>
Content.
</body>
</html>
(I keep a copy of this code somewhere in my files; it’s a useful template to have.)
Metadata
Going through the elements one by one:
<!DOCTYPE html>
just declares that your file is an HTML5 document. There are various other doctypes for other kinds of documents, including older versions of HTML.<meta charset="utf-8">
declares that your document uses UTF-8 encoding. You can use other encodings, but for most intents and purposes, UTF-8 is the best choice. Note: it is best practice to put it within the first 1024 bytes of the file—usually you just make it the first element withinhead
— because some parsers rely on that to determine the charset.<meta name="viewport" content="width=device-width, initial-scale=1>"
is a fix for mobile devices. Mobile browsers tend to resize sites that are too large to fit inside the screen. This tag fixes it, but you’ll have to make sure that your site is properly designed. We’ll cover that in the CSS part with media queries.<title>Title</title>
is simply the title that’s going to be displayed in the tab bar of your browser.
These four elements are the bare minimum you have to put in your header. Josh Buchea has a fairly exhaustive list of all interesting tags you can put in the header on GitHub. A lot of them are related to backwards compatibility and fixing weird browser behaviour, but there are a few that are interesting:
<link rel="stylesheet" type="text/css" href="http://example.com/css/style.css">
links to an external style sheet. You can replace it with a simple<style>...</style>
block in the header if you want to inline the CSS code rather than fetch it externally. (It can be useful for a one-off page, but if you’re gonna be using the same CSS accross various pages, it’s best to use an external one as the browser will cache the CSS.) As a last resort solution, you could also inline the CSS inside the HTML elements using thestyle
HTML attribute, but that can become rather ugly pretty quick.<base href="http://www.example.com/directory/">
allows you to set the base address used in all relative URLs throughout the document. It also works for other header elements, so you might want to put that one first.<script>…(javascript code)…</script>
inserts JavaScript code in the header. It’s usually best practice NOT to put it there, and have it at the right before the closingbody
tag, because JavaScript parsing and execution is blocking the parsing and rendering of the rest of the page. If you still want to have it in your header, HTML5 introduces two attributes that mitigate that:async
will make your script execute while the rest of the page is still parsing, anddefer
will wait until the page is fully parsed to execute your script. See the gory details on MDN.There’s a large list of
meta
/ attribute combinations that will allow you to get better metadata, which in turns will improve your search engine referencing, if you care about that stuff.Similarly, there’s a good number of
link
/ attribute combinations that are useful to describe the structure of your site, which will help automated crawlers like seach engines figure out your site.
Main content
Structuring
If you were taught HTML and CSS layout in the old school ways, you might just want to structure your body
with divs (and relevant CSS classes). It’s totally legit, but HTML5 introduced a neat thing called semantic tags, which is a collection of tags that describe the semantic structure of your document. You can go pretty far with only these—and this very blog uses them a lot.
main
should be used to denote the main content of your document, and it is special in that there should be one in the document. header
and footer
are used to delimit respectively the header and footer of any part of your document. You can use them as many times as you want, fractally. So you can have something like this, with two headers at two different levels:
<body>
<header>Document header</header>
<main>
<header>Main content header</header>
Content
</main>
<footer>Document footer</footer>
</body>
nav
elements are meant precisely for the navigation part of your document, if your site has one. Some sites typically have a lot of links in the main footer as well; no need to replace it with a nav
element: nav
is more meant for the part that contains the major navigation elements. The standard is a bit vague on what this means though, so feel free to do as you fancy.
Inside the main part, the content may be subdivided further with article
and section
. An article
should wrap something that is independent and could be extracted from its surrounding context—basically, anything that would fit in an RSS feed, like a news article, a blog post, or even a comment. A section
is a more generic delimiter, and should typically contain (as its first child) a heading. So, for example, a long blog article could contain various sub-sections, each within its own section
tag pair.
…
<main>
<header>…</header>
<article>
<header><h1>Article title</h1></header>
<section>
<h2>First subtitle</h2>
Contents of first section.
</section>
<section>
<h2>Second subtitle</h2>
Contents of second section.
</section>
…
</article>
</main>
…
Finally, aside
can be used for content that is tangentially related to the main content. You can use it at several levels, for example to separate content in the margin or in a box, but you can also use it at a higher level to separate, for example the content inside main
from, for example, an automatically generated set of links to related articles.
Elements
There’s a wealth of tags between old and new HTML standards; I’ll just cover here a subset of the ones I’ve found the most useful.
For list of elements, you can use either ul
or ol
for (respectively) unordered and ordered lists. Within a pair, you’ll use li
pairs to delimit the elements of the list.
To master HTML and CSS, you need
<ul>
<li>Patience</li>
<li>Preferably some way to access the internet</li>
<li>Some way to cope with the inevitable anger that results
from dealing with a lot of HTML and CSS issues</li>
</ul>
For dictionary-like lists, you can use the dl
, dt
and dd
tags:
<dl>
<dt>HTML</dt>
<dd>A language designed to torture both web browsers and web developers.</dd>
<dt>CSS</dt>
<dd>A presentation language that still, in 2017, lacks several
key features for handling typography and presentation properly.</dd>
</dl>
For general tables, you want to use the table
, tr
and td
/ th
elements (and possibly a few others).
<table>
<tr>
<th>Tag</th>
<th>Meaning</th>
<th>Usefulness</th>
</tr>
<tr>
<td>TR</td>
<td>Table Row</td>
<td>Can't have a table without one of these bad boys!</td>
</tr>
<tr>
<td>TH</td>
<td>Table Header</td>
<td>Optionally gives your columns headers.</td>
</tr>
<tr>
<td>TD</td>
<td>Table Data</td>
<td>Defines a cell in your table.
Why didn't the W3C use TC instead?</td>
</tr>
</table>
Figures (like images or tables) can be embedded into a figure
tag pair, together with a figcaption
.
<figure>
<img src="/static/figure1.png">
<figcaption>Figure 1: graph of developer hopelessness
as a function of complexity of web features used.</figcaption>
</figure>
Another neat addition of HTML5, the details
and summary
pair works together to give a collapsible element:
A list of prime numbers smaller than 20.
2, 3, 5, 7, 11, 13, 17, 19
(Click / tap the small triangle on the left.)
<details>
<summary>A list of prime numbers smaller than 20.</summary>
2, 3, 5, 7, 11, 13, 17, 19
</details>
We can now have a look at some of the most useful inline elements. em
and strong
are typically useful for (respectively) increasing levels of emphasis. mark
is used to… mark text that doesn’t necessarily have any importance. s
will strike through text, while i
will typically set text in italic type, useful to differentiate some texte written in a different language. (Most Markdown renderers are unable to understand the nuance between that and emphasis, unfortunately.) time
should be used to represent either a clock time or a date and time in the Gregorian calendar.
Making the CSS responsive kept me awake until <time>01:00AM</time>.
The coding duel is set to happen at dawn on the <time datetime="2017-07-01T06:00Z">first of July of 2017</time>.
Finally, you can use q
to quote inline (Tempora mori, tempora mundis recorda
), and its bigger brother blockquote
for separate block quotes—possibly with a footer
wrapped inside to indicate the source of the citation.
Nove sed non nova : la manière est nouvelle, mais non la matière. Citation que j’ai jamais pu replacer correctement dans une conversation.
Check out MDN for a full list of the possible elements.
CSS
CSS has several different roles: layout, typography, and general graphic design (colors, shapes, animations…). It can do all of these things, although the degree to which it can do them is barely satisfactory. (If not less.)
There are several ways to work with CSS; you can use a framework like Bootstrap (or Pure, Tachyons, …) which will handle (mostly) the layout part and then bend it to your will to customize the appearance and typography. This is perfectly fine, especially for large projects, but it comes at a cost; you’re paying in terms of bloat (for the end user), and in terms of complexity (for you, developer). For simple pages, a simple, hand-built CSS might very well suffice. As a bonus, learning to build a CSS from scratch can also help you debug CSS problems, including in other people’s frameworks.
Selectors and pseudo-classes
CSS-Tricks has an nice intro if you need to learn or re-learn CSS selectors. MDN also has one.
A neat thing that’s possible with HTML5 structural elements is that you don’t need to define a class for everything. Instead of something like this:
<body>
<header class="page-header"></header>
<main>
<article>
<header class="article-header"></header>
</article>
</main>
</body>
.page-header {
}
.article-header {
}
You can simply forget the classes and use child and descendant selectors
/* select only the header tags that are direct children of body */
body > header {
}
article > header {
}
There’s a good number of CSS pseudo-classes (as well as a few pseudo-elements). I’ve found that :root
, :not()
and the various :*child*
are the most useful classes, as well as the ::before
and ::after
elements. I won’t give examples here, as they are highly situational, but be aware that these exist.
Variables and calc
Perhaps one of the most undersold CSS features is the ability to manipulate variables, or custom properties as they are sometimes called. Wherever you can put a property, you can put a custom property by prefixing the name of your choice with --
. You can then reuse that property (which really is just a variable) with the var()
function.
a {
--link-color: #d6bdbf;
color: var(--link-color);
}
Not only these variables alleviate the need for a CSS preprocessor, they are actually better than preprocessor variables with their ability to cascade (and be selectively overridden, much like general properties) and to be changed at runtime via JavaScript—the browser will make sure to repaint as needed. One of the simplest way to use them if you just want global variables is to simply declare them within the :root
pseudo-class:
:root {
--text-color: #111111;
--bg-color: #eeeeee;
--first-accent-color: #85b5cc;
--second-accent-color: #cc8727;
}
You can then use the variables everywhere.
Another very neat addition to CSS3 is the calc()
function, which allows you to set a property to be the result of a computation. It is extremely useful for laying out things. CSS-Tricks has an article with several examples.
Reset and normalize
Web browsers interpret the standards somewhat differently, and this results in very different defaults across both browsers and platforms. To fix this, web developers will never start a CSS from scratch but generally use either a reset or a normalize. A reset is just some CSS code that will reset CSS properties to a more practical set of default values, which you will generally want to override because, for example, some elements are completely unstyled. On the other hand, a normalize will set usable but arbitrary default values for everything. Here’s a Stack Overflow answer that explains the situation more in-depth.
I’m personally using a subset of the reset presented here. Since I don’t really care about supporting out-of-date browsers, I can get away with only a minimal set of reset rules. I don’t use the reset rules for the tags I don’t use, and I don’t use those reset rules that I will override later anyway. This makes the CSS file leaner, which is a benefit both for me as the developer but also for my users.
Typographic good practices
Matthew Butterick has written a very good free book called Practical Typography which I encourage you to read. It contains some CSS specific advice, and some general practical advice about typography.
Some of the most important takeaways (that I routinely see violated on the Internet in general): use bigger fonts, limit your line length, limit the amount of color and decoration on the page, and in particular limit contrast. These few simple rules will make the page incredibly more easy to read and look at in general.
Layout
Learn Layout offers a very nice introduction to the old-school art of laying out pages with divs, floats and the box model in general. It’s short and you should understand all the concepts there, only to use the superior flexbox for laying out the general structure of your page. Philip Walton has an amazing page called Solved by Flexbox which explains in detail how you can use flexbox for some of the most common page layouts out there. CSS-Tricks has a very comprehensive page about flexbox that explains visually all its properties. FreeCodeCamp has something similar, but with GIFs instead.
Media queries and responsive web design
Media queries allow you to apply certain CSS rules depending on the output media for the page (display, printer, …) and on some other conditions (page width, orientation, …).
By far the most useful usage of media queries is to reorganize the layout of the page depending on the width of the output device. Typically, this allows you to choose from a stacked top-to-bottom layout (for mobile) into a two-column or more grid-like layout for desktop.
If you use flexbox, you can for example switch the orientation of the flex depending the width:
.grid-container {
position: relative;
display: flex;
flex-direction: column;
align-items: flex-start;
}
@media (min-width: 768px) {
.grid-container {
flex-direction: row;
align-items: flex-start;
}
}
Check out Solved by Flexbox for more details.
You can choose to make your rules mobile-friendly and then add media-queried rules for desktop, or the other way around; there isn’t much of a difference if you don’t care particularly about backwards compatibility. If you do, it’s usually better to focus on mobile first, as mobile browsers tend to be older.
Google has a nice small guide on how to make a website responsive. There are a lot of contradictory opinions on the subject in the web development community in general (with regards to break points, units, whether responsive is worthwhile or not…)—you want to keep a critical spirit and choose what makes it easier for you to achieve your goals.
Other
Box sizing
One of the first thing you will want to do in your reset (or normalize) is to change the box model used for all the elements.
*, *:before, *:after {
box-sizing: border-box;
}
This allows you to set a width and actually get it. CSS-Tricks has a more detailed explanation about the differences.
Web fonts & type faces
Google Fonts offers a lot of free fonts in the form of web fonts—that is, loadable externally from the CSS, and usually loaded from Google’s servers. Not all of them are created equal. Choose with great care and don’t go overboard. (Three fonts maximum should be good for most usages.)
A good font choice will make your website less dull and more recognizable, and it can also improve legibility—making it easier to distinguish different characters—and readable—making it easier to read words, sentences, and paragraphs. Like all good design, good typography should aim to be invisible, that is, it should give the reader with a pleasant feeling, but without grabbing their attention to the typography itself. Using a web font also makes it easier to control what your documents look like; system fonts have too much variability to be used within a single CSS file for all platforms.
Google Fonts isn’t your only choice when it comes to web fonts, though. You can also choose to license one or several fonts from some of the many type foundries (and solo type designers) in the world; most of them will have flexible licensing and usually affordable prices. A project’s visual identity will be greatly improved if you choose a set of lesser-known, high-quality fonts, so if you can afford to put some money in it, I’d definitely recommend it. Typewolf is a good resource to help you navigate the world of type on the web. Matthew Butterick’s aforementioned Practical Typography book has a whole section on choosing fonts, including a showcase of the author’s own fonts. Designer Tobias Van Schneider has a blog post with a nice list of type foundries.
Picking fonts is a delicate exercise. If you’re going for the free web fonts, sticking to the most widely used ones is a safer bet: in particular, Droid Sans, Open Sans, PT Serif & PT Sans, Ubuntu and all their variants are all very high quality fonts. Nobody will yell at you for using these. Don’t go overboard with fonts though—in general you shouldn’t need more than 3 fonts (text, titles, monospace).
Font rendering & typography
Font rendering varies wildly both across browsers and OSes, even when rendering the same font. (You can read Smashing Magazine if you’re interested in knowing how font rendering works.) There’s no real solution for that, apart from choosing a font that was created and tested with the major platforms in mind.
Worse than font rendering variability though, the lack of control over basic typographic features, one of which is the very important baseline and its placement. The best thing you can do is tune the line-height
, but even that is not portable across platforms.
CSS Grids
Laying out things in a grid can be fairly useful, and CSS introduced a feature called CSS Grids that’s designed to do just that—and replace the old float tricks of yore that were fraught with perils.
The sad reality though, is that browser support is very recent (as of April 2017); I wouldn’t recommend using it unless you have a very specific need. For general document layout, flexbox is actually more useful, as it matches a little bit better the way you’d want text and elements to flow in the page. If you really need grids though, or are just curious, check out CSS-Tricks’ complete guide to CSS Grids.
Outline
A cute yet less known CSS-property is outline
: it allows you to draw lines around all the boxes, but isn’t part of the box model itself. Think of it as a “wireframe mode” for your 2D layout: not so much useful for the final result, but very useful as a debugging tool.
rem vs em
There’s a big debate about which units to use in CSS; the New Code has a good summary. In particular, font sizes may be expressed in either em (whose name comes from traditional typography) or rem. The difference between the two is that the em is relative to its parent, while the rem (which stands for root em) is absolute. Zell WK has a useful illustrated blog post about the debate.
Global wrappers
Many old school web devs will wrap everything inside both within a global div tag—usually paired with a class. (There are good reasons for needing one or several global wrappers.) The minimalist, modern developer (that you are, now that you’ve read this document!), will remember that any valid HTML5 document contains not one, but two global wrappers for free: both html
and body
can fullfill this role. Remember them before readying your divs.
Centered layout and scroll bars
If you’re using a layout where all your elements are centered around the viewport, you may encounter the problem of having your layout shift slightly in the horizontal direction depending on whether your current page has a scrollbar (which happens if the content overflows vertically) or hasn’t. There are several solutions to this, but the most elegant uses the calc
function. Ayke van Laëthem, the original discoverer of this trick, describes the solution in-depth, and has my eternal gratitude for this elegant fix.
Developing for HTML & CSS
Starting
Creating a whole layout from scratch can take a large amount of time, even more so if you’ve never really done it before. The most important guideline is to start from the layout, and then only fine tune. Doing any kind of fine tuning prematurely can waste vast amounts of time, in my experience. By fine tuning, I mean in particular, adjusting pixel borders, colors, nudging the font size by small amounts, or any other kind of tuning that may seem even too small to affect the general flow of the document.
Most of the time it’s easier to start from a very simple, widely used layout—the CSS box model can be very confusing at first, and there are plenty of resources that can explain how the basic layouts work. Only when you get a good understanding should you consider building more daring designs.
If you want to build a responsive design, you have to think about how you will structure things from the start, and in particular about how elements will flow when the screen size changes. You cannot fine tune out a design that’s flawed from the start. It is also important to define the limit at which you accept that things will be broken: browser / OS compatibility, special browser settings (user zoom, noscript, no CSS, external resources blocked via plugin…), network performance, and others. It’s important to test often at all stages of the design, especially later ones, where one seemingly innocent change in the CSS can for example completely break everything on mobile. Both Firefox (Responsive Design Mode) and Chrome (Device mode) offer special modes for testing the layout at difference screen sizes without having to constantly resize your browser window. Use them.
Having a short feedback loop is immensely helpful. I’d recommend using a hot-reload solution, and if possible, either splitting the screen or using a second monitor to avoid all kinds of context switches between the code editor, the build tools and the browser.
In addition to a short reset and potentially layout building elements, your CSS should also contain from the start the font sizes corresponding roughly to the final values you’d like, as these can make a massive difference in both the perception of your design and how the browser flows the elements through the page. Because font sizes are very much font dependent, choosing the fonts you’ll use from the start is also important. Not only can two fonts at the same font size render to a wide range of heights, but even if you adjust font sizes to obtain a similar rendered height, the width (and also perceived weight) of the font can vary wildly.
Almost every site whose design you like can be dissected by popping up the Developer Tools of your browser: don’t hesitate to have a peek when you see something you like but wonder how it is achieved. You’ll learn a lot of things that way.
Tools
There are plenty of options for live-reloading, but my favorite one is by far the pair of tools devd
and modd
. devd
is a development server that monitors for local changes and sends reload events when necessary; it uses a connects to a websocket created by JavaScript code that is injected into every page served by devd
. It can be used in tandem with modd
, where modd
will do the monitoring and execute the shell commands of your choice whenever a file is changed—making it possible to work with files that need to be preprocessed, like special JS or CSS compilers—and will then instruct devd
to trigger a hot-reload. Check out the documentation for both these tools for more details.
(If you use Hugo, you can also use the built-in development server.)
Emmet
is a family of completion tools available for pretty much every editor out there. There’s almost no learning curve, so using it is a no-brainer if you’re going to be dealing with HTML & CSS a lot. It gives you tab completion on a short hand syntax for HTML tags, properties, CSS selectors, etc., as well as more advanced features.
Ending remarks
If you have any comments or suggestions about this article, feel free to send me a message at blog@lamarque.fr, reach out to me via Twitter.
Special thanks to members of the Recurse Center community for providing useful feedback on this post.
This article is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.