Week 4: An Introduction to CSS

This reading draws heavily from a page by David Humphrey.

Cascading Style Sheets (CSS)

In HTML5, we don't include markup related to how our page should look; instead we focus on its structure and content. We put all the information about how our page should look in style sheets: text files that define CSS selectors and rules for how to style our HTML elements.

CSS makes it possible for us to define how a page looks independent of how we define its structure and content. It allows us to specify style, layout, positioning, and other information about the appearance for HTML elements.

To see just how much impact CSS can have on the same HTML, look at CSS Zen Garden. This site has many examples of the same HTML source file being styled with different CSS style sheets. Readers are invited to create their own styles for the page. (If you'd like to try, download the HTML file and the base style sheet, and play!)

CSS Syntax

CSS syntax is made up of rules, each of which consists of two parts:

  1. a selector that specifies the element(s) to which the rule should be applied
  2. one or more declarations surrounded by {...} braces. Each declaration is a property/value pair.

Consider this example:

h1 {
  color: blue;
  font-size: 12px;
}

In this rule, the selector is h1, which indicates that we want the following rules to be applied to level-1 heading elements, that is, all <h1></h1> elements in the document.

Next comes a list of declarations, each ending with a ;. Each declaration is a property/value pair, where the property is the name of a CSS property that can be associated with the rule's selector.

Here's another example:

p {
  color: red;
  text-align: center;
  text-decoration: underline;
}

This rule says that we want all <p></p> elements in the document to have red, centered text that is underlined.

Where to Put CSS

The CSS used to style an HTML page can come from four different sources.

  1. the tag of an HTML element ("inline")
  2. the HTML file ("internal" or "embedded")
  3. an external file
  4. the browser itself

The browser applies styles to elements in priority order, with styles from the browser itself having lowest priority and styles from the element's tag having highest priority. This means that if more than one style rule is specified for an element, the browser will prefer whatever is defined in an inline style over an internal embedded style, whatever is defined in an internal embedded style over a style defined in an external file, and whatever is defined in an external file over styles provided by the browser.

Inline Styles

We can place a CSS declaration directly on an HTML element via the style attribute:

<p style="background-color: pink;">
  This text is on a pink background.
</p>

This text is on a pink background.

With the rule associated with a specific element, we don't use the selector {...} part of a rule, just one or more declarations in the style attribute's value.

Internal or Embedded Styles

If we want to apply the same CSS rules to more than one element, it makes more sense not to duplicate them on every element's style attribute. One solution is to use a style element in the file's head or body:

<style>
  p { color: red; }
      
  div {
    background-color: blue;
    text-align: center;
  }
</style>
Styles in an External File

Putting a large amount of CSS in style elements makes our HTML files harder to read. It also causes our page to load more slowly, because the browser cannot cache the styles.

More importantly, CSS is about separating style from content. Including CSS rules in an HTML file ties specific styling information with the HTML, making it harder to change the styling of a page or to reuse the styling information on another page.

To overcome these concerns, we usually place our CSS rules in an external .css file and then include them into the HTML file using a link element in the document's head. For example:

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

We can include multiple stylesheets in this way, which means that all of the rules don't have to go in one CSS file. The course website takes advantage of this flexibility to have a general main.css file that applies to all the HTML files on the site, then specific style sheets for reading, session, and homework pages.

<html>
  <head>
    <link rel="stylesheet" href="../main.css" type="text/css">
    <link rel="stylesheet" href="reading.css" type="text/css">
  </head>
  ...
</html>

We can even include .css files from a remote server:

<html>
  <head>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
    <link rel="stylesheet" href="style.css" type="text/css">
  </head>
  ...
</html>

In the example above, the page first includes the popular Bootstrap CSS styles and then loads a local CSS file (one stored on the same web server as the HTML file) to customize styles for the page.

An external .css file can also include other external files, using the @import commande:

/* -- in a CSS file ---*/
/* import fonts and icons from Font Awesome */
@import url(https://use.fontawesome.com/releases/v5.4.2/css/all.css)

... our own CSS rules

The above example loads the popular Font Awesome CSS library for fonts and icons into a style sheet, which itself will be included into an HTML file.

(We will look at Font Awesome in a future session.)

Browser Defaults

The lowest priority CSS rules are provided by the browser itself. These include the browser's default styles and styles injected by browser extensions. For example, here are Firefox's default styles.

CSS Selectors

We can use several different kinds of selector on our CSS rules, with the fundamental type being the HTML tag.

Tag Selectors

The name of an HTML element can be used to specify the styles associated with all elements of that type. For example, to indent all p text in a document, we can say:

p {
  text-indent: 20px;
}
Class Selectors

We often want to apply styles to some but not all elements of a certain kind. Perhaps we only want some of our page's p elements to have a particular look. To achieve this, we define a class and then use that class as an attribute on the elements to be styled. In a CSS rule, a . at the beginning of a selector indicates that it is a classname.

For example, this CSS declaration defines a class named demo:

.demo {
  text-decoration: underline red;
}

Any element with this class will have text decorated with a red underline.

We can then target specific paragraphs to be styled in this way:

<p class="demo">
  This paragraph will have the demo style applied to it.
</p>
<p>
  This paragraph that will not.
</p>
<p class="demo">
  But this one will.
</p>

A class can be applied to elements of different types. In this example, both the h4 element and the p element will be styled as red, underlined text:

<h4 class="demo">A demo-styled heading</h4>
<p class="demo">A styled paragraph</p>
Combined Selectors

We can combine a tag selector with a class selector to apply a style only to elements of a specific type that also have a given class attribute. For example:

p.note {
  font-weight: bold:
}

We can then target specific paragraphs to be styled as notes:

<p class="note">
  This paragraph will be styled.
</p>

<div class="note">
  This div will not be styled, because the rule applies
  only to *paragraphs* with the note class.
</div>

An element can also have multiple classes applied to it, each one adding different styling:

<style>
  .invisible { display: none; }
  .example {
    color: red;
    background-color: gray;
  }
</style>

<p class="invisible example">
  This is a paragraph uses two classes with style.
</p>
ID Selectors

Sometimes we want to style a single element: one specific paragraph, say, but not all paragraphs; or one h2 heading but not all h2 headings. Using a type or class selector would be too broad, because that might style other paragraphs or headings. In these cases, we can use an id attribute instead. Recall that only one HTML element in a document can have a each id value; it must be unique.

<style>
  #summary {
    background-color: skyblue;
  }
</style>

<p id="summary">
  The one summary paragraph in the document will be sky blue.
</p>

When we use an id as a selector, we prefix it with a # symbol (a hash). Notice that the HTML attribute does not include the hash, though.

See below for even more about selectors.

CSS Properties and Values

A property is assigned to a selector in order to manipulate its style. The available CSS properties are defined as part of the CSS standard. When you want to know how one of them works, or which values you can assign, you can look at the documentation on MDN. For example:

There are hundreds of properties that web developers can manipulate. You probably can't memorize them all. It's a good idea, though, to explore what is available and to look at how other web sites use them (via the developer tools). This will familiarize you with what is possible.

VS Code can also help us by offering possible completions for a property name once it sees a few characters as we type a declaration.

A property can have one or more values. The many possible values that a property can have are also defined in the standard. For example:

p {
  text-decoration: underline;
}

.spelling-error {
  text-decoration: red wavy underline;
}

The text-decoration property is defined one or more values in combination, each of which is also defined in the standard.

VS Code can also help us by offering possible completions for the values once it sees a property name in the declaration.

Properties for Styling Text

There are dozens of properties that affect how text is rendered. These include features like the color, spacing, margins, and font characteristics.

h2 {
  color: red;
  text-align: center;
  text-decoration: underline;
  text-transform: uppercase;
}

p {
  color: #0000ff;
  text-indent: 100px;
}
The font-family Property

We can use the font-family property to specify a font, or a list of fonts, for the browser to apply to an element. If a font is not available on the user's computer, the next font in the list will be tried until one is found that is installed, or a default font will be used.

In general it is safe to assume that the following fonts are available on every user's computer:

  • Helvetica, Arial, Verdana, sans-serif — sans-serif fonts
  • Georgia, "Times New Roman", Times, serif — serif fonts
  • "Courier New", Courier, monospace — monospace fonts
h3 {
  font-family: Arial;
}

h4 {
  font-family: "Times New Roman", Times, serif;
}

h5 {
  font-size: 18pt;
  font-style: italic;
  font-weight: 500;
}

If you're interested, check out CSS FontStack for a list of the fonts and OS support.

The font-size Property

Using the font-size property, we can specify sizes in fixed or relative units, depending on how we want our text to scale on different devices:

h1 {
  font-size: 250%;   /* scaled to 250% of regular font size */
}

p {
  font-size: 20pt;   /* size in points -- 20/72 of an inch */
}

.quote {
  font-size: smaller;   /* smaller than normal size */
}

.bigger {
  font-size: 1.5em;   /* 1.5 times larger than the 'M' in normal font size */
}

A Few More CSS Features

Background Properties

Every element has a background that we can style. We might, for example, want to specify that the background be a certain color, or we might want to use an image, or tile an image multiple times, like wallpaper. All of these options and more are possible using the background property.

div.error {
  background: red;
}

div.wallpaper {
  background: url("pattern.jpg") repeat;
}
Colors

CSS allows us to define color values for many elements. We do so by specifying a color using one of the following notations:

  • Named colors — Some colors are so common that they have their own color name defined in the CSS standard. For example: white, black, green, and red, but also lightgray, chocolate and darkorange.
  • Hexadecimal notation — We write three double-digit hexadecimal (base-16) numbers, beginning with a # sign. Each double-digit number is a value between 0 and 255, one for the red component of the color, one for the green component, and one for the blue component. For example, the value #ff0000 has maximum red and no green or blue, so it is red. Pure black is #000000, and pure white is#ffffff.
  • RGB notation — In this notation, the red, green, and blue values are given as decimal values, using rgb(...). rgb(255, 255, 255) is the same as hexadecimal #ffffff, and rgb(255,215,0) is the same gold color as hexadecimal #ffd700. In this notation, we can also give a fourth number for the color's opacity, called alpha. This value ranges from 0.0 to 1.0 to indicate how "see-through" the color is. rgba(0, 191, 0, 0.5) means that the color will be 50% transparent.

The easiest way to understand the relationships between the different notations and to choose a color is to use a Color Picker tool, which lets you visually see the difference caused by changing values.

CSS Units

When we specify values such font sizes, margins, widths, and heights, we sometimes have to use a specific unit. At first, you might think that we would specify all these sizes in pixels. However, modern browsers need to work on such a wide variety of hardware and render to so many different kinds of display (from watches to billboards), we need more options. It is also convenient to be able to specify sizes using relative units, for layouts that need to adapt to changing conditions and still retain the correct proportions.

There is one exception, and that is the value 0. We never need to state a unit with zero, as 0px is the same as 0%, etc.

The most common units we use in CSS are: 1em = 12pt = 16px = 100% Let's look at each of these units in turn:

  • em — the width of the capital letter M. This is a scalable unit that is equal to the current font-size. If the font-size is 12pt, then 1em is the same as 12pt. If the font-size is changed, 1em changes to match. We can also use multiples: 2em is twice the font-size, and .5em is half. Using em for sizes is popular on the web, since things have to scale on both mobile and desktop platforms. (Fixed unit sizes don't work as the screen shrinks or expands).
  • pt — a fixed-size point unit that comes from print media, where 1pt equals 1/72 of an inch.
  • px — a fixed-size pixel units that comes from computer screens, where 1px equals one dot on the display. We use px on the web when we need "pixel perfect" sizing, as with image sizes.
  • % — the percent unit is similar to em in that it scales with the size of the display. 100% is the same as the current font-size.

You may occasionally see values given in vw or vh units. They specify a percentage of the viewport width and the viewport height, respectively. The viewport is the part of the page you can see. 1vw is the same as 1% of the width of the viewport, and 80vh is the same as 80% of the visible height.

Finally, you will also sometimes encounter other ways of measurement that use full words: xx-small, x-small, small, medium, large, x-large, xx-large, smaller, larger, thin, medium, thick.

Here is an example that uses many of the units mentioned above:

<style>
  html, body { height: 100vh; }
      
  .box {
    margin: 10px;
    font-size: 2em;
    height: 150px;
    border: medium solid black;
  }
</style>

<div class="box">
  ...
</div>

More on CSS Selectors

In addition to tag selectors, there are a number of other ways that we can target our styles.

Contextual Selectors

In some cases, we might want to target paragraphs, but only paragraphs nested inside another element. For instance, we may want to style paragraphs that are in a section, but not paragraphs that are in a header or footer. To do this, we write a selector that indicates this relationship. These are called context selectors.

For example, if we want to apply styles to p elements that are inside a body elements, we ould can write:

<style>
  body p {
    font-size: 16px;
  }
</style>

<p>This paragraph will not be 16 pixels.</p>

<body>
  <p>This paragraph will be 16 pixels.</p>
  <p>So will this one.</p>
</body>
Grouping Selectors

Finally, as our set of CSS rules grows, we sometimes notice that we have repeated the same prperty/value pair in multiple rules. Instead of maintaining separate rules, we can group a number of selectors together into a comma-separated list:

html, body {
  height: 75%;
}

h1, h2, h3, h4, h5, h6 {
  font-family: Serif;
  color: blue;
}

These rules use grouping twice to cut-down on the number of times we have to repeat properties. In the first rule, we specified a height of 75% for the html and body elements. (They don't have a height by default, and otherwise will only be as tall as the content within them.) We have also specified font and color information for all the headings we use in the file with a single rule.