Introduction to CSS

Today we'll look at what CSS is, how it operates, where to put it, how to write CSS rules, and how to validate our CSS.

Table of Contents

What is CSS?

Today we learn a new language! CSS, or "Cascading Stylesheets" is a computer language that has been a part of the web since 1996. Currently, we use "CSS3", but since new features keep getting added incrementally, there likely won't be something we call "CSS4".

Just like HTML and the Web Accessibility Guidelines, CSS is governed by W3C.

CSS

(For better, or for worse) CSS controls how web documents (a.k.a. web pages, a.k.a. HTML) look, from colours and fonts to layouts and animation.

Why CSS?

As discussed, having our styling kept separate from our content (HTML) and our functionality (JavaScript), allows for the "separation of concerns".

These different languages do different tasks, which makes things more resilient (one thing can break without taking everything down with it), more maintainable (you can update the look without having to rewrite the content, for example), and easier to understand.

CSS as a language is tremendously flexible (and can be a lot of fun!) But that flexibility means we have to code responsibly, or things can get messy and quick.

Today we're going to go into what makes CSS messy, but before we dive into the nitty-gritty, let me do some quick live-coding to show you, in a nutshell, how CSS normally works.

How to write CSS

Structure of a CSS ruleset

CSS rulesets (commonly just called 'rules') start with a selector. The selector determines what HTML elements the rules should apply to.

Following the selector, there are braces (a.k.a. curly brackets) that wrap the rules.

Inside the braces are the declarations. Declarations are the rules that are going to apply to the selected elements.

These declarations are made up of properties and values. The property is the quality that you want to change. The value is what you want to change the property to be.

After each declaration within the ruleset, you write a semicolon.

At the end of your ruleset is a closing brace.

(selector)open brace(property)colon(value)semicolonclosing brace
h1{color:blue;}
h1 {
    color: blue;
    font-size: 2rem;
}

Selectors

Unless I tell you otherwise, use single classes as your selectors. I'll explain more later. What you're learning in this section will help you work with other people's code, but when you are writing your own code, use classes as your selectors.

Basic Selectors

SelectorDescriptionExampleSelected element
.Selects elements with matching class attribute.my-class {color: blue;}<p class="my-class"></p>
Element nameSelects a matching elementsp {color: blue;}<p></p>
#Selects elements with matching id attribute#myId {color: blue;}<p id="myId"></p>
*Selects all elements* {color: blue;}<p></p> and literally every other element on your page.
[attr=value]Selects all elements with matching attribute[href="#home"] {color: blue;}<a href="#home"></a>

(Actually, this guy's too big to fit on a slide - check it out
in the notes.)

Grouping & Combinator Selectors

SelectorDescriptionExampleSelected element
,Adds multiple selectors to the same ruleset.my-class, .my-other-class {color: blue;}<p class="my-class"></p><h1 class="my-other-class"></h1>
Combined selectorsSelects one element based on multiple selectorsdiv.my-class.my-other-class{color: blue;}<div class="my-class my-other-class"></div>
[space]Selects descendant elementsdiv .my-class{color: blue;}<div><p><span class="my-class"></span></p></div>
>Selects direct child elements#myId > span {color: blue;}<p id="myId"><span></span></p>
~Selects all sibling elementsp ~ .my-class {color: blue;}<p></p><div></div><span class="my-class"></span>
+Selects immediate siblingh1 + p {color: blue;}<h1></h1><p></p>
To see our CSS selectors in action, check out this demo:

See the Pen CSS selectors demo by Simon Borer (@simonborer) on CodePen.

Where to write CSS

There are 3 places you can write CSS:

  1. In an external stylesheet document
  2. In the <head> of your HTML document, wrapped in a <style> element
  3. In the style attribute of an element, i.e.
    <span style="color:red;">My red text</span>

External stylesheets

Most of the CSS you write will go in an external stylesheet - a document with a .css file extension. This gets loaded into your document via a <link> element in the <head> of your HTML document, much the same way we load images via an <img> element. But we'll worry about that next week.

This week, we can just work in the 'CSS' pane of Codepen.

Style tags

It's fine to write CSS in a style tag in the head of your document. However, if you're hoping to share this CSS across multiple pages (and you're not templating the head across documents), or if you write more than a few dozen lines of CSS, this can get really messy and unmaintainable.

Style attributes

The least popular way to write CSS is in the style attribute. It's inefficient, messy and hard to maintain. People will make fun of you if you do this without a good reason. And they're right to do it.

Inheritance, specificity, and the 'Cascade'

The messy part of CSS is determining what rules take precendence based on priority.

The priority is set based on 3 factors: inheritance, specificity, & the 'Cascade'.

Inheritance

Some properties1 are inherited from parent elements.

<p style="color:green">
    All this <strong>text</strong>
    will <em>be green</em>
<p>

Inheritance is the lowest priority. Any selector beats inheritance.

Specificity

Specificity gets very complicated Opens in a new window very quickly.

Here's the short version:

An id selector (#myId) beats a class selector (.my-class), and a class selector beats an element selector (h1, for example).

Three levels of specificity (.three-levels .two-levels .one-level {}) beats two levels of specificity (.two-levels .one-level {}) which beats one level of specificity (.one-level {})2.

Combined selectors (h1#myId) beat single selectors (#myId).

All of this specificity gets beaten by an inline style3.

The only thing with a higher priority than an inline style is !important.

.so-important {
    color: purple !important;
}

The only thing that can override !important is another !important.

How the 'Cascade' works

If you have more than one declaration targetting the same selector with the same level of specificity, the cascade determines precedence.

The 'Cascade' refers to prioritization based on the type and load-order of stylesheets (and CSS written in <style> tags).

Default browser styles (also called 'User-agent styles') get loaded first.

Next, styles defined by the web page's author ('author styles') are loaded in the order they appear in the document.

Why some people hate CSS

I mean, you get it at this point, right? It can be really hard to figure out what takes precedence, and therefore how to make that thing blue, or whatever.

That's why I'm going to strongly, strongly encourage you to use classes with little to no layers of specificity for all your styles. It is very, very easy to make your code into a confusing mess, also known as specificity wars Opens in a new window.

If you want to have lots of classes that do very specific things (i.e. one for font-size, one for border), that's actually very popular these days Opens in a new window, and is certainly better than the alternative.

Personally, I like having a system for naming Opens in a new window my component classes. But that's just me.

Some basic CSS units, values & properties

Okay, now that you've been thoroughly intimidated by the 'Cascading' part, it's time to actually get stylish!

Here's a list from our friends at MDN Opens in a new window. Check it out in order to determine what values a property can have, and what elements it can be applied to.

Colours in CSS

Where a property can take a colour as a value, those values are usually written as hexadecimal values (the # symbol, followed by a six-digit alphanumeric code). You can also use named colors, and RGBA units if you want to take advantage of an opacity value.

Find hex codes here Opens in a new window.

Units in CSS

UnitDescription
pxNumber of pixels (1/96th of an inch). The only common way of hard-coding an absolute value in CSS.
remFont size of the root element.
emFont size of the parent element.
vw1% of the viewport's width.
vh1% of the viewport's height.
%Well, this is context-dependent and gets messy. For example, if you set a width to a percentage, then it would be that percentage of the parent's width.

(Yah, this guy's waaay too big to fit on a slide - check it out
in the notes.)

Common CSS properties

PropertyDescription
backgroundDefines the background color or image.
borderDefines the width, style and colour of the element's border.
border-radiusDefines the degree to which an element's corners are rounded.
colorChanges the color of text.
font-familyChanges the text's font.
font-sizeChanges the text's size.
font-weightChanges the text's weight.
marginChanges the space around the outside of an element.
paddingChanges the padded space inside of an element.
text-alignChanges the justification of text.
text-decorationChanges the decoration of text.
heightChanges the height of an element.
widthChanges the width of an element.

How to validate CSS

Just like HTML, we have the option to spot-check things in Codepen, and do a proper validation through the W3C Opens in a new window.

Here's today's lab work:

  1. Sign into your CodePen Opens in a new window account.
  2. In CodePen, create a new "Pen".
  3. Create a short write-up about what you learned today about how CSS determines what rules apply to what elements. Your write-up should be styled with at least one instance of each of the following:
    • a class selector
    • an id selector
    • a sibling selector
    • a child selector
    • centred text
    • a hex code
    • a font-size
    • one style that gets overridden by another
  4. When you're done, submit the link to it via Blackboard, just like we did the first week.

Footnotes

1Honestly, this is the best list Opens in a new window I could find. Inherited properties are largely limited to text-based properties like font-size, line-height, and text-align, including list properties like list-style.
↑ Back to reference 1
2Note that combinators like +, >, ~, and [space] don't affect specificity.
↑ Back to reference 2
3I mean, most of the time. Not always. Ugh.
↑ Back to reference 3