Chapter 4 CSS Fundamentals

CSS (Cascading Style Sheets) is a declarative language used to alter the appearance or styling of a web page. CSS is used to define a set of formatting rules, which the browser applies when it renders your page. Thus CSS can tell the browser to use a particular font for the page text, a certain color for the first paragraph in an article, or a picture for the page’s background.

Files of CSS rules (called stylesheets) thus act kind of like Styles or Themes in PowerPoint, but are way more powerful. You can control nearly every aspect of an element’s appearance, including its overall placement on the page.

  • To give you some idea of just how much control you have, check out the examples in the CSS Zen Garden. Every one of those examples uses the exact same HTML page, but they all look completely different because each one uses a different CSS stylesheet.

This chapter will explain how to include CSS in your web page and the overall syntax for declaring basic CSS rules. Additional details and options can be found in the following chapter

4.1 Why Two Different Languages?

If you are new to web programming, you might be wondering why there are two different languages: HTML for your page content; and CSS for formatting rules. Why not just include the formatting right in with the content?

There is an old, tried-and-true principle in programming referred to as “separation of concerns”. Well-designed software keeps separate things separate, so that it’s easy to change one without breaking the other. And one of the most common forms of separation is to keep the data (content) in a program separate from the presentation (appearance) of that data.

By separating content (the HTML) from its appearance (the CSS), you get a number of benefits:

  • The same content can easily be presented in different ways (like in the CSS Zen Garden). In web development, you could allow the user to choose different “themes” for a site, or you could change the formatting for different audiences (e.g., larger text for vision-impaired users, more compact text for mobile users, or different styles for cultures with different aesthetic sensibilities).

  • You can have several HTML pages to all share the same CSS stylesheet, allowing you to change the look of an entire web site by only editing one file. This is an application of the Don’t Repeat Yourself (DRY) principle.

  • You can also dynamically adjust the look of your page by applying new style rules to elements in response to user interaction (clicking, hovering, scrolling, etc.)

  • Users who don’t care about about the visual appearance (e.g., blind users with screen readers, automated web indexers) can more quickly and effectively engage with the content without needing to determine what information is “content” and what is just “aesthetics”.

Good programming style in web development thus keeps the semantics (HTML) separate from the appearance (CSS). Your HTML should simply describe the meaning of the content, not what it looks like!

For example, while browsers might normally show <em> text as italic, we can use CSS to instead make emphasized text underlined, highlighted, larger, flashing, or with some other appearance. The <em> says nothing about the visual appearance, just that the text is emphatic, and it’s up to the styling to determine how that emphasis should be conveyed visually.

4.2 CSS Rules

While it’s possible to write CSS rules directly into HTML, the best practice is to create a separate CSS stylesheet file and connect that to your HTML content. These files are named with the .css extension, and are typically put in a css/ folder in web page’s project directory, as with the following folder structure:

my-project/
|-- css/
   |-- style.css
|-- index.html

(style.css, main.css, and index.css are all common names for the “main” stylesheet).

You connect the stylesheet to your HTML by adding a <link> element to your page’s <head> element:

<head>
  <!--... other elements here...-->

  <link rel="stylesheet" href="css/style.css">
</head>

The <link> element represents a connection to another resource. The tag includes an attribute indicating the relation between the resources (e.g., that the linked file is a stylesheet). The href attribute should be a relative path from the .html file to the .css resource. Note also that a <link> is an empty element so has no closing tag.

  • It is also possible to include CSS code directly in your HTML by embedded it in a <style> element in the <head>, but this is considered bad practice (keep concerns separated!) and should only be used for quick tests.

Overall Syntax

A CSS stylesheet lists rules for formatting particular elements in an HTML page. The basic syntax looks like:

/* this is pseudocode for a CSS rule */
selector {
   property: value;
   property: value;
}

/* this would be another, second rule */
selector {
   property: value;
}

A CSS rule rule starts with a selector, which specifies which elements the rule applies to. The selector is followed by a pair of braces {}, inside of which is a set of formatting properties. Properties are made up of the property name (e.g., color), followed by a colon (:), followed by a value to be assigned to that property (e.g., purple). Each name-value pair must end with a semi-colon (;).

  • If you forget the semi-colon, the browser will likely ignore the property and any subsequent properties—and it does so silently without showing an error in the developer tools!

Like most programming languages, CSS ignores new lines and whitespace. However, most developers will use the styling shown above, with the brace on the same line as the selector and indented properties.

As a concrete example, the below rule applies to any h1 elements, and makes them appear in the ‘Helvetica’ font as white text on a dark gray background:

h1 {
  font-family: 'Helvetica';
  color: white;
  background-color: #333; /*dark gray*/
}

Note that CSS comments are written using the same block-comment syntax used in Java (/* a comment */), but cannot be written using inline-comment syntax (//a comment).

When you modify a CSS file, you will need to reload the page in your browser to see the changed appearance. If you are using a program such as live-server, this reloading should happen automatically!

CSS Properties

There are many, many different CSS formatting properties you can use to style HTML elements. All properties are specified using the name:value syntax described above—the key is to determine the name of the property that produces the appearance you want, and then provide a valid value for that property.

Pro-tip: modern editors such as VS Code will provide auto-complete suggestions for valid property names and values. Look carefully at those options to discover more!

Below is a short list of common styling properties you may change with CSS; more complex properties and their usage is described in the following chapter.

  • font-family: the “font” of the text (e.g., 'Comic Sans'). Font names containing white space must be put in quotes (single or double), and I tend to quote any specific font name as well.

    Note that the value for the font-family property can also be a comma-separated list of fonts, with the browser picking the first item that is available on that computer:

    /* pick Helvetic Nue if exists, else Helvetica, else Arial, else the default
       sans-serif font */
    font-family: 'Helvetica Nue', 'Helvetica', 'Arial', sans-serif;
  • font-size: the size of the text (e.g., 12px to be 12 pixels tall). The value must include units (so 12px, not 12). See the next chapter for details on Units & Sizes.

  • font-weight: boldness (e.g., bold, or a numerical value such as 700).

  • color: text color (e.g., either a named color like red or a hex value like #4b2e83. See the next chapter for details on colors. The background-color property specifies the background color for the element.

  • border: a border for the element (see “Box Model” in the next chapter). Note that this is a short-hand property which actually sets multiple related properties at once. The value is thus an ordered list of values separated by spaces:

    /* border-width should be 3px, border-style should be dashed, and border-color
       should be red */
    border: 3px dashed red;

Read the documentation for an individual property to determine what options are available!

Note that not all properties or values be effectively or correctly supported by all browsers. Be sure and check the browser compatibility listings!

CSS Selectors

Selectors are used to “select” which HTML elements the css rule should apply to. As with properties, there are many different kinds of selectors (and see the following chapter), but there are three that are most common:

Element Selector

The most basic selector, the element selector selects elements by their element (tag) name. For example, the below rule will apply the all <p> elements, regardless of where they appear on the page:

p {
   color: purple;
}

You can also use this to apply formatting rules to the entire page by selecting the <body> element. Note that for clarity/speed purposes, we generally do not apply formatting to the <html> element.

body {
   background-color: black;
   color: white;
}

Class Selector

Sometimes you want a rule to apply to only some elements of a particular type. You will most often do this by using a class selector. This rule will select elements with a class attribute that contains the specified name. For example, if you had HTML:

<!-- HTML -->
<p class="highlighted">This text is highlighted!</p>
<p>This text is not highlighted</p>

You could color just the correct paragraph by using the class selector:

/* CSS */
.highlighted {
   background-color: yellow;
}

Class selectors are written with a single dot (.) preceding the name of the class (not the name of the tag!) The . is only used in the CSS rule, not in the HTML class attribute.

Class selectors also let us apply a single, consistent styling to multiple different types of elements:

<!-- HTML -->
<h1 class="alert-flashing">I am a flashing alert!</h1>
<p class="alert-flashing">So am I!<p>

CSS class names should start with a letter, and can contain hyphens, underscores, and numbers. Words are usually written in lowercase and separated by hyphens rather than camelCased.

Note that HTML elements can contain multiple classes; each class name is separate by a space:

<p class="alert flashing">I have TWO classes: "alert" and "flashing"</p>
<p class="alert-flashing">I have ONE class: "alert-flashing"</p>

The class selector will select any element that contains that class in its list. So the first paragraph in the above example would be selected by either .alert OR .flashing.

You should always strive to give CSS classes semantic names that describe the purpose of element, rather than just what it looks like. highlighted is a better class name than just yellow, because it tells you what you’re styling (and will remain sensible even if you change the styling later). Overall, seek to make your class names informative, so that your code is easy to understand and modify later.

There are also more formal methodologies for naming classes that you may wish to utilize, the most popular of which is BEM (Block, Element, Modifier).

Class selectors are often commonly used with <div> (block) and <span> (inline) elements. These HTML elements have no semantic meaning on their own, but can be given appearance meaning through their class attribute. This allows them to “group” content together for styling:

<div class="cow">
  <p>Moo moo moo.</p>
  <p>Moooooooooooooooooooo.</p>
</div>

<div class="sheep">
  <p>Baa baa <span class="dark">black</span> sheep, have you any wool?</p>
</div>

Id Selector

It is also possible to select HTML elements by their id attribute by using an id selector. Every HTML element can have an id attribute, but unlike the class attribute the value of the id must be unique within the page. That is, no two elements can have the same value for their id attributes.

Id selectors start with a # sign, followed by the value of the id:

<div id="sidebar">
   This div contains the sidebar for the page
</div>
/* the one element with id="sidebar" */
#sidebar {
    background-color: lightgray;
}

The id attribute is more specific (it’s always just one element!) but less flexible than the class attribute, and makes it harder to “reuse” your styling across multiple elements or multiple pages. Thus you should almost always use a class selector instead, unless you are referring to a single, specific element.

4.3 The Cascade

CSS is called Cascading Style Sheets because multiple rules can apply to the same element (in a “cascade” of style!)

CSS rules are additive—if multiple rules apply to the same element, the browser will combine all of the style properties when rendering the content:

/* CSS */
p { /* applies to all paragraphs */
  font-family: 'Helvetica'
}

.alert { /* applies to all elements with class="alert" */
  font-size: larger;
}

.success { /* applies to all elements with class="success" */
  color: #28a745; /* a pleasant green */
}
<!-- HTML -->
<p class="alert success">
  This paragraph will be in Helvetica font, a larger font-size, and green color,
  because all 3 of the above rules apply to it.
</p>

CSS styling apply to all of the content in an element. And since that content can contain other elements that may have their own style rules, rules may also in effect be inherited:

<div class="content"> <!-- has own styling -->
  <div class="sub-sec"> <!-- has own styling + .content styling -->
    <ol class="demo-list"> <!-- own styling (ol AND .demo-list rules) + .sub-sec + .content -->

      <!-- li styling + .demo-list + .sub-sec + .content -->
      <li>Item 1</li>
      <li>Item 2</li>
      <li>Item 3</li>
    </ol>
  </div>
</div>

We call these inherited properties, because the child elements inherit the setting from their ancestor elements. This is a powerful mechanism that allows you to specify properties only once for a given branch of the DOM element tree. In general, try to set these properties on the highest-level element you can, and let the child elements inherit the setting from their ancestor.

Rule Specificity

Important! Rules are applied in the order they are defined in the CSS file. If you link multiple CSS files to the same page, the files are processed in order they are linked in the HTML. The browser selects elements that match the rule and applies the rule’s property. If a later rule selects the same element and applies a different value to that property, the previous value is overridden. So in general, all things being equal, the last rule on the page wins.

/* two rules, both alike in specificity */
p { color: red; }
p { color: blue; }
<p>This text will be blue, because that rule comes last!</p>

However, there are some exceptions when CSS treats rules as not equal and favors earlier rules over later ones. This is called Selector Specificity. In general, more specific selectors (#id) take precedence over less specific ones (.class, which is more specific than tag). If you notice that one of your style rules is not being applied, despite your syntax being correct, check your browser’s developer tools to see if your rule is being overridden by a more specific rule in an earlier stylesheet. Then adjust your selector so that it has the same or greater specificity:

/* css */
.alert { color: red; }
div { color: blue; }
<!-- html -->
<div class="alert">This text will be red, even though the `div` selector is last,
because the `.alert` selector has higher specificity so is not overridden.</div>

Precedence rules are not a reason to prefer #id selectors over .class selectors! Instead, you can utilize the more complex selectors described in Chapter 6 to be able to create reusable rules an avoid duplicating property declarations.

Resources