The HTML and CSS Workshop

By Lewis Coulson , Brett Jephson , Rob Larsen and 2 more
  • Instant online access to over 7,500+ books and videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies
  1. 1. Introduction to HTML and CSS

About this book

You already know you want to learn HTML and CSS, and a smarter way to learn HTML and CSS is to learn by doing. The HTML and CSS Workshop focuses on building up your practical skills so that you can build your own static web pages from scratch, or work with existing themes on modern platforms like WordPress and Shopify. It’s the perfect way to get started with web development. You'll learn from real examples that lead to real results.

Throughout The HTML and CSS Workshop, you'll take an engaging step-by-step approach to beginning HTML and CSS development. You won't have to sit through any unnecessary theory. If you're short on time you can jump into a single exercise each day or spend an entire weekend learning about CSS pre-processors. It's your choice. Learning on your terms, you'll build up and reinforce key skills in a way that feels rewarding.

Every physical print copy of The HTML and CSS Workshop unlocks access to the interactive edition. With videos detailing all exercises and activities, you'll always have a guided solution. You can also benchmark yourself against assessments, track progress, and receive free content updates. You'll even earn a secure credential that you can share and verify online upon completion. It's a premium learning experience that's included with your printed copy. To redeem, follow the instructions located at the start of your HTML CSS book.

Fast-paced and direct, The HTML and CSS Workshop is the ideal companion for a HTML and CSS beginner. You'll build and iterate on your code like a software developer, learning along the way. This process means that you'll find that your new skills stick, embedded as best practice. A solid foundation for the years ahead.

Publication date:
November 2019
Publisher
Packt
Pages
698
ISBN
9781838824532

 

1. Introduction to HTML and CSS

Overview

By the end of this chapter, you will be able to describe the roles of HTML and CSS in a web page; explain the HTML DOM and CSSOM; explain how a web page renders; create a web page from scratch; and use CSS selectors and calculate CSS specificity. This chapter introduces two core technologies of the web – HTML and CSS. We will look at how they work, how we can write them, and how we can use them to build web pages.

 

Introduction

Whether you want to create a simple web page to advertise a business, blog about your hobbies and interests, maintain an online community, or even create your own social media network, HTML and CSS are the foundational technologies upon which you can build for the web and are a way for you to get your ideas out there to as wide an audience as possible.

When a web browser navigates to a web page, it will receive and parse an HTML document, which may include text, pictures, links, and other media (for instance, sound and video).

HTML structures this content. It gives it context, describes the content and tells the browser what to do with it. CSS tells the browser how to present the content. A set of styling rules lets the browser know how to render elements within the HTML document. HTML and CSS together give the browser the information it needs to render the web page for the user.

Navigate to a website and what you see is the rendered output of content marked up with HTML and styled with CSS. As a browser user, you have access to the source code of a web page. In Chrome, for example, you can view a page's source code with the keyboard shortcut Ctrl + U on a PC or Cmd + U on a Mac, or right-click and choose View Page Source. Try it yourself. As an example, the following two figures show what the Packt website's Web Development portal looks like when rendered in the browser and as source code respectively.

Ultimately, by learning how to write the HTML and CSS found in that source code, we can create a modern website:

Figure 1.1: The Packt Publishing site's Web Development portal

Figure 1.1: The Packt Publishing site's Web Development portal

The following figure shows the source code of the Packt website:

Figure 1.2: The HTML source code of the Packt site

Figure 1.2: The HTML source code of the Packt site

In this chapter, we will look at how a web page renders by following the process from initial request to completed composition. We will create our first web page and look at how a web browser will parse HTML and CSS to render that page. We will look at how browser developer tools, such as those included with the Chrome browser, can help us to identify and edit nodes within an HTML document and the CSS applied to those nodes.

 

HTML

HyperText Markup Language (HTML) is a markup language used to describe the structure of a web page.

Consider a snippet of text with no markup:

HTML HyperText Markup Language (HTML) is a markup language used to describe the structure of a web page. We can use it to differentiate such content as headings lists links images Want to https://www.packtpub.com/web-development Learn more about web development.

The above snippet of text may make some sense to you, but it may also raise some questions. Why does the snippet begin with the word HTML? Why is there a URL in the middle of a sentence? Is this one paragraph?

Using HTML, we can differentiate several bits of content to give them greater meaning. We could mark the word HTML as a heading, <h1>HTML</h1>; we could mark a link to another web page using the URL <a href="https://www.packtpub.com/web-development">Learn more about web development</a>.

Throughout this chapter, we will be looking at the HTML5 version of the HTML language. We will look at the syntax of HTML in the next section.

Syntax

The syntax of HTML is made up of tags (with angle brackets, <>) and attributes. HTML provides a set of tags that can be used to mark the beginning and end of a bit of content. The opening tag, closing tag, and all content within those bounds represent an HTML element. The following figure shows the HTML element representation without attributes:

Figure 1.3: HTML element representation without tag attributes

Figure 1.3: HTML element representation without tag attributes

The following figure shows the HTML element representation with tag attributes:

Figure 1.4: HTML element representation with tag attributes

Figure 1.4: HTML element representation with tag attributes

A tag has a name (for instance, p, img, h1, h2, h3, br, or hr) and that name combined with attributes will describe how the browser should handle the content. Many tags have a start and an end tag with some content in between, but there are also tags that don't expect any content, and these can be self-closing.

An opening tag can have any number of attributes associated with it. These are modifiers of the element. An attribute is a name-value pair. For example, href="https://www.packtpub.com/web-development" is an attribute with the name href and the value https://www.packtpub.com/web-development. An href attribute represents a hypertext reference or a URL, and when this attribute is added to an anchor element, <a>, it creates a hyperlink that the user can click in the browser to navigate to that URL.

To provide information within an HTML document to be ignored by the parser and not shown to the end user, you can add comments. These are useful for notes and documentation to aid anyone who might read or amend the source of the HTML document. A comment begins with <!-- and ends with -->. Comments, in HTML, can be single or multiline. The following are some examples:

<!-- Comment on a single line -->
<!--
    This comment is over multiple lines.
    Comments can be used to inform and for detailed documentation.
-->

You can use comments to provide helpful hints to other developers working on the web page but they will be ignored by the browser when parsing the page.

Let's see what the previous snippet of text content looks like when it is given some meaning with HTML:

<h1>HTML</h1>
<p> 
HyperText Markup Language (HTML) is a markup language used to describe the structure of a web page.
</p>
<p>
We can use it to differentiate such content as:
</p>
<ul>
    <li>headings</li>
    <li>lists</li>
    <li>links</li>
    <li>images</li>
</ul>
<p>
Want to <a href="https://www.packtpub.com/web-development">learn more about web development?</a>
</p>

If we were to look at this HTML code rendered in a browser, it would look like the following figure:

Figure 1.5: HTML rendered in the Google Chrome web browser

Figure 1.5: HTML rendered in the Google Chrome web browser

The first line shows the text content "HTML" with a start tag, <h1>, and an end tag, </h1>. This tells the browser to treat the text content as an h1 heading element.

The next line of our code snippet has a <p> start tag, which means the content until the corresponding end tag, </p> (on the last line), will be treated as a paragraph element. We then have another paragraph and then an unordered list element that starts with the <ul> start tag and ends with the </ul> end tag. The unordered list has four child elements, which are all list item elements (from the <li> start tag to the </li> end tag).

The last element in the example is another paragraph element, which combines text content and an anchor element. The anchor element, starting from the <a> start tag and ending at the </a> end tag, has the text content learn more about web development? and an href attribute. The href attribute turns the anchor element into a hyperlink, which a user can click to navigate to the URL given as the value of the href attribute.

As with our example, the contents of a paragraph element might be text but can also be other HTML elements, such as an anchor tag, <a>. The relationship between the anchor and paragraph elements is a parent-child relationship.

Content Types

HTML5 provides many elements for describing the metadata, content, and structure of an HTML document, and you will learn more about the meaning of specific elements throughout the following chapters.

When starting out with HTML, it can be easy to find the number and variety of elements overwhelming. That is why it may be helpful to think about HTML in terms of content types. We can categorize HTML elements as one of the following content types:

  • Metadata
  • Flow
  • Sectioning
  • Phrasing
  • Heading
  • Embedded
  • Interactive

The following table has the description and example of different content types:

Figure 1.6: Table describing the different content types

Figure 1.6: Table describing the different content types

To see how we can use these categories, we will introduce an HTML5 element and see how it will fit into these category types. We will look at the <img> element.

If we want to embed an image in our web page, the simplest way is to use the img element (for more on images, see Chapter 7, Media, Audio, Video, and Canvas). If we want to create an img element, an example of the code looks like this: <img src="media/kitten.png" alt="A cute kitten">.

We set the src attribute on the img element to an image URL; this is the source of the image that will be embedded in the web page.

Unless your image has no value other than as a decoration, it is a very good idea to include an alt attribute. The alt attribute provides an alternative description of the image as text, which can then be used by screen readers if an image does not load, or in a non-graphical browser.

An img element is a form of embedded content because it embeds an image in an HTML document. It can appear in the body of an HTML document as the child element of the body element, so it would be categorized as flow content.

An image can be included as content in a paragraph, so it is a type of phrasing content. For example, we could have inline images appear in the flow of a paragraph:

<p>Kittens are everywhere on the internet. The best thing about kittens is that they are cute. Look here's a kitten now: <img src="media/kitten.jpg" alt="A cute kitten">. See, cute isn't it?</p>

This code would render the following figure, with the image embedded in the paragraph and the rest of the text flowing around it:

Figure 1.7: Image with text flowing around it

Figure 1.7: Image with text flowing around it

In certain circumstances, an img element is a type of interactive content. For this to be the case, the image must have a usemap attribute. The usemap attribute allows you to specify an image map, which defines areas of an image that are treated as hyperlinks. This makes the image interactive.

An img element does not act as metadata and it does not provide a sectioning structure to an HTML document. Nor is it a heading.

There are lots more elements in the HTML5 standard. Elements can appear in more than one category and there is some overlap between the relationships of the categories. Some of these elements are very common and are used often, but some of these elements have very specific purposes and you may never come across a use case for them.

The content types can be useful for grouping elements into more manageable chunks, for getting an overview of the choices HTML gives you and the restrictions it puts on the content of an element, and for understanding the content types generally before we drill down into the uses of specific elements in later chapters.

For further reference, we can see where each available element is categorized in the W3C's documentation on HTML5: https://packt.live/2OvPGRi.

The HTML Document

An HTML document represents a hierarchical tree structure, rather like a family tree. Starting from a root element, the relationship between an element and its contents can be seen as that of a parent element and a child element. An element that is at the same level of the hierarchy as another element can be considered a sibling to that element, and we can describe elements within a branch of the tree as ancestors and descendants. This structure can be represented as a tree diagram to get a better idea of the relationship between elements.

Take, for example, this simple HTML document:

<html>
  <head>
    <title>HTML Document structure</title>
  </head>
  <body>
    <div>
      <h1>Heading</h1>
      <p>First paragraph of text.</p>
      <p>Second paragraph of text.</p>
    </div>
  </body>
</html>

Here, we have an HTML element, the root of the document, which hosts a head element containing a title element, and a body element, containing some content including a div element with an h1 heading element and some paragraph elements. It can be represented as a tree diagram as follows:

Figure 1.8: A representation of the HTML document as a tree diagram

Figure 1.8: A representation of the HTML document as a tree diagram

In the browser, this code would render the following web page:

Figure 1.9: HTML rendered in the Google Chrome web browser

Figure 1.9: HTML rendered in the Google Chrome web browser

The <html> element is the parent of <head> and <body>, which (as children of the same parent) are siblings. <body> has one child, a <div> element, and that has three children: an <h1> element and two <p> elements. The <h1> element is a descendant of the <body> element but not of the <head> element.

Understanding this structure will become more important when we look at CSS selectors and how we target parts of the HTML document later in this chapter.

The HTML DOM

We can also represent the HTML document as a Document Object Model (DOM). The DOM is an in-memory representation of our HTML document as a tree of objects. The tree is represented as a set of nodes and their connections to other nodes.

A node is associated with an object. The object stores properties, methods, and events associated with the HTML element. The node represents where that element sits in the document tree structure by storing references to its parent and child nodes.

When we want to change the document programmatically, as is often the case when we use JavaScript, we do so through the DOM. We can traverse the document programmatically and make changes to elements by changing properties on the objects.

As an example, we can use JavaScript's DOM API to create an anchor element, change properties on the element, and then add it to a paragraph with the parent class attribute:

<script>
  const anchorElement = document.createElement('a');
  anchorElement.href = '#';
  anchorElement.textContent = 'Click me!';
  const p = document.querySelector('.parent');
  p.appendChild(anchorElement);
</script>

The DOM represents the HTML document in a way that means we can traverse the tree and make changes to it programmatically. This allows modern web pages to be more than static documents.

We will mostly concentrate on the HTML and CSS parts of the web page but will see how we can use JavaScript to enhance and manipulate the HTML document in later chapters.

The Doctype Declaration

To let the browser, know which version of HTML to expect on our web page, we provide a doctype declaration. There are multiple versions of HTML and, at the time of writing, we are on version 5.2. Each version of HTML has a different declaration.

We will be working with HTML5 in this book so the appropriate doctype is as follows:

<!DOCTYPE html>

Note

The doctype declaration is not case-sensitive, so variations such as <!doctype html> and <!DOCTYPE HTML> are equally valid.

Without a doctype declaration, the browser can still try to parse an HTML document but it will do so in something called quirks mode. The effects of quirks mode can be different depending on the browser and whether the HTML document complies with the standard or not. This mode is there for backward compatibility and to handle old web pages and may cause your web page to render in unexpected ways. It is recommended to always add a doctype.

One of the nice things about HTML5 is that it really simplifies doctype declaration. Before HTML5, there were two commonly used variations of web markup – HTML4 and XHTML1 – and they both had strict, transitional, and frameset versions of their doctype declarations. For example, the HTML 4 strict declaration looked like this: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">.

The HTML5 doctype simplifies things and makes it a lot easier to get started creating a web page.

 

Structuring an HTML Document

A requirement of HTML5 is that all HTML documents are structured with a root element, the html element, and two child elements, the head element, and the body element.

HTML

The html element is the root element of an HTML document. In an HTML document, the only thing that appears outside the html element is the doctype declaration, which appears above the html element. Before we put any content on our web page, the code looks like this:

<!doctype html>
<html lang="en"></html>

The html element is the top-level element and all other elements must be a descendant of it. The html element has two children – one head element and a body element, which must follow the head element.

It is strongly recommended that you add a lang attribute to your html element to allow the browser, screen readers, and other technologies, such as translation tools, to better understand the text content of your web page.

Head

The head element contains metadata. It stores information about the HTML document that is used by machines – browsers, web crawlers, and search engines – to process the document. This section of an HTML document is not rendered for human users to read.

The minimum content the head element can have is a title element. Within a web page, the code would look like this:

<!doctype html>
<html lang="en">
    <head>
        <title>Page Title</title>
    </head>
</html>

Body

An HTML element is expected to have one body element and it is expected to be the second child of the html element following the head element.

Our minimal HTML document would therefore have the following code:

<!doctype html>
<html lang="en">
    <head>
        <title>Page Title</title>
    </head>
    <body>
    </body>
</html>

The body element represents the content of the document. Not everything in the body will necessarily be rendered in the browser, but all human-readable content should be hosted in the body element. This includes headers and footers, articles, and navigation.

You will learn more about the elements that can be the content of the body element throughout the following chapters.

Our First Web Page

In our first example, we will create a very simple web page. This will help us to understand the structure of an HTML document and where we put different types of content.

Exercise 1.01: Creating a Web Page

In this exercise, we will create our first web page. This is the foundation upon which the future chapters will build.

Note

Before beginning the exercises in the book, please make sure you have followed the instructions given in the Preface regarding installing VSCode and the extension Open In Default Browser.

The steps are as follows:

  1. To start, we want to create a new folder, named Chapter01, in a directory of your choice. Then open that folder in Visual Studio Code (File > Open Folder…).
  2. Next, we will create a new plain text file by clicking File > New File. Then, save it in HTML format, by clicking File > Save As... and enter the File name: Exercise 1.01.html. Finally, click on Save.
  3. In Exercise 1.01.html, we start by writing the doctype declaration for HTML5:
    <!DOCTYPE html>
  4. Next, we add an HTML tag (the root element of the HTML document):
    <html lang="en">
    </html>
  5. In between the opening and closing tags of the html element, we add a head tag. This is where we can put metadata content. For now, the head tag will contain a title:
    <head>
        <title>HTML and CSS</title>
    </head>
  6. Below the head tag and above the closing html tag, we can then add a body tag. This is where we will put the majority of our content. For now, we will render a heading and a paragraph:
    <body>
        <h1>HTML and CSS</h1>
        <p>How to create a modern, responsive website with HTML and CSS</p>
    </body>

If you now right-click on the filename in VSCode on the left-hand side of the screen and select Open In Default Browser, you will see the following web page in your browser:

Figure 1.10: The web page as displayed in the Chrome web browser

Figure 1.10: The web page as displayed in the Chrome web browser

Metadata

The head element is home to most machine-read information in an HTML document. We will look at some commonly used metadata elements and how they enhance a web page and how they can optimize a web page for search engines and modern browsers.

The following elements are considered metadata content: base, link, meta, noscript, script, style, and title.

We've already added a title element in the previous exercise. This is the name of your web page and it appears in the tab of most modern browsers as well as in a search engine's results as the heading for the web page's listing.

The link element lets us determine the relationships between our document and external resources. A common use for this element is to link to an external style sheet. We will look at that use case in the section on CSS later in this chapter. There are several other uses for the link element. These include linking to icons and informing the browser to preload assets.

The base element lets you set a base URL. This will be used as the base for all relative URLs in the HTML document. For example, we could set the base href and then link to a style sheet with a relative URL:

<base href="http://www.example.com">
<link rel="stylesheet" href="/style.css">

This would result in our browser trying to download a style sheet from http://www.example.com/style.css.

The meta element acts as a catch-all for other metadata not represented by the other metadata content elements. For example, we can use the meta element to provide a description or information about the author of the web page.

Another use for the meta element is to provide information about the HTML document, such as the character encoding used. This can be very important as text characters will render differently or not at all if not set correctly. For example, we normally set the character encoding to UTF-8:

<meta charset="utf-8">

This character encoding declaration tells the browser the character set of the document. UTF-8 is the default and is recommended. This gives information to the browser but does not ensure the document conforms to the character encoding. It is also necessary to save the document with the correct character encoding. Again, UTF-8 is often the default but this varies with different text editors.

It is important that the character encoding declaration appears early in the document as most browsers will try to determine the character encoding from the first 1,024 bytes of a file. The noindex attribute value is set for the web pages that need not be indexed, whereas the nofollow attribute is set for preventing the web crawler from following links.

Another meta element that is very useful for working with mobile browsers and different display sizes is the viewport element:

<meta name="viewport" content="width=device-width, initial-scale=1">

The viewport element is not standard but is widely supported by browsers and will help a browser define the size of the web page and the scale to which it is zoomed on smaller display sizes. The units of viewport height and viewport width are vh and vw respectively; for example, 1vh = 1% of the viewport width. We will dive deeper into the viewport element and other aspects of responsive web development in Chapter 6, Responsive Web Design and Media Queries.

The script element lets us embed code in our HTML document. Typically, the code is JavaScript code, which will execute when the browser finishes parsing the content of the script element.

The noscript element allows us to provide a fallback for browsers without scripting capabilities or where those capabilities are switched off by the user.

We will look at the style element in more detail when we look at CSS later in this chapter.

These elements won't appear on the web page as content the user sees in the browser. What they do is give web developers a lot of power to tell a browser how to handle the HTML document and how it relates to its environment. The web is a complex environment and we can describe our web page for other interested parties (such as search engines and web crawlers) using metadata.

Exercise 1.02: Adding Metadata

In this exercise, we will add metadata to a web page to make it stand out in search engine results. The page will be a recipe page for a cookery website called Cook School. We want the page's metadata to reflect both the importance of the individual recipe and the larger website so it will appear in relevant searches.

To achieve this, we will add metadata – a title, a description, and some information for search engine robots. On the web, this information could then help users find a blog post online via a search engine.

Here are the steps we will follow:

  1. Open the Chapter01 folder in VSCode (File > Open Folder…) and create a new plain text file by clicking File > New File. Then, save it in HTML format by clicking File > Save As...and enter the File name: Exercise 1.02.html. Next, we will start with a basic HTML document:
    <!DOCTYPE html>
    <html lang="en">
        <head>
            <!-- Metadata will go in the head -->
        </head>
        <body>
            <!-- Cupcake recipe will go in the body -->
        </body>
    </html>
  2. Let's add a title for the recipe page that will be relevant to users who have navigated to the page or who are looking at a search engine results page. We will add this to the head element:
    <title>Cook School - Amazing Homemade Cupcakes</title>
  3. Just after the opening <head> element, we will add a metadata element, <meta>, to let the browser know which character encoding to use:
    <meta charset="utf-8">
  4. Next, we are going to add a description meta element below the title element:
    <meta name="description" content="Learn to bake delicious, homemade cupcakes with this great recipe from Cook School.">
  5. We will add another meta element. This time, it is the robots meta element, which is used to make search engine crawling and indexing behave in a certain way. For example, if you didn't want a page to be indexed by a search engine, you could set the value to noindex. We will set a value of nofollow, which means a web crawler will not follow links from the page:
    <meta name="robots" content="nofollow">

    If you don't set this tag, the default value will be index and follow. This is normally what you want but you might not want a search engine to follow links in comments or index a particular page.

  6. The viewport meta element, which is very useful for working with mobile browsers and different display sizes, is added just below the title element in the head element:
    <meta name="viewport" content="width=device-width, initial-scale=1">
  7. To finish, let's add some content to the body element that correlates with the metadata we've added:
    <h1>Cook School</h1>
    <article>
        <h2>Amazing Homemade Cupcakes</h2>
        <p>Here are the steps to serving up amazing cupcakes:</p>
        <ol>
             <li>Buy cupcakes from a shop</li>
             <li>Remove packaging</li>
             <li>Pretend you baked them</li>
         </ol>
    </article>

If you now right-click on the filename in VSCode on the left-hand side of the screen and select Open In Default Browser, you will see the following web page in your browser:

Figure 1.11: The web page as displayed in the Chrome web browser

Figure 1.11: The web page as displayed in the Chrome web browser

The important thing in the relationship between content and metadata is that they should make sense together. There is no point in adding keywords or writing a description of cars if the article is about cupcakes. The metadata should describe and relate to your actual content.

There are many search engines out there and they all do things a bit differently, and often with their own bespoke meta elements. If you would like to know more about how Google's search engine understands the meta tags from your web page's source code, some information is available at https://packt.live/35fRZ0F.

Mistakes in HTML

Most browsers do their best to render a web page even if the HTML does not comply perfectly with the W3C's HTML5 standard. One area where HTML5 differs from the previous versions, including XHTML, is that the standard gives detailed instructions for browser developers on how to handle mistakes and issues in an HTML5 document. HTML5 tries to standardize how browsers handle problems and there is a lot of flexibility built into the standard (such as optional omitted end tags).

With that said, there are still many ways that an HTML document might be wrong due to typos, omitted tags, or the incorrect use of tags. Let's look at a few potential mistakes.

A common problem is a missing or mistyped closing tag. Here, we can see an example: in the following snippet of HTML, we have a paragraph with two anchor elements, both of which are pointing at different pages of the Packt website:

<p>
    Learn about <a href="https://www.packtpub.com/web-development">web     development</a>. Try out some of the <a     href="https://www.packtpub.com/free-learning">Free learning on the     Packt site.
</p>
<p>
    Lorem ipsum...
</p>

There is one problem with this code. The second link does not have a closing tag and so the anchor element never closes. This makes the rest of the paragraph and the next paragraph in the document the same anchor tag. Anything beneath the opening anchor tag (<a>) until another closing anchor tag (</a>) would become an active link due to this mistake.

We can see the result in the following figure where the link text runs on to the second paragraph:

Figure 1.12: Missing closing tag on an anchor element

Figure 1.12: Missing closing tag on an anchor element

Some issues are not to do with syntax error but are regarding the semantic constraints of HTML5. In other words, an element might have a specific role or meaning and having more than one instance might not make sense.

For example, the main element describes the main content of an HTML document. There should never be more than one main element visible on a web page at any one time.

The following code would not be valid:

<body>
     <main id="main1"><!-- main content here … --></main>
     <main id="main2"><!-- more main content here ... --></main>
</body>

However, if we were to hide one of the instances of the main element and only render that one when we hide the other, we would be using the main element in a way that is acceptable. The browser could still determine what the main content of our web page is. For example, the following code would be valid:

<body>
     <main id="main1"><!-- main content here … --></main>
     <main id="main2" hidden><!-- more main content here ... --></main>
</body>

Look carefully and you will see that we have added the hidden attribute to the second instance of the main element. This means there is only one visible main element in the web page.

You will learn more about main and other structural elements in the next chapter.

Sometimes, mistakes are caused by not knowing the specification. Take, for example, Boolean attributes such as the disabled attribute. We can apply this attribute to some interactive elements such as form inputs and buttons.

A button element creates a clickable button UI on a web page. We can use this element to trigger form submissions or to change the web page. We can use the disabled attribute with this element to stop it from submitting or taking any action.

If we add the disabled attribute like this, <button disabled="false">Click me!</button>, we might expect this element to be enabled. We've set the disabled attribute to false, after all. However, the specification for the disabled attribute says that the state of the element is decided by whether the attribute is present or not and the value is not regarded. To enable the element, you must remove the disabled attribute.

Because of the ways most modern browsers try to correct problems in HTML5 documents, it might not be immediately obvious what the benefits of making your HTML document valid are. However, it is good to keep in mind that, while developing for the web, you could have an audience on a variety of browsers – not all of them the most modern. Equally, it is still very easy to make mistakes that will cause obvious rendering issues. The best way to solve these is to make sure your document is valid and therefore working as expected.

There are tools available to help you check that your web page is valid. In the forthcoming exercise, we will look at how we can use an online tool to validate a web page.

Validating HTML

Mistakes in HTML5 can cause our web pages to render in ways we are not expecting. They can also cause problems for screen reader technologies that rely on the semantic meaning of HTML elements. Thankfully, there are some really useful tools out there to automate the validation of our HTML document and to keep us from making costly mistakes.

In this section, we will introduce the W3C's Markup Validation Service, an online tool that will validate a web page for us. We will then try out the tool with the help of exercises.

W3C's Markup Validation Service is an online tool that lets us validate a web page. The tool is available at https://packt.live/323qgOI. Navigating to that URL, we will see the tool as in the following figure:

Figure 1.13: The W3C's Markup Validation Service

Figure 1.13: The W3C's Markup Validation Service

There are several options available, depending on how you wish to provide the validator a web page to validate. The options are:

  • Validate by URI – choose a publicly accessible URL you wish to validate
  • Validate by File Upload – validate a file uploaded from your computer
  • Validate by Direct Input – copy and paste code to validate

As well as these input options, you have some more advanced options under the More Options heading, as seen in the following figure:

Figure 1.14: The More Options panel of the W3C's Markup Validation Service

Figure 1.14: The More Options panel of the W3C's Markup Validation Service

With these options, you can:

  • Set the character encoding and document type
  • Group error messages
  • Show source code
  • Set the level of output (verbose)

Once you hit the Check button on the validator, it will run the tool and your results will appear in the results panel. You will either see a message telling you your document is valid or you will see a list of errors describing where the document is invalid and possible reasons.

We will see examples of both these results in the next two exercises.

Exercise 1.03: Validation

In this exercise, we will validate a web page using the W3C's Markup Validation Service. The steps are as follows:

  1. For this exercise, we need a web page to validate. Create a new file within the Chapter01 folder by clicking File > New File. Then, save it in HTML format, by clicking File > Save As...and enter the File name: Exercise 1.03.html. Copy the following content into the file:
    <!DOCTYPE html>
    <html lang="en">
        <head>
            <meta charset="utf-8">
            <title>Valid HTML document</title>
            <meta name="viewport" content="width=device-width,           initial-scale=1">
        </head>
        <body>
            <h1>Valid HTML document</h1>
            <p>This document is valid HTML5.</p>
            <!-- 
                This document will not throw errors in 
                W3C's Markup Validation Service 
            -->
        </body>
    </html>
  2. In a browser, navigate to https://packt.live/323qgOI. This will take you to the W3C's online Markup Validation Service.
  3. You can validate web pages by URI, file upload, or copy and paste. We will use the file upload method. Click the Validate by File Upload tab.
  4. Click the Choose file button to select the Exercise 1.03.html file.
  5. Click the Check button.

If all went well, we should see a results page similar to that shown in the following figure, where there is green highlighted text saying Document checking completed. No errors or warnings to show. This means we have a valid HTML document:

Figure 1.15: W3C's Markup Validation Service results page with no errors

Figure 1.15: W3C's Markup Validation Service results page with no errors

Exercise 1.04: Validation Errors

Now we will see what happens if the HTML document does not validate. Here are the steps:

  1. Firstly, we need a web page with some errors in its source code. Create a new file under Chapter01 folder by clicking File > New File. Then, save it in HTML format, by clicking File > Save As... and enter the File name: Exercise 1.04.html.
  2. In Exercise 1.04.html, we will add the following content:
    <html lang="en">
        <head>
        </head>
        <body>
            <p>Hello world!</p>
            <title>My first web page</title>
        </body>
    </html>

    This HTML document has some problems that should cause validation errors when this page is run through the W3C's validation service.

  3. Repeat the steps from Exercise 1.03, Validation, uploading the Exercise 1.04.html file in place of the valid file.

    The results should look like the following figure. Each error is flagged with a line number. In our case, there should be three errors because the doctype is missing, a <title> element is expected in the <head> element of the document, and <title> is not allowed as a child of the <body> element.

    The error messages can point out issues with the content model, such as the <title> element missing in a <head> element, as well as issues where an opening tag does not have a corresponding closing tag:

Figure 1.16: Validation errors in the W3C's Markup Validation Service

Figure 1.16: Validation errors in the W3C's Markup Validation Service

The HTML5 standard is pretty robust and tries to handle things such as omitted closing tags, but it is still possible to cause errors with typos or missed tags, and so the validator is a very useful tool. A valid HTML document is likely to be better optimized for performance, cause fewer bugs in JavaScript or CSS, and be easier for web crawlers, search engines, and browsers to understand.

Activity 1.01: Video Store Page Template

We've been tasked with creating a website for an online on-demand film store called Films On Demand. We don't have designs yet but want to set up web page boilerplate that we can use for all the pages on the site.

We will use comments as placeholders to know what needs to change for each page that is built on top of the boilerplate template. For visible content in the body element, we will use lorem ipsum to get an idea of how content will flow.

The following figure shows the expected output for this activity:

Figure 1.17: Expected output for the video store page template

Figure 1.17: Expected output for the video store page template

The steps are as follows:

  1. Create a file named Activity 1.01.html.
  2. We want the page to be a valid HTML5 document. So, we will need to add the following:

    The correct doctype definition.

    Elements to structure the document: the html element, the head element, and the body element.

    A title element that combines the Films on Demand brand with some specifics about the current page.

    Metadata to describe the site – we'll set this to Buy films from our great selection. Watch movies on demand.

    Metadata for the page character set and a viewport tag to help make the site render better on mobile browsers.

  3. We want to add placeholders for a heading (an h1 element) for the page, which we will populate with lorem ipsum and a paragraph for the content flow, which we will also populate with the following lorem ipsum text:

    "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam quis scelerisque mauris. Curabitur aliquam ligula in erat placerat finibus. Mauris leo neque, malesuada et augue at, consectetur rhoncus libero. Suspendisse vitae dictum dolor. Vestibulum hendrerit iaculis ipsum, ac ornare ligula. Vestibulum efficitur mattis urna vitae ultrices. Nunc condimentum blandit tellus ut mattis. Morbi eget gravida leo. Mauris ornare lorem a mattis ultricies. Nullam convallis tincidunt nunc, eget rhoncus nulla tincidunt sed.

    Nulla consequat tellus lectus, in porta nulla facilisis eu. Donec bibendum nisi felis, sit amet cursus nisl suscipit ut. Pellentesque bibendum id libero at cursus. Donec ac viverra tellus. Proin sed dolor quis justo convallis auctor sit amet nec orci. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus."

    Note

    The solution to this activity can be found on page 584.

CSS

Cascading Style Sheets (CSS) is a style sheet language used to describe the presentation of a web page. The language is designed to separate concerns. It allows the design, layout, and presentation of a web page to be defined separately from content semantics and structure. This separation helps keeps source code readable and it is important because a designer can update styles separately from a developer who is creating the page structure or a web editor who is changing content on a page.

A set of CSS rules in a style sheet determines how an HTML document is displayed to the user. It can determine whether elements in the document are rendered at all, whether they appear in some context but not others, how they are laid out on the web page, whether they are rendered in a different order to the order in which they appear within a document, and their aesthetic appearance.

We will begin by looking at the syntax of CSS.

Syntax

A CSS declaration is made of two parts: a property and a value. The property is the name for some aspect of style you want to change; the value is what you want to set it to.

Here is an example of a CSS declaration:

color: red;

The property is color and the value is red. In CSS, color is the property name for the foreground color value of an element. That essentially means the color of the text and any text decoration (such as underline or strikethrough). It also sets a currentcolor value.

For this declaration to have any effect on an HTML document, it must be applied to one or more elements in the document. We do this with a selector. For example, you can select all the <p> elements in a web page with the p selector. So, if you wanted to make the color of all text in all paragraph elements red, you would use the following CSS ruleset:

p {
  color: red;
}

The result of this CSS ruleset applied to an HTML document can be seen in the following figure:

Figure 1.18: Result of a CSS rule applied to <p> elements in HTML

Figure 1.18: Result of a CSS rule applied to <p> elements in HTML

The curly braces represent a declaration block and that means more than one CSS declaration can be added to this block. If you wanted to make the text in all paragraph elements red, bold, and underlined, you could do that with the following ruleset:

p {
  color: red;
  font-weight: bold;
  text-decoration: underline;
}

The result of this CSS ruleset applied to an HTML document can be seen in the following figure:

Figure 1.19: Several CSS declarations applied to <p> elements in HTML

Figure 1.19: Several CSS declarations applied to <p> elements in HTML

Multiple selectors can share a CSS ruleset. We can target these with a comma-separated list. For example, to apply the color red to p elements, h1 elements, and h2 elements, we could use the following ruleset:

p, h1, h2 {
  color: red;
}

Multiple CSS rulesets form a style sheet. The order of these CSS rules in a style sheet is very important as this is partly how the cascade or specificity of a rule is determined. A more specific rule will be ranked higher than a less specific rule and a higher-ranked rule will be the style shown to the end user. We will look at cascade and specificity later in this chapter:

Figure 1.20: A CSS ruleset explained

Figure 1.20: A CSS ruleset explained

Adding Styles to a Web Page

There are several ways to add your styles to a web page:

  • You can use inline styles, which are applied directly to an element in the HTML document using the style attribute. The value of the style attribute is a CSS declaration block, meaning you can apply a semicolon-separated list of CSS declarations to the element.
  • You can use a style element to add style information to an HTML document. The style element can be a child of either the head element or body element of a document. The head element tends to be preferable as the styles will be applied to your page more quickly.
  • You can provide a style sheet as an external resource using the link element. One of the rationalities behind style sheets is the separation of concerns, which is why this approach is often recommended.

We will try out each of these methods in the following exercises.

Exercise 1.05: Adding Styles

In this exercise, we will be styling web pages by adding styles within the HTML document itself.

Here are the steps:

  1. Open the Chapter01 folder in VSCode (File > Open Folder…) and we will create a new plain text file by clicking File > New File. Then, save it in HTML format, by clicking File > Save As... and enter the File name: Exercise 1.05.html and start with the following web page:
    <!DOCTYPE html>
    <html lang="en">
        <head>
            <meta charset="utf-8">
            <title>Adding styles</title>
        </head>
        <body>
            <h1>Adding styles</h1>
            <p>First paragraph</p>
            <p>Second paragraph</p>
        </body>
    </html>

    Without any styles, this web page would look like the following:

    Figure 1.21: The unstyled web page

    Figure 1.21: The unstyled web page

  2. We've decided to use a nicer font and make some of the text red. To do this, we will add a style element to the head element. We can add the following code under the title element:
    <style>
     h1 {
        font-family: Arial, Helvetica, sans-serif;
        font-size: 24px;
        margin: 0;
        padding-bottom: 6px;
     }
     p {
        color: red;
     }
    </style>

    The results of this code change are that we should now have styles applied to the h1 element and to both of the p elements, all of which will have red text. The result will look similar to the following figure:

    Figure 1.22: The web page with styles applied

    Figure 1.22: The web page with styles applied

  3. Finally, we will give the first paragraph element a different style by overriding the style set in the head element. Let's add an inline style to the first paragraph, setting the color to blue and adding a line-through text decoration as follows:
            <p style="color: blue; text-decoration: line-          through">First paragraph</p>

If you now right-click on the filename in VSCode on the left-hand side of the screen and select Open In Default Browser, you will see the following web page in your browser:

Figure 1.23: The web page with inline style applied

Figure 1.23: The web page with inline style applied

Something to note is that the inline style, applied to the first paragraph, takes precedence over the more general CSS rule applied to all p elements in the style element in the head element of the document. We will look at specificity and the rules of the cascade later in this chapter, but first, let's try moving these style rules into an external file.

Exercise 1.06: Styles in an External File

In this exercise, we will separate the concerns of presentation and structure of Exercise 1.05, Adding Styles, by moving all the styles to an external file.

The steps are as follows:

  1. Open the Chapter01 folder in VSCode (File > Open Folder…) and create a new plain text file by clicking File > New File. Then, save it in HTML format, by clicking File > Save As... and enter the File name: Exercise 1.06.html.
  2. Add the same web page as in Exercise 1.05, Adding Styles, to the file:
    <!DOCTYPE html>
    <html lang="en">
        <head>
            <meta charset="utf-8">
            <title>Adding styles</title>
        </head>
        <body>
            <h1>Adding styles</h1>
            <p>First paragraph</p>
            <p>Second paragraph</p>
        </body>
    </html>
  3. We will add a link element to reference a .css file below the title element:
    <link href="styles/Exercise_1.06.css" rel="stylesheet">
  4. Create a styles directory in the same directory as Exercise 1.06.html. Next, create a file named Exercise_1.06.css within the styles directory.
  5. Now, add the following styles to Exercise_1.06.css:
    h1 {
      font-family: Arial, Helvetica, sans-serif;
      font-size: 24px;
      margin: 0;
      padding-bottom: 6px;
    }
    p {
      color: red;
    }
  6. To get the equivalent styles that we had at the end of Exercise 1.05, Adding Styles, without using an inline style, we have to have a specific way of targeting the first p element. We will use the :first-of-type pseudo-class. You will learn more about CSS selectors later in this chapter. For now, add this CSS rule to the bottom of Exercise_1.06.css:
    p:first-of-type {
      color: blue;
      text-decoration: line-through;
    }

The result will be as seen in Figure 1.23 – the same result as in Exercise 1.05, Adding Styles. The difference is that we have removed all references to styles from the HTML document into their own external resources. We have successfully separated concerns.

Both these methods add styles to the HTML document when it loads. Similar to the HTML DOM, we can manipulate CSS programmatically with JavaScript. This is because the styles are also represented as an object model called the CSSOM.

CSSOM

The CSS Object Model (CSSOM) is similar to the HTML DOM, which we described earlier. The CSSOM is an in-memory representation of the styles in the document as they are computed on elements. It is a tree-structure with nodes that mirror those in the HTML DOM, and the objects associated have a list of style properties where all CSS rules have been applied.

The CSSOM represents all the styles that have been created in the document as objects with properties that we can change with JavaScript. We can access these styles and change the values of style properties.

We mostly access these styles via the style property of a DOM element, as here:

const boldElement = document.querySelector('.aBoldElement');
boldElement.style.fontWeight = 'bold';

In JavaScript, we can also access the CSSOM with the getComputedStyle method on the window object; for example:

const boldElement = document.querySelector('.aBoldElement');
window.getComputedStyle(boldElement);

This will return a computed styles object for an element with the aBoldElement class attribute. This method returns a read-only styles object with all computed styles for the element.

In the next section, we will look at the different CSS selectors we can use to apply our styles to a web page.

CSS Selectors

To target elements in the HTML document with CSS, we use selectors. There are a lot of options available to help you select a wide range of elements or very specific elements in certain states.

Selectors are a powerful tool and we will look at them in some detail as the different options available can help with both web page performance and making your CSS more maintainable.

For example, you can use a selector to target the first letter of a heading, like you might expect to see in a medieval book:

h1::first-letter { 
  font-size: 5rem; 
}

Or you could use a selector to invert the colors of every odd paragraph in an article:

p {
  color: white;
  background-color: black;
}
p:nth-of-type(odd) { 
  color: black;
  background-color: white;
}

We will explore a variety of the options available to us when creating selectors.

Element, ID, and Class

Three commonly used selectors are:

  • Element type: For example, to select all p elements in an HTML document, we use the p selector in a CSS ruleset. Other examples are h1, ul, and div.
  • A class attribute: The class selector starts with a dot. For example, given the HTML snippet <h1 class="heading">Heading</h1>, you could target that element with the .heading selector. Other examples are .post and .sub-heading.
  • An id attribute: The id selector starts with a hash symbol. For example, given the HTML snippet <div id="login"> <!-- login content --> </div>, you could target this element with the #login selector. Other examples include #page-footer and #site-logo.

The Universal Selector (*)

To select all elements throughout an HTML document, you can use the universal selector, which is the asterisk symbol (*). Here is an example snippet of CSS that is often added to web pages; a value is set on the html element and then inherited by all descendant elements:

html {
  box-sizing: border-box;
}
*, *:before, *:after {
  box-sizing: inherit;
}

Using the inherit keyword and the universal selector, we can pass a value on to all the descendants of the html element. This snippet will universally apply the border-box model to all elements and their pseudo-elements (that's the reason for :before and :after). You'll learn more about the box model and layout in the next chapter.

Attribute Selectors

Attribute selectors let you select elements based on the presence of an attribute or based on the value of an attribute. The syntax is square brackets, [], with the suitable attribute inside. There are several variations that you can use to make matches:

  • [attribute] will select all elements with an attribute present; for example, [href] will select all elements with an href attribute.
  • [attribute=value] will select all elements with an attribute with an exact value; for example, [lang="en"] will select all elements with a lang attribute set to en.
  • [attribute^=value] will select all elements with an attribute with a value that begins with the matching value; for example, [href^="https://"] will select all elements with an href attribute beginning with https://, which links to a secure URL.
  • [attribute$=value] will select elements with an attribute with a value that ends with the matching value; for example, [href$=".com"] will select all elements with an href attribute that ends with .com.
  • [attribute*=value] will select elements with an attribute with a value that has a match somewhere in the string; for example, [href*="co.uk"] will select all elements with an href attribute matching .co.uk. http://www.example.co.uk?test=true would be a match, as would https://www.example.co.uk.

Pseudo-classes

To select an element when it is in a particular state, we have several pseudo-classes defined. The syntax of a pseudo-class is a colon, :, followed by a keyword.

There are a great number of pseudo-classes, but most developers' first experience of them is when styling links. A link has several states associated with it:

  • When an anchor element has an href attribute, it will have the :link pseudo-class applied to it.
  • When a user hovers over the link, the :hover pseudo-class is applied to it.
  • When the link has been visited, it has the :visited pseudo-class applied to it.
  • When the link is being clicked, it has the :active pseudo-class applied to it.

Here is an example of applying styling to the various pseudo-class states of an anchor element:

a:link, a:visited {
    color: deepskyblue;
    text-decoration: none;
}
a:hover, a:active {
    color: hotpink;
    text-decoration: dashed underline;
}

In the following figure, we can see the first link with the :link or :visited styles applied and the second link with the :hover or :active styles applied:

Figure 1.24: Link with and without the hover state

Figure 1.24: Link with and without the hover state

The cascade can cause some issues with styling links. The order in which you specify your CSS rules for each state of the link is important. If, for example, we applied the a:hover rule before the a:link rule in the previous example, we would not see the hover effect. A mnemonic exists for remembering the order: love-hate. The l is for :link, the v is for :visited, the h is for :hover, and the a is for :active.

Some other useful pseudo-classes for selecting elements in a particular interactive state include :checked, :disabled, and :focus.

There are several pseudo-classes that help us select a pattern of children nested under an element. These include :first-child, :last-child, :nth-child, :nth-last-child, :first-of-type, :last-of-type, :nth-of-type, and :nth-last-of-type.

For example, we can use :nth-child with an unordered list to give a different style to list items based on their position in the list:

<style>
  ul {
    font-family: Arial, Helvetica, sans-serif;
    margin: 0;
    padding: 0;
  }
  li {
    display: block;
    padding: 16px;
  }
  li:nth-child(3n-1) {
    background: skyblue;
    color: white;
    font-weight: bold;  
  }
  li:nth-child(3n) {
    background: deepskyblue;
    color: white;
    font-weight: bolder;
  }
</style>
<!-- unordered list in HTML document -->
<ul>
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
    <li>Item 4</li>
    <li>Item 5</li>
    <li>Item 6</li>
    <li>Item 7</li>
</ul>

The following figure shows the result. The :nth-child pseudo-class gives you a lot of flexibility because you can use keywords such as odd and even or functional notation such as 3n - 1:

Figure 1.25: Using the :nth-child pseudo-class

Figure 1.25: Using the :nth-child pseudo-class

Pseudo-elements

Pseudo-element selectors are preceded by two colons (::) and they are used to select part of an element. The available pseudo-elements include ::after, ::before, ::first-letter, ::first-line, ::selection, and ::backdrop.

These pseudo-elements give us a handle we can use to add stylistic elements without adding to the HTML document. This can be a good thing if the pseudo-element has no semantic value and is purely presentational, but it should be used with care.

Combining Selectors

What makes CSS selectors particularly powerful is that we can combine them in several ways to refine our selections. For example, we can select a subset of li elements in an HTML document that also has a .primary class selector with li.primary.

We also have several options, sometimes called combinators, for making selections based on the relationships of elements:

  • To select all the li elements that are descendants of a ul element, we could use ul li.
  • To select all the li elements that are direct children of a ul element with the primary class, we might use ul.primary > li. This would select only the direct children of ul.primary and not any li elements that are nested.
  • To select an li element that is the next sibling of li elements with the selected class, we could use li.selected + li.
  • To select all of the li elements that are the next siblings of li elements with the selected class, we could use li.selected ~ li.

The following figure shows the difference between using li.selected + li and li.selected ~ li:

Figure 1.26: Selecting the next adjacent sibling compared to selecting all of the next siblings

Figure 1.26: Selecting the next adjacent sibling compared to selecting all of the next siblings

Let's try out some of the selectors we've learned about in an exercise.

Exercise 1.07: Selecting Elements

In this exercise, we will differentiate list items by styling the odd items. We will use a class selector to style a selected item and a next-siblings combinator to style the elements after the selected item.

The steps are as follows:

  1. Open the Chapter01 folder in VSCode (File > Open Folder…) and we will create a new plain text file by clicking File > New File. Then, save it in HTML format, by clicking File > Save As... and enter the File name: Exercise 1.07.html. Now, copy the following simple web page with a ul list element and nine list items:
    <!DOCTYPE html>
    <html lang="en">
        <head>
            <meta charset="utf-8">
            <title>Selectors</title>
        </head>
        <body>
            <ul>
                <li>Item 1</li>
                <li>Item 2</li>
                <li>Item 3</li>
                <li>Item 4</li>
                <li>Item 5</li>
                <li>Item 6</li>
                <li>Item 7</li>
                <li>Item 8</li>
                <li>Item 9</li>
           </ul>
        </body>
    </html>
  2. So that we can style a selected item differently, we will add a selected class to the fifth list item:
                <li class="selected">Item 5</li>
  3. Next, we will add a style element to the head element with the following CSS:
        <head>
            <meta charset="utf-8">
            <title>Selectors</title>
            <style>
              ul {
                  font-family: Arial, Helvetica, sans-serif;
                  margin: 0;
                  padding: 0;
               }
               li {
                   display: block;
                   padding: 16px;
                }
           </style>
           </head>

    This will remove some of the default styling of the unordered list in the browser. It will remove margins and padding on the list and set the font style to Arial (with Helvetica and sans-serif as a fallback).

  4. Next, we will style the odd list items with the :nth-child pseudo-class. We can use the odd keyword for this. With this style, any odd list item will have a blue background and white text:
    li:nth-child(odd) {
         background-color: deepskyblue;
         color: white;
         font-weight: bold;
    }

    This gives us the stripy effect that we can see in the following figure:

    Figure 1.27: Stripy list using :nth-child(odd)

    Figure 1.27: Stripy list using :nth-child(odd)

  5. We can style the selected class selector:
    li.selected {
         background-color: hotpink;
    }

    This overrides the striped effect for the selected item as seen in the following figure:

    Figure 1.28: Stripy list with a selected item

    Figure 1.28: Stripy list with a selected item

  6. Finally, we will style the odd list items after the selected item using the all-next-siblings combinator:
    li.selected ~ li:nth-child(odd) {
         background-color: orange;
    }

If you now right-click on the filename in VSCode on the left-hand side of the screen and select Open In Default Browser, you will see the following web page in your browser:

Figure 1.29: Combining selectors to style a list

Figure 1.29: Combining selectors to style a list

Style sheets can have a large number of style rules and combinations of selectors. It is good to understand why one rule takes precedence over another one. This is where CSS specificity comes in.

CSS Specificity

If we have two CSS declarations that have an effect on the same style property of an element, how do we know which of those declarations will take precedent?

There are several factors that decide the ranking of a CSS declaration and whether it is the style the browser will apply. The term for these factors is specificity.

A style attribute that adds inline styles to an element has the highest specificity value. An ID selector has a greater specificity value than a class selector and a class selector or attribute selector has a greater specificity value than an element type. We can calculate the specificity value by giving points to each of these specificity values.

The most common way of representing this is as a comma-separated list of integers, where the leftmost integer represents the highest specificity. In other words, the leftmost value is the inline style attribute; next is an ID selector; next is a class selector, pseudo-class, or attribute selector; and the rightmost value is an element.

An inline style would have the value 1, 0, 0, 0. An ID selector would have the value 0, 1, 0, 0. A class selector would have the value 0, 0, 1, 0, and an h1 element selector would have the value 0, 0, 0, 1.

Let's look at a few examples with more complex selectors:

  • li.selected a[href] has two element selectors (li and a), a class selector (.selected) and an attribute selector ([href]), so its specificity value would be 0, 0, 2, 2:
Figure 1.30: Calculating the specificity of li.selected a[href]

Figure 1.30: Calculating the specificity of li.selected a[href]

  • #newItem #mainHeading span.smallPrint has two ID selectors, a class selector (.smallPrint), and a span element, so its specificity value would be 0, 2, 1, 1:
Figure 1.31: Calculating the specificity of #newItem #mainHeading span.smallPrint

Figure 1.31: Calculating the specificity of #newItem #mainHeading span.smallPrint

Comparing the two selectors, we can see that the selector in the second example is more specific than the selector in the first example.

The Special Case of !important

The !important value can be appended to the value of any CSS declaration. It is a special keyword that can be applied to selectors to override the specificity value. It trumps any other specificity value. In terms of specificity value, it would add another column to become the value 1, 0, 0, 0, 0. It would even take precedence over an inline style.

For example, we might want to create a style rule that is reusable and lets us hide content on a web page. Something like this:

.hide {
  display: none;
}

If we apply this class to an element, we want that element to be hidden and to not be rendered on the web page. We might use this to later reveal the element using JavaScript. However, consider the following example:

<style>
 div.media {
  display: block;
  width: 100%;
  float: left;
 }
 .hide {
  display: none;
 }
</style>
<div class="media hide">
 ...Some content
</div>

We might expect our div element to be hidden because the .hide class appears second in the style sheet. However, if we apply the specificity calculations we've learned about, we can see that div.media scores 0, 0, 1, 1 and .hide only scores 0, 0, 1, 0. The div.media rule for the display property with block value will override the none value of the .hide class. We can't really use this instance of the .hide class as we don't know whether it will have any effect.

Now consider the same .hide class but using the !important keyword:

.hide {
  display: none !important;
}

Adding the !important keyword will make this .hide class much more reusable and useful as we can pretty much guarantee that it will hide content as we desire.

We've learned a lot about CSS in this part of the chapter. Let's apply some of this knowledge to an activity.

Activity 1.02: Styling the Video Store Template Page

In the previous activity, we were tasked with creating boilerplate HTML for a web page for the Films On Demand website. In this activity, we are going to add some style to that template page.

The following figure shows the expected output for this activity:

Figure 1.32: Expected output for styling the video store template page

Figure 1.32: Expected output for styling the video store template page

The steps are as follows:

  1. We will start with the template from Activity 1.01, Video Store Page Template, which we will save as Activity 1.02.html:
    <!DOCTYPE html>
    <html lang="en">
        <head>
           <meta charset="utf-8">
           <title>Films on Demand - <!-- Title for page goes here --        ></title>
           <meta name="description" content="Buy films from our great          selection. Watch movies on demand.">
           <meta name="viewport" content="width=device-width,          initial-scale=1">
        </head>
        <body>
              <h1>Lorem ipsum</h1>
              <p>
              Lorem ipsum dolor sit amet, consectetur adipiscing elit.           Nullam quis scelerisque mauris. Curabitur aliquam ligula           in erat placerat finibus. Mauris leo neque, malesuada et           augue at, consectetur rhoncus libero. Suspendisse vitae           dictum dolor. Vestibulum hendrerit iaculis ipsum, ac           ornare ligula. Vestibulum efficitur mattis urna vitae           ultrices. Nunc condimentum blandit tellus ut mattis.          Morbi eget gravida leo. Mauris ornare lorem a mattis           ultricies. Nullam convallis tincidunt nunc, eget           rhoncus nulla tincidunt sed. Nulla consequat tellus           lectus, in porta nulla facilisis eu. Donec bibendum           nisi felis, sit amet cursus nisl suscipit ut.           Pellentesque bibendum id libero at cursus. Donec ac           viverra tellus. Proin sed dolor quis justo convallis           auctor sit amet nec orci. Orci varius natoque           penatibus et magnis dis parturient montes, nascetur           ridiculus mus.
              </p>
        </body>
    </html>
  2. We are going to link to an external CSS file. One of the difficulties with styling web pages is handling differences between browsers. We are going to do this by adding a file to normalize our default styles. We will use the open source normalize.css for this. Download the file from https://packt.live/3fijzzn. Add the file to a styles folder and link to it from the Activity 1.02.html web page.
  3. We are going to add a style element to the head element of Activity 1.02.html. In the style element, we want to set some styles used across all pages. We want to do the following:

    Set box-sizing to border-box for all elements using the universal selector (*).

    Add a font family with the Arial, Helvetica, sans-serif values and a font size of 16px to the whole page.

    Add the background color #eeeae4 for the whole page. To do this, we will add a div element wrapper with the pageWrapper ID, where we will set the background color and padding of 16px, and a full-page class, where we will set the minimum height to 100vh (100% of the viewport height).

    Add an h1 element selector that sets the margin to 0 and adds padding of 16px to the bottom of the h1 element.

    Note

    The solution to this activity can be found on page 587.

We've learned a lot about HTML and CSS in this chapter. In the next section, we will learn a little bit about the Chrome developer tools and how we can use them to better understand our web page.

Dev Tools

Most browsers come with some tools to help web developers create and change web pages. One of the most useful of these tools is the built-in developer tools that come with the Chrome browser.

You can access the developer tools on any web page with the Command + Option + I keyboard shortcut (on Mac) and F12 or Control + Shift + I (on Linux and Windows).

On opening the developer tools, you should see something similar to the following figure:

Figure 1.33: Chrome developer tools (Elements tab)

Figure 1.33: Chrome developer tools (Elements tab)

There are a lot of options available in the developer tools. We will not cover all of them here but will focus on the top bar and the Elements tab in this chapter.

The Top Bar

The top bar gives you access to several options and tools, including access to all the other sections of the developer tools via the tabs:

Figure 1.34: Chrome DevTools top bar

Figure 1.34: Chrome DevTools top bar

The top bar has the following tools and options:

  • Select tool – You can use this tool to select an element from within the web page.
  • Devices Devices toolbar – Changes the view so you can select the view size of various devices.
  • Tabs – We can access various tools from the top bar menu such as Console, Elements, Sources, Network, and Performance. We will focus on the Elements tab.
  • Configuration Configuration – Gives you access to various settings for the developer tools.
  • Close Close – Closes the developer tools.

While developing the HTML and CSS for a web page, one of the tabs we use the most is the Elements tab.

The Elements Tab

The Elements tab has two areas – the left-hand panel shows the current HTML DOM and the right-hand panel shows details about the selected element.

You can use the left-hand panel to select an element from the HTML DOM and you can also edit an element to change its attributes:

Figure 1.35: Selectable HTML DOM in the left-hand panel of the Elements tab

Figure 1.35: Selectable HTML DOM in the left-hand panel of the Elements tab

Once you have an element selected, you can see a lot of information about the element in the right-hand panel. This information is divided into tabs and the first tab shows the styles:

Figure 1.36: The Styles tab of the right-hand panel of the Elements tab

Figure 1.36: The Styles tab of the right-hand panel of the Elements tab

Essentially, the Styles tab shows a representation of the CSSOM. You can look at the styles associated with the element, including the cascade of styles, showing you where a style is inherited from and where it has been set but overridden. The topmost element is the most specific. You can also use this tab to edit the styles of an element and to check different states, such as the hover state.

The Computed tab shows styles as they have been computed for the element.

There are also tabs to show you the event listeners and properties associated with an element.

Having had a glimpse at the power of Chrome's developer tools, let's finally consider how the browser works with HTML and CSS technologies to render a web page.

How a Web Page Renders

How does a web page render in the browser? We've learned a lot about HTML and CSS in this chapter, but let's see how these technologies are put together by the browser to render our web page.

The following figure shows a flowchart of the process, which is further explained below:

Figure 1.37: Flow chart of the web page render process

Figure 1.37: Flow chart of the web page render process

To summarize the process:

  1. The user starts by navigating to a URL, possibly via a hyperlink or by typing the URL into the address bar of their browser.
  2. The browser will make a GET request to the disk or a network. It will read the raw bytes from that location and convert them to characters (based on character encoding such as UTF-8).
  3. The browser then parses these characters according to the HTML standard to find the tokens that are familiar as HTML elements, such as <html> and <body>.
  4. Another parse is then made to take these tokens and construct objects with their properties and based on the rules appropriate to that token. At this point, the objects are defined.
  5. Finally, the browser can define the relationships between these objects and construct the HTML DOM for the web page.
  6. At this point, we have a DOM but not a rendered web page. The next task is to construct the CSSOM. Again, the browser will load any style sheet resources it needs to, which were found while parsing the document. It will then construct the styles associated with nodes in the tree structure, which gives us the CSSOM.
  7. With the information gathered in the DOM and the CSSOM, the browser can create a render tree. The render tree is constructed by combining information from the CSSOM and the HTML DOM. Nodes in the HTML DOM that will not be rendered (for instance, those with the display: none; style) are excluded from the render tree. Those that are rendered are enriched with their computed style rules.
  8. Now the browser has all the information it needs, it can begin to calculate the positions of elements in the rendered viewport. This is called the layout stage. The browser lays elements out based on their size and position within the browser viewport. This stage is often also called reflow. It means the browser must recalculate the positions of elements in the viewport when elements are added to or removed from the page or when the viewport size is changed.
  9. Finally, the browser will rasterize or paint each element on the page, depending on their styles, shadows, and filters to render the page the user will see.

That is a brief and simplified summary of the rendering of a web page. Think about how many resources might be loaded on a relatively complicated website and with JavaScript running events and we can see that much of this process happens frequently and not in such a linear manner. We can start to see the complexities of what a browser is doing when it renders your web page.

 

Summary

In this chapter, we have looked at how we write HTML and CSS and their roles in structuring and presenting a web page. We've looked at how to make sure our HTML document is working as we expect and is understandable to a web browser, and we've looked at how to target elements in the HTML document so we can style them.

To demonstrate our understanding, we have created a web page that we will use as a template for the pages of a website and we have added CSS to normalize the style and add some initial styles for the site.

In the next chapter, we will look at the options for structuring and laying out a web page and elements within it and how we can style these for different web page layouts.

About the Authors

  • Lewis Coulson

    Lewis Coulson is a London based senior front-end engineer with experience gained at a range of leading digital agencies, startups, corporations and consultancies. He is passionate about bridging the creative/technical divide and bringing innovative digital ideas to life using the latest cutting edge technologies.

    Browse publications by this author
  • Brett Jephson

    Brett Jephson started his career as a web developer in 2005. Having built web applications and games for everything from start-ups through to global corporations the one consistency has been a passion for web technologies.

    Browse publications by this author
  • Rob Larsen

    Rob Larsen is an experienced front-end engineer, team lead, and manager. He is an active writer and speaker on web technology with a special focus on the continuing evolution of HTML, CSS, and JavaScript. He is a co-author of Professional jQuery, the author of Beginning HTML and CSS, and the author of The Uncertain Web. He's also an active member of the open source community as a maintainer of several popular projects.

    Browse publications by this author
  • Matt Park

    Matt Park has been a web developer since 2007, and has worked for various web agencies around the UK and built many iconic brand websites over the years ranging from startups to large corporations. He currently works as a senior front-end developer for The Constant Media, and is involved with working with many high profile brand websites daily. Striving for pixel perfection, Matt aims to deliver high quality websites while maintaining high coding standards.

    Browse publications by this author
  • Marian Zburlea

    Marian Zburlea has been into web developing since 1997. His passion is to innovate and design for the future. He is also a proud mentor who helps the masses to jump-start their web developer career.

    Browse publications by this author

Recommended For You

The Python Workshop

Cut through the noise and get real results with a step-by-step approach to learning Python 3.X programming

By Andrew Bird and 4 more
The Java Workshop

Cut through the noise and get real results with a step-by-step approach to learning Java programming

By David Cuartielles and 2 more
The Data Science Workshop

Cut through the noise and get real results with a step-by-step approach to data science

By Anthony So and 4 more
Mastering PostgreSQL 12 - Third Edition

Master PostgreSQL 12 features such as advanced indexing, high availability, monitoring, and much more to efficiently manage and maintain your database

By Hans-Jürgen Schönig