Introduction to CSS

What is CSS

CSS (an abbreviation of Cascading Style Sheets) is the language that we use to style an HTML file, and tell the browser how should it render the elements on the page.

It was grown out of the necessity of styling web pages. Before CSS was introduced, people wanted a way to style their web pages, which looked all very similar and “academic” back in the day. You couldn’t do much in terms of personalization.

HTML 3.2 introduced the option of defining colors inline as HTML element attributes, and presentational tags like center and font, but that escalated quickly into a far from ideal situation 😱.

CSS let us move everything presentation-related from the HTML to the CSS, so that HTML could get back being the format that defines the structure of the document, rather than how things should look in the browser.

CSS is continuously evolving, and CSS you used 5 years ago might just be outdated, as new idiomatic CSS techniques emerged and browsers changed.

How does CSS look like

A CSS rule set has one part called selector, and the other part called declaration. The declaration contains various rules, each composed by a property, and a value.

In this example, p is the selector, and applies one rule which sets the value 20px to the font-size property:

p {
  font-size: 20px;
}

Multiple rules are stacked one after the other:

p {
  font-size: 20px;
}

a {
  color: blue;
}

A selector can target one or more items:

p, a {
  font-size: 20px;
}

and it can target HTML tags, like above, or HTML elements that contain a certain class attribute with .my-class, or HTML elements that have a specific id attribute with #my-id.

More advanced selectors allow you to choose items whose attribute matches a specific value, or also items which respond to pseudo-classes (more on that later)

Semicolons

Every CSS rule terminates with a semicolon. Semicolons are not optional, except after the last rule, but I suggest to always use them for consistency and to avoid errors if you add another property and forget to add the semicolon on the previous line.

Formatting and indentation

There is no fixed rule for formatting. This CSS is valid:

      p
      {
  font-size:           20px   ;
                      }

a{color:blue;}

but a pain to see. Stick to some conventions, like the ones you see in the examples above: stick selectors and the closing brackets to the left, indent 2 spaces for each rule, have the opening bracket on the same line of the selector, separated by one space.

Correct and consistent use of spacing and indentation is a visual aid in understanding your code.

How do you load CSS in a Web Page

CSS can be loaded in a page in 3 ways: with a style tag in the page head, with an external CSS file, and inline in tags.

Style sheets in the head tag

<html>
  <head>
    <!--...-->
    <style>
      p {
        font-size: 20px;
      }
    </style>
  </head>
  <body>
    <!--...-->
  </body>
</html>

External CSS file

<html>
  <head>
    <!--...-->
    <link href="style.css" rel="stylesheet" type="text/css">
  </head>
  <body>
    <!--...-->
  </body>
</html>

style.css

p {
  font-size: 20px;
}

Inline styles

Inline styles allow you to set some CSS directly inside an HTML element, using the style HTML attribute:

<html>
  <!--...-->
  <body>
    <p style="font-size: 20px">Test</p>
  </body>
</html>

They are sometimes useful for quick tests, but should be generally avoided.

Error handling

CSS is resilient. When it finds an error, it does not act like JavaScript which packs up all its things and goes away altogether, terminating all the script execution after the error is found.

CSS tries very hard to do what you want.

If a line has an error, it skips it and jumps to the next line without any error.

If you forget the semicolon on one line:

p {
  font-size: 20px
  color: black;
  border: 1px solid black;
}

the line with the error AND the next one will not be applied, but the third rule will be successfully applied on the page. Basically, it scans all until it finds a semicolon, but when it reaches it, the rule is now font-size: 20px color: black;, which is invalid, so it skips it.

Sometimes it’s tricky to realize there is an error somewhere, and where that error is, because the browser won’t tell us.

This is why tools like CSS Lint exist:

Find error through lint

The “Cascading” part explained

CSS means Cascading Style Sheets, so what does cascading mean?

Two or more competing rules for the same property applied to the same element need to be elaborated according to some specific rules, to determine which one needs to be applied.

Those rules involve 3 things:

  • specificity
  • importance
  • order in the file

Specificity

The more specific is a selector, the more priority the rule has over the others. Specificity is measured with this set of rules:

  • 1 point: element selectors
  • 10 points: class selectors, attribute selectors, pseudo class selectors
  • 100 points: id selectors
  • 1000 points: rules defined inline, in a style attribute.

Those points are summed, and the selector which is more specific gets the prize, and shows up on the page.

Importance

Specificity does not matter if a rule ends with !important:

p {
  font-size: 20px!important;
}

That rule will take precedence over any rule with more specificity

Order in file

If a rule is defined after one with same specificity, the second rule wins:

p {
  color: black;
}

p {
  color: white;
}

The rule that wins is color: white.

This applies to all rules, including the ones with !important.

CSS Inheritance

Some CSS rules applied to an element are inherited by its children.

Not all rules, just some. It depends on the property.

The commonly used rules which apply inheritance are:

  • border-spacing
  • color
  • cursor
  • font-family
  • font-size
  • font-style
  • font-variant
  • font-weight
  • font
  • letter-spacing
  • line-height
  • list-style-image
  • list-style-position
  • list-style-type
  • list-style
  • text-align
  • text-indent
  • text-transform
  • visibility
  • white-space
  • word-spacing

In a child element, you can set any property to special values, to explicitly set the inheritance behavior:

  • inherit: inherit from the parent
  • initial: use the default browser stylesheet if available. If not, and if the property inherits by default, inherit the value. Otherwise do nothing.
  • unset: if the property inherits by default, inherit. Otherwise do nothing.
  • revert: use the CSS rule in our stylesheets if available. Otherwise use the default browser stylesheet.

Normalizing CSS

The default browser stylesheet mentioned above is the set of rules that browser have to apply some minimum style to elements.

Since every browser has its own set, it’s common finding a common ground. Rather than removing all defaults, like a CSS reset does, normalizing removes browser inconsistencies, while keeping a basic set of rules you can rely on.

Normalize.css is the most commonly used solution for this problem.

Pseudo classes

Pseudo classes are used to specify a specific state of an element, or to target a specific child.

They start with a single colon :.

They can be used as part of a selector, and they are very useful to style active or visited links for example, change the style on hover, focus, or target the first child, or odd rows. Very handy in many cases.

These are the most popular pseudo classes you will likely use:

Pseudo class Targets
:active an element being activated by the user (e.g. clicked). Mostly used on links or buttons
:checked a checkbox, option or radio input types that are enabled
:default the default in a set of choices (like, option in a select or radio buttons)
:disabled an element disabled
:empty an element with no children
:enabled an element that’s enabled (opposite to :disabled)
:first-child the first child of a group of siblings
:focus the element with focus
:hover an element hovered with the mouse
:last-child the last child of a group of siblings
:link a link that’s not been visited
:not() any element not matching the selector passed. E.g. :not(span)
:nth-child() an element matching the specified position
:nth-last-child() an element matching the specific position, starting from the end
:only-child an element without any siblings
:required a form element with the required attribute set
:root represents the html element. It’s like targeting html, but it’s more specific. Useful in CSS Variables.
:target the element matching the current URL fragment (for inner navigation in the page)
:valid form elements that validated client-side successfully
:visited a link that’s been visited

:nth-child() and :nth-last-child() are quite complex and deserve a special mention. They can be used to target odd or even children with :nth-child(odd) and :nth-child(even). They can target the first 3 children with :nth-child(-n+3). They can style 1 in every 5 elements with :nth-child(5n). More details on MDN.

Some pseudo classes are used for printing, like :first, :left, :right. More on using CSS for printing in the CSS printing tutorial.

Find the list with links to all the pseudo links on MDN.

Pseudo elements

Pseudo elements are used to style a specific part of an element.

They start with a double colon :: (for backwards compatibility you can use a single colon, but you should not, to distinguish them from pseudo classes).

::before and ::after are probably the most used pseudo elements. They are used to add content before or after an element, like icons for example.

Pseudo element Targets
::after creates a pseudo element after the element
::before creates a pseudo element after the element
::first-letter can be used to style the first letter of a block of text
::first-line can be used to style the first line of a block of text
::selection targets the text selected by the user

What to learn next

I suggest you to take a look at my Flexbox and CSS Grid tutorials.

Building a layout is the most satisfying parts of CSS, and it’s a great way to start with the right foot.