Syllabus

Welcome to Web Development and Design by Oval! We're happy to have you here. Over the course of this class, you will learn everything you need in order to build and publish your own fully functional website online.

In this course reader, you will find notes and tutorials for each lecture. While the entire course reader is available to you beforehand, we suggest that you read each chapter only after you have attended the corresponding lecture and have completed all previous homework (though feel free to take a look at what's to come!).

Schedule

The objective of this course is to equip you with the knowledge required to build your own personal website—be it a page about yourself, your favorite movie, your pet, or whatever else that you envision1. To do so, the course is split into 4 different units, with individual subchapters. Each subchapter has a supporting 2-hour lecture, notes, and homework. Some chapters refer to separate readings to support the knowledge that you obtain in lectures. During Chapter 1.2, you will set up a repository (directory) for your upcoming website, and all of the later assignments will help you improve it. Below is the table of contents—it covers everything from what is a browser to how to deploy your final website online.


UNIT 1 - Technical Foundations

Chapter 1.1: Browsers, Servers, Command Line Tools, IDEs.

How does a browser work? How does it retrieve information and how does it display it? This chapter focuses on the conceptual overview of computer networking and it will introduce you to the tools that every web developer needs to be comfortable with in order to build efficient websites rapidly.

Chapter 1.2: Introduction to Git. Introduction to HTML.

In this chapter, you will learn how to use Git, a version control system used by millions of developers. You will also learn about HTML—a markup language that defines the structure of every website that you ever visited. After that, you will set up a repository for your own starter website on Github.

Chapter 1.3: Introduction to CSS and Advanced HTML Tags.

This chapter covers advanced HTML elements such as buttons, images, as well as semantic tags to help you organize your code for readibility. It will also explain what is CSS and will teach you how to style your HTML elements (i.e., how to add colors, margins, background images, etc).


UNIT 2 - Design

Chapter 2.1: Introduction to User Interface Design.

We will take a break from coding and explore what makes a website visually appealing and easy to use. What is a design personality? How to use typography and colors to define your website personality? What is a design system? After completing this chapter, you will be ready to answer questions like these, will know about fundamental UI/UX design patterns, and will start sketching your own website.

Chapter 2.2: Advanced User Interface Design.

How to space elements of the interface? How to create color palettes? What are advanced techniques for designing text? After completing this chapter, you will equipped with the most essential tools for designing your website, will do advanced sketches for your own website, and will be prepared to learn about designing software in the upcoming chapter.

Chapter 2.3: Design Tools.

In order to be able to quickly and efficiently design beautiful websites, it is important to know how to use prototyping software. A very popular (and free) choice among developers is Figma—an online platform used by millions of designers. In this chapter you will learn how to use it and will be ready to start creating the final design for your website.


UNIT 3 - Introduction to Programming

Chapter 3.1: Programming in JavaScript.

So far you have set up the structure of your website, its elements, designed its appearance, and even know how to style them in CSS. But how do you animate your website to be dynamic and feature-rich? Here is where programming comes in. In particular, all browsers use JavaScript to add programmed components into your website. Before progressing to implementing the design that you have developed in the previous unit, we will learn how to make a website interactive. In this chapter, you will learn fundamental computer science concepts like variables, conditional statements, and loops, and will learn how to use them in JavaScript.

Chapter 3.2: Functions and Event Handlers.

How do you set up your website's elements such that the user can interact with them and can change the state of your website? The solution is to use event listeners and handlers. In this chapter, you will learn about JavaScript functions and how to use them to make elements of your website interactive.


UNIT 4 - Responsive & Rapid UI Design

Chapter 4.1: Element Alignment and Tailwind CSS.

Positioning elements on a website can be tricky. After this chapter, however, you will master this skill—we will show you what is a CSS Flexbox and Grid Layout and how to make prototyping them a lot faster using a utility-first CSS framework Tailwind CSS.

Chapter 4.2: Layout, Positioning, and Responsive Design.

How do you position your elements on the screen and organize them into containers and grids? How do you make your website look good on all devices, regardless of their screen dimensions? In this chapter, we will learn what Tailwind CSS capabilities you may use to organize your content and optimize it for different screen dimensions.

Final classes

Beyond HTML, CSS, and JS. Office Hours.

The previous ten chapters have covered a substantial amount of information — in fact, we've designed them to cover the most important insights and skills we've gained ourselves over multiple years of web development. By now, your website is almost ready, though we realize that you may still have lingering questions. Use this time to ask us anything! Besides that, we will cover some of your possible next steps beyond the course during the lecture. For homework, you will finalize your website and deploy it online.

Project Presentation.

Congrats! You've worked very hard and we hope you are proud of what you have built. Share your website with us!


Course Policies

This course is fast-paced: over the duration of the course, you will learn fundamentals of computer science, networking, and front-end web development. In order to make sure that everyone is keeping up with the workload and is getting a solid grasp of the material, each lecture will be followed by homework that is due the upcoming lecture. For example, Lecture 1 will have Homework 1 that will be due Lecture 2.


1 Within reasonable complexity constraints, of course — we can't teach you how to build a new startup in one month, but you are definitely going to be proud of what you build!

Chapter 1.1 - Browsers, servers, command line tools, code editors.


Browsers, servers, command line tools, code editors.

In order to be able to build and deploy fascinating websites like you are about to create, you need to know the basic concepts first. In this chapter, you will get familiar with how browsers work and how they send requests to servers. Once you know that, we will transition to talking about tools that you will need to build your awesome website.

Chapter 1.1.1 - What is the Internet?


Before we delve into complicated questions, we need to answer a more fundamental one — what is the Internet. Generally speaking, it's a network of connected computers just like yours. They're connected in various ways: some are connected to the Internet with optic fiber (that travels at the speed of light), some with cellular networks, some with Wi-Fi, etc. What unites them is the languages they speak: protocols for exchanging information. The architecture of the Internet is very complicated and we will not go in-depth on these topics (save that for an advanced undergraduate course). However, we will provide a friendly overview of the most important components that we believe are crucial to know before you can embark on the journey of building your own website.

IP addresses

In most cases, each computer in the Internet has its own address. If you're on a shared Wi-Fi, than your computer would share the same IP address as other computers connected to the router, although it would still be a unique address. Sometimes they change: that's called a dynamic IP address. In most cases, though, the IP addresses are static. What's the difference? There's no fundamental difference, other than the fact that they change, and the reason why that happens is because your IP address is assigned to you by your Internet provider, and sometimes they recycle them for internal purposes.

Client vs. server

There are two main participants in the exchange of information via the Internet: the client and the server. The client is the computer that sends a request for some information to the server, and the server is the computer in charge of returning some requested information back to the client. For example, when you go to https://apple.com, you are the client and you are sending a request to some of the Apple's servers.

There are also two types of IP addresses currently available: IPv4 and IPv6. For the purposes of this course, we will only deal with IPv4 addresses. IPv4 address is represented by four numbers less or equal to 255 split by a dot (i.e. 192.168.0.1). Why 255? That is the maximum value that a byte can hold.

Server ports

Think of servers as office buildings. To reach a particular office, you would first need to know the address of its office building (IP address). Then, you'd need to know the office number. The analogy of an office number for servers is a port number: a digit ranging from 0 to 65536. Why 65536? That is the maximum value that two bytes can hold (though don't worry about this, and you certainly don't need to memorize that number). There are some conventions for port numbers; here are just a few:

  • 21 is for FTP servers (File Transfer Protocol)
  • 80 is for HTTP servers (Hyper-Text Transfer Protocol; explained below)
  • 443 is for HTTPS servers (Secure HTTPS; explained below)

80 and 443 are so common that you don't actually need to type them in your browser — simply use the IP address. For other ports, you would need to write the IP addresses followed by a colon and by the port number (i.e., 192.168.0.1:21). The website you will build will be available at ports 80 and 443 (unless you don't want others to be able to find them).

HTTP/HTTPS

HTTP is the protocol used by practically every website you ever visited. It is a standard protocol that your computer uses to form a request to the server and that the server uses to compile necessary information and send it back to you. For example, if you visit https://apple.com, your browser would actually create something like the HTTP request below and send it to Apple (this will differ from computer to computer). Note that it contains my operating system, my language, and other metadata that will allow Apple to customize their response to me.

GET / HTTP/2
Host: www.apple.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:88.0) Gecko/20100101 Firefox/88.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
DNT: 1
Connection: keep-alive
Cookie: ...
Upgrade-Insecure-Requests: 1
Sec-GPC: 1

In response, Apple would send back the HTML file for https://apple.com. What is HTML? You will learn that in Chapter 2 :)

You don't need to know what each of the lines in the above request means, except the first one — that's the kind of HTTP request that you are sending. There are quite a few possible requests. Here are the most common ones:

  • GET: used to retrieve information
  • POST: used to post/update information (usually sent with some payload, i.e., the data that you want to update)
  • DELETE: used to delete some information
  • OPTIONS: used to retrieve available HTTP methods (for example, not all servers support POST or even GET)

For the purposes of this course you will likely only use GET. If you were to build a complicated server with a database, you would need to support more methods. When you visit a website, your browser always sends a GET request. In fact, you can't conveniently send anything else unless you send it in code (you will learn JavaScript in Chapter 6).

HTTPS is just a secure version of HTTP. Essentially, before sending this HTTP request above, your browser would encrypt it and the server would decrypt it — that way anyone in between (for example, your Internet provider) would not know what you are sending and receiving. How exactly that works is beyond the scope of this class, but trust us when we say some brilliant people created it and it's definitely secure.

DNS

The final important concept for understanding websites is DNS — the Domain Name System. As we mentioned above, each computer connected to the Internet has an IP address, but people are not good at memorizing four arbitrary-looking three-digit numbers, and so the founders of the Internet created DNS — a way to map easily memorizable domain names like apple.com to less memorizable addresses like 17.253.144.10 (which is the real address behind that domain, at least for my computer). There are many ways to configure DNS when you get your own domain, but here are the two most relevant records:

  • A: maps an IP address to a domain name
  • CNAME: stores a canonical name for your domain (in other words, an alias)

Chapter 1.1.2 - What is a browser?


A browser is a kind of software that allows you to very conveniently navigate the web. Here's how it does it:

  • When you go to some website, your browser contacts the DNS server to learn what is the real IP address for its domain name (recall our Apple example in the DNS section).
  • Once your browser knows the IP address, it sends a GET request to that IP address describing what it wants to retrieve. For example, when you visited this page, your browser sent a GET request to the IP address of the server that's hosting this page and asked to retrieve the HTML file chapter-1.2.html.
  • Once the browser receives the requested HTML file back, it starts to analyze it and build a DOM-tree (more on that in Chapter 2). For now, think of that as an internal structure of the website. If a file that you requested is not HTML, then other methods of displaying are used (for example, a PDF file would be displayed with a PDF reader). If your browser can't display a file, it prompts to download it to your hard drive. Every website you visit uses HTML.
  • Once the browser has created the DOM-tree of the HTML page, it starts to render it. Meanwhile, if the page contains images, your browser sends additional GET requests to retrieve those files so that it can display them.

All of that happens within seconds, if not less!

One important thing that you should know is that, by default, if you don't specify a file and only specify the directory that you want to retrieve when going to a website, your browser will send a request for index.html. For example, when you visit https://www.apple.com/mac/, you browser actually sends a request for https://www.apple.com/mac/index.html, retrieves index.html, and renders it. Click both links to confirm that they lead to the same destination!

By now you may have noticed that the website addresses after the domain name look like addresses on your computer's filesystem. It's because they are! Essentially, a server is hosting a directory and you can access its files remotely. (Some website architectures are more complicated and actually generate files when you request them, but you don't need to worry about that.)

Exercise

Press Cmd+Shift+C (or F12) to go to Firefox's console, click the "Network" tab, then visit any website. Look at how many HTTP requests are needed just to display one website! Note also that the first request is a request for an .html file.

Chapter 1.1.3 - Command line tools


Back in the days, computers didn't have convenient user interfaces, and everything was done using the command line. Despite the advent of operating systems with accessible user interfaces, the command line is still a useful part of every system. In this section, you will learn how to use it.

Families of operating systems

There are two main families of operating systems systems: Unix and DOS. DOS was developed by Microsoft and it is used in Windows operating systems. Unix is derived from AT&T Unix, developed in 1970, and it is used in both Linux and Mac OS. The command line tools and syntax differs between these two systems, but we will use Unix throughout this course.

Current working directory

When you use a command line, you are located within a directory from which you can access other files and directories. For example, if you open the Terminal (command line) in Mac OS, by default the current working directory will be set as your home directory located in /Users/$USER (where $USER is your username). From there, you can access all files and directories within that folder with their respective names.

Executables

The command line allows to run executables (or, simply, programs). In order to do so, simply type the name of the executable you wish to run and pass the required arguments (parameters), if needed. For example, in Unix, cd is an executable that allow to change directories. If you are in your home folder on Mac OS, you can navigate to "Documents" by typing cd Documents. Here are other useful executables:

  • ls: lists the contents of the current working directory. If a parameter is passed, it lists the contents of that directory.
  • pwd: prints the path to the current working directory.
  • rm: removes the given file (for example, rm a.txt).
  • mkdir: creates a new directory (for example, mkdir new-directory).

If you want to pass a parameter with spaces, wrap it inside quotation marks. For example, if you want to create a directory called "New Directory", type mkdir "New Directory".

There are many other executable that come with Linux/Mac OS and executables that you can install yourself, but these are the most common ones that you need to remember.

Flags

Executables can also accept flags to change their behavior. Flags are similar to arguments but are prefixed with either - or --. For example, ls accepts an -a flag which would force ls to print hidden files within the directory (hidden files are simply files that are not visible by default and whose names start with .). rm accepts -r flag which forces rm to traverse the files within the given directory (and their files) and delete them too. For example, if you were to run rm -r /Users/$USER/Desktop, you would erase all desktop contents! (You should probably not try it.)

Absolute vs relative paths

An absolute path to a file or a directory is a path that includes all folders starting from the root directory /. For example, the absolute path to Desktop on Mac OS is /Users/$USER/Desktop.

A relative path to a file or a directory is a path to it from your current working directory. For example, if your current working directory is /Users/$USER, the relative path to Desktop is Desktop.

Each Unix directory also contains a link to itself and to its parent directory:

  • The alias for the parent directory is ... A parent directory is a directory that contains another directory, which is its child. For example, /Users is a parent directory for $USER, which is its child directory. If your current working directory is /Users/$USER and you run cd .., your current working directory will change to /Users.
  • The alias for the current directory is .. If your current working directory is /Users/$USER and you run cd ., your current working directory will remain the same.

Finally, there is another useful alias for the home directory: ~.

PATH

Usually, you need to give the path to an executable that you wish to run. For example, if you create an executable called my-executable and place it within your current working directory, you would need to run ./my-executable (note that you need to include the alias to the current working directory). However, it would be tedious to know where each executable is located within your filesystem, and so Unix provides a global variable called PATH that contains folders with executables that need to be accessed globally. When you type ls, your operating system actually goes through each folder in PATH and checks if it contains that executable. It then finds the directory with the absolute path of /bin and runs ls within it. If you want to know where a global executable is located, run where followed by the executable's name. For example, where ls outputs /bin/ls.

Chapter 1.1.4 - Working with code editors


Practically speaking, you can write websites in any text editor. However, there are specialized code editors that help you write clean, formatted, error-free code—sometimes they even write code for you! There are many choices out there, from IDEs (Integrated Development Environments) like WebStorm to universal code editors like Sublime Text, Atom, and Visual Studio Code. Since we want you to pick up a tool that you can use no matter what project you are working on, we will stick to universal code editors. Specifically, we are going to use Visual Studio Code, as its extensions library has thousands of ways to improve and speed up development. We are not going to do a better job describing what Visual Studio Code is than Microsoft themselves, so read more about it on their official website.

Homework


The homework for this chapter will make you install, configure, and play around with Visual Studio Code. This will be our main development tool throughout the course, so make sure to carefully follow the instructions below.

Part 1: Installation

Navigate to https://code.visualstudio.com/, download the appropriate version for your platform (the homepage should automatically detect your system), and install it.

Part 2: Extensions

Since Visual Studio Code is just a code editor, it allows developers to work in any programming language. However, it also allows them to build extensions for their favorite languages which they can then share with the world. We will use a few such extensions to improve our experience of building websites. Since we haven't covered any programming so far, you don't have to know what these extensions do yet — just make sure to install all of them. To do so, take a look at this guide: https://code.visualstudio.com/docs/editor/extension-marketplace. Once you have learned how to install and uninstall extensions, search and install the following ones:

  • HTML Snippets (by Mohamed Abusaid): abusaidm.html-snippets.
  • HTML Preview (by Thomas Haakon Townsend): tht13.html-preview-vscode.
  • HTML CSS Support (by ecmel): ecmel.vscode-html-css.
  • Tailwind CSS IntelliSense (by Brad Cornes): bradlc.vscode-tailwindcss.
  • Headwind (by Ryan Heybourn): heybourn.headwind.

Feel free to install other extensions if you find something that you like!

Part 3: Configuration

Click Cmd+Shift+P or Ctrl+Shift+P and go to Preferences: Open Settings (UI) (you may type it). In the Commonly Used tab, set "Tab Size" to 2. Now go to Text Editor → Formatting and enable "Format on Save".

Part 4: Play Around

Now that you have set up Visual Studio Code, try to experiment! Create a new project and create a index.html file. Now, paste the following code:

<!DOCTYPE html>
<html>
<head>
<title>Experiment</title>
</head>
<body>
<p>Hello from Oval!</p>
</body>
</html>

If you've set everything up properly, when you save the file (Cmd+S or Ctrl+S), it will be formatted and turn into

<!DOCTYPE html>
<html>
  <head>
    <title>Experiment</title>
  </head>
  <body>
    <p>Hello from Oval!</p>
  </body>
</html>

Now, in the Explorer tab on the left of Visual Studio Code (the top one), right-click on index.html and click "Reveal in Finder" (or "Reveal in File Explorer" on Windows). This will open the directory containing your project outside of VSCode. Run index.html and you will see a browser tab containing a website that just says "Hello from Oval!". Congratulations, you have just written your first website! Don't worry about what the code does — we will cover it in the following lectures.

Chapter 1.2 - Introduction to Git. Introduction to HTML.


In this chapter, you will learn how to use Git—a free and open source distributed version control system designed to work on small or large projects in collaboration with other programmers. It can be used locally on your computer to keep track of changes you make to your project, or online with Github to collaborate with people across multiple networks. After learning about Git, you will learn the basics of HTML and set up your own project on Github.

GitHub is the industry standard for showcasing your programming portfolio. Technology companies and universities like to see what you have been working on and GitHub provides an easy way to showcase that.

By the end of this course, you will be hosting a fully-customized portfolio site, built from scratch, on GitHub Pages—a static website hosting service that takes HTML, CSS, and JavaScript files straight from a repository on GitHub, optionally runs the files through a build process, and publishes a website.

Install Git (Windows only)

Git is installed on Linux and macOS computers by default. However, Windows does not include it. If you are using a Windows machine, follow the instructions below to install Git onto your computer.

  1. Open the Git website.
  2. Click the Download link to download Git. The download should automatically start.
  3. Once downloaded, start the installation from the browser or the download folder.
  4. In the Select Components window, leave all default options checked and check any other additional components you want installed.
  5. Next, in the Choosing the default editor, select VS Code.
  6. Next, in the Adjusting your PATH environment, we recommend keeping the default Use Git from the command line and also from 3rd-party software as shown below. This option allows you to use Git from either Git Bash or the Windows Command Prompt.
  7. Next, we recommend leaving the default selected as Use OpenSSH.
  8. Next, in Choosing HTTPS transport backend, leave the default Use the OpenSSL library selected.
  9. In the Configuring the line ending conversions, select Checkout Windows-style, commit Unix-style line endings unless you need other line endings for your work.
  10. In the Configuring the terminal emulator to use with Git Bash window, select Use MinTTY (the default terminal of MSYS2).
  11. Click the Install button

If you are on Windows, use Git Bash (a Unix-based shell) throughout the course. In our experience, it is a lot more beneficial to learn Unix shell than Windows, and so we will not be including Windows-based examples.

What is HTML?

HTML stands for Hyper Text Markup Language. This is the language that is used across all of the websites on the internet to display information. HTML files are just plain text files (with .html extension) that consist of a series of elements which tell the browser how to display the content you type. Since HTML is just a markup language, there are no special programs that you need other than VSCode!

Chapter 1.2.1 - Understanding Version Control, Repositories


Version Control

Version control is a system that records changes to a file or set of files over time so that you can recall specific versions later. Git essentially takes snapshots of your code—it records the entire state of your project at different moments in time so that you may revert to those snapshots if needed.

Git Repository

A repository is simply a directory that somebody has initialized with Git.

In order to initialize Git inside a directory, type the following command into your command line (remember to use Git Bash if you are on Windows):

git init

This command creates a .git subfolder in your directory where Git keeps track of your changes. By default, files and directories that starts with a period . are not visible in Finder or File Explorer. To see hidden files, enable this setting in your operating system or run ls -a.

If you ever clone (copy) someone else's repository, it should already contain .git/ inside and so you don't have to run git init.

In short, a repository (or just "repo") is a set of files and subfolders that Git tracks for you.

Chapter 1.2.2 - Configuring Git


To be able to use GitHub and Git on your machine, you have to create an account on GitHub.

Once you have your account set up, open up your Terminal application and tell Git your name and email:

git config --global user.name "Your Full Name"
git config --global user.email your_email@email.com

For example, Jon Doe, whose email is JonDoe@outlook.com would type:

git config --global user.name "Jon Doe"
git config --global user.email "JonDoe@outlook.com"

Chapter 1.2.3 - Creating a Git Project


Let's create a new directory for our sample Git project.

In Mac or Linux, open Terminal and type the following commands (you don't have to include anything after #—they are just comments and don't affect anything):

cd # takes you to home directory
mkdir test1 # creates subfolder called 'test1'
cd test1 # takes you to 'test1' subfolder

Now, put the directory under Git revision control:

git init

You have successfully created your first Git repo!

Creating a file and making changes

Now, let's add a file, make some changes, and commit them to Git.

Type the following command into your Terminal to create a text file that contains 'This is some text' inside:

echo "This is some text" > myfile.txt

Let's see what git thinks about what we're doing:

git status

The git status command reports that myfile.txt is 'Untracked'. Let's allow git to track our file by adding it to the staging area.

git add myfile.txt

Run git status again. It now reports that my file.txt is "a new file to be committed." Let's commit it and type a useful comment:

git commit -m "Added myfile.txt program."

We have successfully put our first coding project under git revision control!

To recap use

  • git status to learn about the status of your project (that is, which files were created/modified/deleted)
  • git add {filename} in order to track a file (you have to do this every time you modify it). If you don't want to list each modified file manually, simply type git add . (the period is a wildcard for all files).
  • git commit -m "{message}" in order to create a new "checkpoint" for your project which will include the entire current state of the repository.

Pushing Our Sample Project to GitHub

When programmers talk about "pushing" projects to GitHub, they essentially mean that they are synchronizing their changes with a repository hosted in the cloud where other people can see the code they have written. We will push our sample project to GitHub:

  1. Create a new repository on GitHub. To avoid errors, do not initialize the new repository with README, license, or gitignore files. You can add these files after your project has been pushed to GitHub.

  2. At the top of your GitHub repository's Quick Setup page, click to copy the remote repository URL. Copy remote repository URL field

  3. In Terminal or Command Prompt, add the URL for the remote repository where your local repository will be pushed.

$ git remote add origin  <REMOTE_URL> 
# Sets the new remote
$ git remote -v
# Verifies the new remote URL
  1. Push the changes in your local repository to GitHub.
$ git push -u origin main
# Pushes the changes in your local repository up to the remote repository you specified as the origin

From here on, you will need to type only git push whenever you want to synchronize your Github repository with your local repository.

You have now succesfully pushed your project to Github!

Chapter 1.2.4 - HTML Syntax


An HTML document is a text file that holds the layout of a website. To do so, it has a set of elements that it can use (buttons, generic containers, text containers, etc). Each element has a start tag, content, and a closing tag. The start tag starts with < and ends with >. The end tag starts with < and ends with />. Everything that's between the start and the end tag is the content of the element. For example, here is how a button would look like: <button>Press me!</button>

Some elements are so-called self-closing tags. They don't have a closing tag, but their starting tag ends with />. There are not many of them, but, for example, <img> is a self-closing tag, and an image would like: <img src="img/ostrich.png" alt="Ostrich Picture">

As you may have noted in the example above, elements may also have attributes—meta parameters. The most popular attributes are id, used to identify unique elements, and class, features that are shared among many elements. Don't worry about class yet—we will get back to it in the CSS section. In the example above, we used src and alt, which are unique to <img />: src contains a link to the image file, and alt contains a description of the image for accessibility purposes.

Elements provide extra information about the data in the document. They can stand on their own, for example, to mark the place where a picture should appear in the page, or they can contain text and other elements, for example when they mark the start and end of a paragraph.

Every HTML document has the following structure:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>

    <body></body>
</html>

The rest is up to you to fill in! For example, here is a sample webpage source code:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>A quote</title>
    </head>

    <body>
        <h1>A quote</h1>

        <blockquote>
            <p>The connection between the language in which we think/program and the
            problems and solutions we can imagine is very close.  For this reason
            restricting language features with the intent of eliminating programmer
            errors is at best dangerous.</p>

            <p>-- Bjarne Stroustrup</p>
        </blockquote>

        <p>Mr. Stroustrup is the inventor of the C++ programming language, but
        quite an insightful person nevertheless.</p>

        <p>Also, here is a picture of an ostrich:</p>

        <p><img src="img/ostrich.png" alt="ostrich picture"></p>
        
    </body>
</html>

You can see what this website looks like by clicking here.

Elements that contain text or other pages are opened with <tagname> and closed with </tagname>. The html element always contains two children: head and body. The first holds information on the document and the second contains the document itself.

Here is a small list of tags to get you started:

tagfunction
h1Stands for "heading 1". When characters are wrapped in this tag, they become a heading. Other variations of the tag include h2, h3, ..., h6 (the higher the number, the smaller the header).
pStands for "paragraph". When characters are wrapped inside it, they become a new paragraph.
imgStands for "image". This tag does not contain displayable characters inside of it: it contains attributes such as src="img/ostrich.png" and alt="ostrich picture". It is also a self-closing tag.
divStands for "content division". This tag is a generic container for other tags and does not have any impact without applied CSS styles.

To learn more about HTML and see a comprehensive list of available HTML tags, visit the HTML Documentation from Mozilla Foundation.

Chapter 1.2.5


Homework

Now that you know how to create a Git repository and know the basics of HTML, let's get you started with creating the first part of your website!

Create Your Website Repositorry

For the first step, you will want to create the folder from which you will be editing and pushing your changes to GitHub.

First, navigate to a directory on your file system where you want to host the website project. Then, create a directory and some folders that we will use in the future. To do so, open the command line and paste the following (don't forget to use Git Bash if you're on Windows):

mkdir personal-website
cd personal-website
mkdir assets
cd assets
mkdir img
mkdir css
mkdir js
cd ..

Finally, initialize your repo:

git init

Create an HTML Document

Open Visual Studio Code and in the Top Left of your screen, select File > Open and select the folder you just created, personal-website.

Once you have successfully opened your folder, create a new file by selecting File > New File. Save it selecting File > Save and call it index.html. This will be the landing page that will come up first when people go to your website.

You can also type touch index.html to create this file in the command line).

Copy the code below onto your index.html file. You may modify it as much as you'd like and we will be able to stylize it further in the future using CSS, JavaScript, and more advanced HTML tags!

<!doctype html>

<html lang="en">
<head>
  <meta charset="utf-8">

  <title>My Portfolio Site</title>
  <meta name="description" content="This is my own website!">
  <meta name="author" content="YOURNAME">

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

<body>
  <script src="js/main.js"></script>
</body>
</html>

Save the file by selecting File > Save.

Push Your Repo

Navigate back to Terminal (or Command Prompt on windows) and add all of the changes you have made to the repo so far by typing:

git add .

Check that there are no "Untracked" documents by typing

git status

If all of the documents are ready to be committed and you have finalized all of your changes, commit your project.

git commit -m "Initialized the repository."

Create a new repository on GitHub following the instructions in Chapter 1.2.3 and push your changes to the cloud. If you can see your files in the site for your repository online, you have done this succesfully! You are ready to start modifying your site.

Chapter 1.3 - Introduction to CSS and Advanced HTML.


In this chapter, you will learn about CSS, short for Cascading Style Sheets—a style sheet language designed to modify the appearance of HTML files. While HTML is used to structure how content appears on the website, CSS allows to style and organize the content so it looks visually appealing. CSS is the second building block of every website—once you know it, you will be capable of building any static website that doesn't require interactivity.

CSS is used to apply styles to specific elements in the HTML page that links to it (we will learn how to link HTML with CSS in the homework portion of this chapter). In order to write in CSS, you need to create a file that ends in .css. Once there, the syntax for each style is as follows:

selector {
  property1: value1;
  property2: value2;
  ...
}

We will discuss what selectors, properties, and values are in the following sections of this chapter.

Chapter 1.3.1 - Selectors


Selectors

As elements are added to a web page, they may be styled using CSS. A selector designates exactly which element or elements within our HTML to target and apply styles (such as color, size, and position) to. Selectors may include a combination of different qualifiers to select unique elements, all depending on how specific we wish to be. For example, we may want to select every paragraph on a page, or we may want to select only one specific paragraph on a page. Selectors generally target an attribute value, such as an id or class value, or target the type of element, such as <h1> or <p>. In CSS, selectors are followed by curly brackets, { }, which hold the styling that is applied to the selected element. In the following example, the selector 'p' is used to tell CSS to apply specific styles to the <p> elements.

To code and upkeep professional websites, it is important that you know how to properly classify different elements and apply styles: selectors play a crucial role in this.

Type Selectors

Type selectors target elements by their element type. For example, if we wish to target all division elements, <div>, we would use a type selector of div. The following two code snippets showcase the CSS selection as well as the elements that are selected in the HTML file.

CSS

div { ... }

HTML

<div>...</div>
<div>...</div>

Class Selectors

Class selectors allow us to select an element based on the element’s class attribute value. Class selectors are a little more specific than type selectors, as they select a particular group of elements rather than all elements of one type. Class selectors allow us to apply the same styles to different elements at once by using the same class attribute value across multiple elements. >In CSS, classes are denoted by a leading period, ., followed by class attribute value. In the next example, the class sector selects any elements containing the class attribute value of awesome including both division and paragraph elements.

CSS

.awesome {...}

HTML

<div class="awesome">...</div>
<p class="awesome">...</p>

ID Selectors

ID selectors are even more precise than class selectors, as they target only one unique element at a time. Just as class selectors use an element’s class attribute value as the selector, ID selectors use an element’s id attribute value as a selector.

id attribute values can only be used once per page. Reserve them for significant elements!

In CSS, ID selectors are denoted by a leading has sign, #, followed by the id attribute value. In the following example, the ID selector will only select the element containing the id attribute value of oval.

CSS

#oval {...}

HTML

<div id="oval">...</div>

In the previous chapter we talked about HTML attributes like id and class but omitted what they were used for. Now you know that they're mostly used to link CSS to them (among other reasons)!

Chapter 1.3.2 - The Cascade and Combining Selectors


The Cascade

Within CSS, all styles cascade from the top of a style sheet to the bottom, allowing different styles to be added or overwritten as the style sheet progresses.

For example, say we select all paragraph elements at the top of our style sheet and set their background color to orange and their font size to 24 pixels. Then towards the bottom of our style sheet, we select all paragraph elements again and set their background color to green, as seen here.

p {
	background: orange;
	font-size: 24px;
}
p {
	background: green;
}

Because the paragraph selector that sets the background color to green comes after the paragraph selector that sets the background color to orange, it will take precedence in the cascade. All of the paragraphs will appear with a green background. The font size will remain 24 pixels because the second paragraph selector didn’t identify a new font size. >The cascade also works with properties inside individual selectors. In the following example, the green property takes precedence over the orange.

p {
	background: orange;
	background: green;
}

If you want to make sure that some value won't be overwritten by another value, use !important key after the value (i.e., background: orange !important).

Selector Specificity Weight

Every selector in CSS has a specificity weight. A selector’s specificity weight, along with its placement in the cascade, identifies how its styles will be rendered.

You've learned about three types of selectors: type, class, and ID. A selector's specificity is calculated using three columns. They are outlined below as follows:

selectorweight
type0-0-1
class0-1-0
ID1-0-0

The first column counts ID selectors, the second column counts class selectors, and the third column counts type selectors. The ID selector has a higher specificity weight than the class selector, and the class selector has a higher specificity weight than the type selector. The higher the specificity weight of a selector, the more superiority the selector is given when a styling conflict occurs.

For example, if a paragraph element is selected using a type selector in one place and an ID selector in another, the ID selector will take precedence over the type selector regardless of where the ID selector appears in the cascade.

HTML

<p id="food">...</p>

CSS

#food {
	background: green;
}
p {
	background: orange;
}

In the above example we have a paragraph element with an ID attribute value of food. Within our CSS, that paragraph is being selected by two different kinds of selectors: one type selector and one ID selector. Although the type selector comes after the ID selector in the cascade, the ID selector takes precedence over the type selector because it has a higher specificity weight; consequently the paragraph will appear with a green background.


Combining Selectors

By combining selectors we can be more specific about which element or group of elements we’d like to select. For example, say we want to select all paragraph elements that reside within an element with a class attribute value of hotdog and set their background color to brown. However, if one of those paragraphs happens to have the class attribute value of mustard, we want to set its background color to yellow.

HTML

<div class="hotdog">
	<p>...</p>
	<p>...</p>
	<p class="mustard">...</p>
</div>

CSS

.hotdog p {
	background: brown;
}
.hotdog p.mustard {
	background: yellow;
}

When selectors are combined they should be read from right to left. The selector farthest to the right, directly before the opening curly bracket, is known as the key selector. The key selector identifies exactly which element the styles will be applied to. Any selector to the left of the key selector will serve as a prequalifier.


Spaces Within Selectors

Since there isn’t a space between the paragraph type selector and the mustard class selector that means the selector will only select paragraph elements with the class of mustard. If the paragraph type selector was removed, and the mustard class selector had spaces on both sides of it, it would select any element with the class of mustard, not just paragraphs. The best practice is to not prefix a class selector with a type selector. Generally we want to select any element with a given class, not just one type of element. And following this best practice, our new combined selector would be better as .hotdog .mustard.


Reading the combined selector from right to left, it is targeting paragraphs with a class attribute value of mustard that reside within an element with the class attribute value of hotdog.

Specificity Within Combined Selectors

When selectors are combined, so are the specificity weights of the individual selectors. These combined specificity weights can be calculated by counting each different type of selector within a combined selector >Looking at our combined selectors from before, the first selector, .hotdog p, had both a class selector and a type selector. Knowing that the point value of a class selector is 0-1-0 and the point value of a type selector is 0-0-1, the total combined point value would be 0-1-1, found by adding up each kind of selector.

In general we want to always keep an eye on the specificity weights of our selectors. The higher our specificity weights rise, the more likely our cascade is to break.

Layering Styles with Multiple Classes

To keep the specificity weights of our selectors low we should consider being as modular as possible by sharing similar styles from element to element . We layer on different styles by using multiple classes.

Elements within HTML can have more than one class attribute value so long as each value is space separated. With that, we can place certain styles on all elements of one sort while placing other styles only on specific elements of that sort.

HTML

<a class="btn color-danger">....</a>

<a class="btn colorr-success">...</a>

CSS

.btn {
	font-size: 16px;
}
.color-danger {
	background: red;
}
.color-success {
	background: green;
}

In the above example, we want our buttons to have a font size of 16 pixels; however, we want the background color of our buttons to vary depending on where the buttons are used. We create a few classes and layer them on an element as necessary.

Chapter 1.3.3 - Common CSS Property Values


Properties

Once an element is selected, a property determines the styles that will be applied to that element. Property names fall after a selector, within the curly brackets, {}, and immediately preceding a colon, :. There are numerous properties we can use, such as background, color, font-size, height, and width, and new properties are often added. In the following code, we are defining the color and font-size properties to be applied to all <p> elements.

p {
	color: ...;
	font-size: ...;
}

Values

We can determine the behavior of a property with a value. Values can be identified as the text between he color, :, and semicolon, ;. In the example below, we are selecting all <p> elements and setting the value of the color property to be orange and the value of the font-size property to be 16 pixels.

p {
	color: orange;
	font-size: 16px;
}

Note: it is common practice to indent the property and value pairs within the curly brackets (usually with 2 spaces, though 4 spaces are used in these examples).

Common CSS Property Values

There are a few ways to specify color and length property values. Those are outlined below respectively.

Colors

CSS defines color values on an sRGB (standard red, green, and blue) color space. We can form colors by combing red, green and blue color channels together at different levels. There are four ways to represent colors within CSS: keywords, hexadecimal notation, RGB and HSL values.

Keyword Colors

Keyword color values are names (such as red, green, or blue) that map to a given color. Most common colors have keyword names. You can find all of these keywords here.

.btn {
	background: yellow;
}
.task {
	background: red;
}

Here we apply the property value yellow to the class btn and the property value red to the class task.

Hexadecimal Colors

A hexadecimal color value begins with a # (pound or hash) followed by a six-character figure. The figures use the numbers 0 through 9 and the letters a through f. Since one hexadecimal digit can take 16 different values (0-9 and a-f), two of them combined can take 16*16=256 values. Each such pair defines red, green, and blue (RGB) color channels. For reasons we don't have to get into, RGB can show most of the visible colors, and it is used in web development and many other applications to define colors.

The color white, for example, is made by mixing each of the three primary colors at their full intensity, resulting in the Hex color code of #FFFFFF.

#FFFFFF

Black, the absence of any color on a screen display, is the complete opposite, with each color displayed at their lowest possible intensity and a Hex color code of #000000.

#000000

The color red can be made by using only the red channel and leaving blue and green channels at 0.

#FF0000

Understanding the basics of Hex color code notation we can create grayscale colors very easily, since they consist of equal intensities of each color:

#454545

#999999

You can find a full list of common hexademical color mappings here.

There are millions of hexadecimal colors, over 16.7 million to be exact. There are 16 options for every character in a hexadecimal color, 0 through 9 and A through F. With the characters grouped in pairs, there are 256 color options per pair (16 multiplied by 16, or 16 squared). And with three groups of 256 color options we have a total of over 16.7 million colors (256 multiplied by 256 multiplied by 256, or 256 cubed).

.btn {
	background: #FFFF00;
}
.task {
	background: #FF0000;
}

We can recreate the yellow and red colors from before by using their hexadecimal values.

RGB & RGBa Colors

RGB color values are stated using the rgb() function, which stands for red, green, and blue. The function accepts three comma-separated values, each of which is an integer from 0 to 255. A value of 0 would be pure black; a value of 255 would be pure white.

The first value within the rgb() function represents the red channel, the second value represents the green channel, and the third value represents the blue channel.

.btn {
	background: rgb(255, 255, 0);
}
.task {
	background: rgb(255, 0, 0);
}

We can, once again, recreate the yellow and red colors from before by using their rgb() combination.

RGB color values may also include an alpha, or transparency, channel by using the rgba() function. The rgba() function requires a fourth value, which must be a number between 0 and 1, including decimals. A value of 0 creates a fully transparent color, meaning it would be invisible, and a value of 1 creates a fully opaque color. Any decimal value in between 0 and 1 would create a semi-transparent color.

.btn {
	background: rgba(255, 255, 0, .25);
}
.task {
	background: rgba(255, 0, 0, .1);
}

We can make our yellow color 25% opaque by setting the final parameter to .25 and, similarly, we can make our red color 100% opaque by setting its last parameter to 1.

HSL & HSLa Colors

HSL color values are stated using the hsl() function, which stands for hue, saturation, and lightness. Within the parentheses, the function accepts three comma-separated values, much like rgb().

The first value, the hue, is a unitless number from 0 to 360. The numbers 0 through 360 represent the color wheel, and the value identifies the degree of a color on the color wheel.

The second and third values, the saturation and lightness, are percentage values from 0 to 100%. The saturation value identifies how saturated with color the hue is, with 0 being grayscale and 100% being fully saturated. The lightness identifies how dark or light the hue value is, with 0 being completely black and 100% being completely white.

.btn {
	background: hsl(60, 100%, 50%);
}
.task {
	background: hsl(0, 100%, 50%);
}

Using hsl(), we can recreate our previous colors by setting the hue to 60 for yellow and 0 for red.

HSL color values, like RGBa, may also include an alpha, or transparency, channel with the use of the hsla() function. The behavior of the alpha channel is just like that of the rgba() function. A fourth value between 0 and 1, including decimals, must be added to the function to identify the degree of opacity.

.btn {
	background: hsl(60, 100%, 50%, .25);
}
.task {
	background: hsl(0, 100%, 50%, 1);
}

We can set the opacity of our yellow color to 25% by setting the last parameter to .25 and the opacity of our red color to 100% by setting the last parameter to 1.

Hexadecimal color values are the most widely used and supported amongst different browsers.


Lengths

We use two different types of lengths, absolute and relative, to set the size and shape of our elements in CSS.

Absolute Lengths

Absolute lengths represent physical measurements such as inches, centimeters, pixels and millimeters. The most popular absolute unit is the pixel, represented by the px unit notation.

The pixel is equal to 1/96th of an inch; thus there are 96 pixels in an inch. The exact measurement of a pixel, however, may vary slightly between high-density and low-density viewing devices.

p {
	font-size: 14px;
}

We can use the pixel to set the font size of a p tag to 14px.

Pixels don't adapt too well from device to device but they are still a ubiquitous unit used in styling.

Relative Lengths

Relative lengths, by definition, are not fixed and thus they rely on the length of some other measurement.

Percentages

Percentage lengths are defined in relation to the length of another object.

.col {
	width: 50%;
}

We can set the width of an element in the col class to be 50% of the parent element's width.

Em

The em unit is represented by the em unit notation, and its length is calculated based on an element's font size.

A single em unit is equivalent to an element’s font size. So, for example, if an element has a font size of 14 pixels and a width set to 5em, the width would equal 70 pixels (14 pixels multiplied by 5).

.banner {
	font-size: 14px;
	width: 5em;
}

When a font size is not explicitly stated, the em unit will be relative to the font size of the closest parent element with a stated font size. The em unit is often used for styling text, including font sizes, as well as spacing around text, including margins and paddings.

Rem

The rem unit is represented by the rem unit notation, and it is similar to em but it's length is calculated based on the website's font size. For example, while 1 em can be different from element to element (depending on its size and its parent elements' sizes), 1 rem will remain the same across the page. We will be mostly using rem since it is universal and allows for consistent design across different screens. It is also the unit used in Tailwind CSS, but more on that in Chapter 4.2.

Chapter 1.3.4 - Box Model


Box Model

In HTML, elements are classified either block- or inline-level. This has to do with how the elements are displayed.

type of leveldescription
block
  • begin on new line
  • stack on top of the other
  • occupy any available width
  • most commonly used for larger pieces of content such as paragraphs
in-line
  • do not begin on new line
  • fall into normal flow of document
  • lining up one after the other
  • only maintain the width of their content
  • cannot wrap block
  • level elements
  • most commonly used with smaller pieces of content, such as a few words

Display

You can change how an element is displayed through the display property. Every element has a default display property but it can be overwritten to be block, inline, inline-block, and none.

p {
	display:block;
}

A value of block will make that element a block-level element.

p {
	display: inline;
}

A value of inline will make that element an inline-level element.

p {
	display: inline-block;
}

With the inline-block value, the element behaves as a block-level element, accepting all box model properties; however, the element will be displayed in line with other elements, and it will not begin on a new line by default.

Paragraph one.

Paragraph two.

Paragraph three.

Three paragraph elements displayed inline, sitting right next to the other in a horizontal line.

div {
	display: none;
}

An element displayed as none will not appear on the page.


What is the Box Model?

Every element on a page is a essentially rectangular with a width, height, padding, borders, and margins.

You can see in the above example that all elements are rectangular, regardless of their shape.

Working with the Box Model

Every element has a set of properties which determine its size.

propertydescription
displaycould determine width and height
width and heightexplicit length of width and height values
padding and borderexpand the dimensions of the box outward from the element's width and height
marginany margins specified follow the border

Each part of the box model corresponds to a CSS property.

div {
	border: 6px solid #9495599;
	height: 100px;
	margin: 20px;
	padding: 20px;
	width: 400px;
}

We can calculate the width of the hypothetical element above with the following formula: margin-right + border-right + padding-right + width + padding-left + border-left + margin_left. The total height of an element can be calculated using the following formula: margin-top + border-top + padding-top + height + padding-bottom + border-bottom + margin-bottom.

  • Width: 492px = 20px + 6px + 20px + 400px + 20px + 6px + 20px
  • Height: 192px = 20px + 6px + 20px + 100px + 20px + 6px + 20px

The box model for the previous example, visualized.

Each property has a different way of interacting with the content surrounding it.

propertydescription
width
  • block elements have a default width of 100%, consuming entire horizontal space
  • inline and inline-block elements expand and contract horizontally to accommodate content
  • only relevant to non-inline elements
height
  • default height of an element is determined by its content
  • an element expands and contracts vertically as necessary to accommodate its content
  • only relevant to non-inline elements
margin
  • allows us to set the amount of space that surrounds an element
  • margins are transparent fall outside of any border
  • can be used to help position elements in a particular place a page
  • top and bottom margins are not accepted by inline-level elements
padding
  • similar to margin property
  • falls inside of an element's border
  • used to provide spacing directly within an element
  • works vertically on inline-level elements, unlike the the margin property
  • vertical padding may blend into the line above or below the given element

    Shorthand and Longhand

    The margin and padding properties come in both longhand and shorthand from. When using the shorthand margin property to set the same value for all four sides of an element, we specify one value:

    div {
    	margin: 20px;
    }
    

    To set one value for the top and bottom and another for the left and right sides, specify two values: top and bottom first, then left and right.

    div {
    	margin: 10px 20px;
    }
    

    You can specify unique values for all four sides by specifying them in order of top, right, bottom, and left, moving clockwise.

    div {
    	margin: 10px 20px 0 15px;
    }
    

    Any of these options are considered shorthand. Longhand involves explicitly stating the property and side you would like to modify.

    div {
    	margin-top: 10px;
    	padding-left: 6px;
    }
    

    In the above example, we set our margin-top property value to be 10px and our padding-left property to be 6px;

    It is best to use longhand notation when we wish to identify only one margin or padding value. This keeps our code explicit and helps us avoid any confusion.

    Border

    The border property requires three values: width, style and color. Shorthand values for the border property are stated in that order--width, style, color. In longhand, we break these three values into the border-width, border-style and border-color properties. They are useful for overwriting a single property value.

    The most common border styles are solid, double, dashed, dotted, and none.

    Just like the margin and padding properties, border has highly specific longhand sub properties. These highly specific longhand border properties include a series of hyphen-separated words starting with the border base, followed by the selected side—top, right, bottom, or left—and then width, style, or color, depending on the desired property.

    div {
    	border-bottom: 6px solid #949599;
    }
    

    In the above example, we created a border solely on the bottom side of the div element.

    div {
    	border-bottom-width: 12px;
    }
    

    Styles for individual border sides may be controlled at a fine level. In the above code, we change the width of the bottom border to 12px.

    To round the corners of border, we use the border-radius property. This property accepts length units, including percentages and pixels, that identify the radius by which the corners of an element to be rounded.

    Similarly to the margin and padding shorthand notation, we can specify the radius of all corners equally by giving one value, the radius of top/bottom and right/left with two, and the radius of individual corners with four values, going in a clockwise direction.

    div {
    	border-radius: 5px 0 15px 20px;
    }
    

    In the above example, we set the radius of the top-left, top-right, bottom-right, bottom-left corner to 5px, 0, 15px, and 20px respectively.

    You may even set the individual border-radius of a corner usingborder- followed by a specific corner and the word radius.

    div {
    	border-top-right-radius: 5px;
    }
    

    In the above example, we change the radius of the top-right corner to be 5px.


    Box Sizing

    We have discussed the the additive nature of the box model where width, padding and border contribute to the overall width of an element. CSS3 introuced the box-sizing property which allows us to change how the box model works and in turn how an element's size is calculated. The three primary values it accepts are content-box, padding-box, and border-box.

    Content Box

    The content-box value is the default value.

    Padding Box

    The padding-box value alters the box model by including the padding property values within the width and height of an element. When using the padding-box value, if an element has a width of 400 pixels and a padding of 20 pixels around every side, the actual width will remain 400 pixels. As any padding values increase, the content size within an element shrinks proportionately.

    If we add a border or margin, those values will be added to the width or height properties to calculate the full box size. For example, if we add a border of 10 pixels and a padding of 20 pixels around every side of the element with a width of 400 pixels, the actual full width will become 420 pixels.

    div {
    	box-sizing: padding-box;
    }
    

    Border Box

    The border-box value alters the box model so that any border or padding property values are included within the width and height of an element. When using the border-box value, if an element has a width of 400 pixels, a padding of 20 pixels around every side, and a border of 10 pixels around every side, the actual width will remain 400 pixels.

    If we a margin, those values need to be added to calculate the full box size. >No matter which box-sizing property value is used, any margin values will need to be added to calculate the full size of the element.

    div {
    	box-sizing: border-box;
    }
    

    Generally speaking, the best box-sizing value to use is border-box. The border-box value makes our math much, much easier. If we want an element to be 400 pixels wide, it is, and it will remain 400 pixels wide no matter what padding or border values we add to it.

    box-sizing is not supported in every browser so if you encounter displaying issues, consider this a potential source of error.

    Chapter 1.3.5 - Advanced HTML Formatting


    Advanced HTML Formatting

    In Chapter 1.2.4, you learned about the HTML document and its tag-based syntax. In this chapter, you will explore more advanced HTML tags that will help you format your code for ease of readability and illustration.


    Tags

    There are a few key tags that are incredibly useful to know, let's walk you through them.

    A link or hyperlink is a connection from one web resource to another. Links allow users to move seamlessly from one page to another, on any server anywhere in the world.A link or hyperlink is a connection from one web resource to another. Links allow users to move seamlessly from one page to another, on any server anywhere in the world.

    A link has two ends, called anchors. The link starts at the source anchor and points to the destination anchor, which may be any web resource, for example, an image, an audio or video clip, a PDF file, an HTML document or an element within the document itself, and so on.

    We can specify a link in HTML by using the <a> tag. This could be a word, group of words, or even an image.

    <a href="url">Link text</a>
    

    In the example above, we generated this Link text.

    The href attrilbute specifes the target of the link and its value can be an absolute or relative URL.

    URLExampleDescription
    Relativeimages/smiley.pngincludes every part of the URL format, such as protocol, host name, and path of the document.
    Absolutehttps://oval-webdev.netlify.app/syllabus.htmlare page-relative paths, never include the http:// or https:// prefix.

    You can add a target attribut to your <a> tags to specify to the browser how it should open a linked document.

    targetDescription
    _blankOpens the linked document in a new window or tab.
    _parentOpens the linked document in the parent window.
    _selfOpens the linked document in the same window/tab as the source. This is the default behaviour and can be omitted.
    _topOpens the linked document in the full browser window.
    <a href="https://www.google.com" target="_blank">Google.</a>
    

    The above example generates this link: Google.

    Create Bookmark Anchors

    You can create bookmark anchors to allow users to jump to specific sections of a web page. These are useful for very long web pages.

    This is a two step process:

    1. Add the id attribute on the element where you want to jump.
    2. Use the id attribute value preceded by the has sign (#) as the value of the href attribute of the <a> tag.
    <a href="#sectionX">Jump to Section X</a>
    <h2 id="sectionX">Section X</h2>
    

    The above example creates this link: Jump to Section X

    ...which jumps to here:

    Section X

    Text Formatting

    HTML provides you with several tags that can be used to make text on your web site appear different from normal text.

    <p>This is <b>bold text</b>.</p>
    <p>This is <strong>strongly important text</strong>.</p>
    <p>This is <i>italic text</i>.</p>
    <p>This is <em>emphasized text</em>.</p>
    <p>This is <mark>highlighted text</mark>.</p>
    <p>This is <code>computer code</code>.</p>
    <p>This is <small>smaller text</small>.</p>
    <p>This is <sub>subscript</sub> and <sup>superscript</sup> text.</p>
    <p>This is <del>deleted text</del>.</p>
    <p>This is <ins>inserted text</ins>.</p>
    

    In the above example, you can see the most commonly used formatting tags. This is how they would appear:

    This is bold text.

    This is strongly important text.

    This is italic text.

    This is emphasized text.

    This is highlighted text.

    This is computer code.

    This is smaller text.

    This is subscript and superscript text.

    This is deleted text.

    This is inserted text.

    Quotations

    To format quotation blocks from other sources, you should use the blockquote tag.

    <blockquote>
        <p>Learn from yesterday, live for today, hope for tomorrow. The important thing is not to stop questioning.</p>
        <cite>— Albert Einstein</cite>
    </blockquote>
    

    The above example showcases the blockquote tag in action. The cite tag is used to describe a reference to a creative work. This is how it appears:

    Learn from yesterday, live for today, hope for tomorrow. The important thing is not to stop questioning.

    — Albert Einstein

    For short inline quoatations, you use the HTML <q> tag.

    <p>According to the World Health Organization (WHO): <q>Health is a state of complete physical, mental, and social well-being.</q></p>
    

    According to the World Health Organization (WHO): Health is a state of complete physical, mental, and social well-being.

    To display an address, use the <address> tag.

    <address>
    Mozilla Foundation<br>
    331 E. Evelyn Avenue<br>
    Mountain View, CA 94041, USA
    </address>
    

    The above example would appear as follows:

    Mozilla Foundation
    331 E. Evelyn Avenue
    Mountain View, CA 94041, USA

    Images

    You can add images to your site by using the <img> tag. This tag contains attributes only.

    <img src="https://api.time.com/wp-content/uploads/2019/12/ducks-walk-on-glass-roof-video.jpg" alt="duckss">
    

    The above image displays ducks: ducks

    The src attribute tells the browser where to find the image. The alt tag provides an alternative text for the image.

    You can set the width of an image using the width and height attributes.

    <img src="https://api.time.com/wp-content/uploads/2019/12/ducks-walk-on-glass-roof-video.jpg" alt="ducks" width="200px" height="100px">
    

    The above code produces the following image: ducks

    Below is a list of all of the currently available and useful HTML5 tags. You may try them out by navigating to this website, copy/pasting the html snippet at the bottom of this page, and running the project. You may also modify your index.html file in your project repossitory.

    TagDescriptionEnd Tag?
    <a>Defines a hyperlink.
    <abbr>Defines an abbreviated form of a longer word or phrase.
    <address>Specifies the author's contact information.
    <area>Defines a specific area within an image map.
    <article>Defines an article.
    <aside>Defines some content loosely related to the page content.
    <audio>Embeds a sound, or an audio stream in an HTML document.
    <b>Displays text in a bold style.
    <base>Defines the base URL for all relative URLs in a document.
    <bdi>Represents text that is isolated from its surrounding for the purposes of bidirectional text formatting.
    <bdo>Overrides the current text direction.
    <blockquote>Represents a section that is quoted from another source.
    <body>Defines the document's body.
    <br>Produces a single line break.
    <button>Creates a clickable button.
    <canvas>Defines a region in the document, which can be used to draw graphics on the fly via scripting (usually JavaScript).
    <caption>Defines the caption or title of the table.
    <cite>Indicatess a citation or reference to another source.
    <code>Specifies text as computer code.
    <col>Defines attribute values for one or more columns in a table.
    <colgroup>Specifies attributes for multiple columns in a table.
    <data>Links a piece of content with a machine-readable translation.
    <datalist>Represents a set of pre-defined options for an <input> element.
    <dd>Specifies a description, or value for the term (<dt>) in a description list (<dl>).
    <del>Represents text that has been deleted from the document.
    <details>Represents a widget from which the user can obtain additional information or controls on-demand.
    <dfn>Specifies a definition.
    <dialog>Defines a dialog box or sub window.
    <div>Specifies a division or a section in a document.
    <dl>Defines a description list.
    <dt>Defines a term (an item) in a description list.
    <em>Defines emphasized text.
    <embed>Embeds external application, typically multimedia content like audio or video into an HTML document.
    <fieldset>Specifies a set of related form fields.
    <figcaption>Defines a caption or legend for a figure.
    <figure>Represents a figure illustrated as part of the document.
    <footer>Represents the footer of a document or a section.
    <form>Defines an HTML form for user input.
    <head>Defines the head portion of the document that contains information about the document such as title.
    <header>Represents the header of a document or a section.
    <hgroup>Defines a group of headings.
    <h1 to <h6>Defines HTML headings.
    <hr>Produce a horizontal line.
    <html>Defines the root of an HTML document.
    <i>Displays text in an italic style.
    <iframe>Displays a URL in an inline frame.
    <img>Represents an image.
    <input>Defines an input control
    <ins>Defines a block of text that has been inserted into a document.
    <kbd>Specifies text as keyboard input.
    <keygen>Represents a control for generating a public-private key pair.
    <label>Defines a label for an <input> control.
    <legend>Defines a caption for a <fieldset> element.
    <li>Defines a list item.
    <link>Defines the relationship between the current document and an external resource.
    <main>Represents the main or dominant content of the document.
    <map>Defines a client-side image-map.
    <mark>Represents text highlighted for reference purposes.
    <menu>Represents a list of commands.
    <menuitem>Defines a list (or menuitem) of commands that a user can perform.
    <meta>Provides structured metadata about the document content.
    <meter>Represents a scalar measurement within a known range.
    <nav>Defines a section of navigation links.
    <noscript>Defines alternative content to display when the browser doesn't support scripting.
    <object>Defines an embedded object.
    <ol>Defines an ordered list.
    <optgroup>Defines a group of related options in a selection list.
    <option>Defines an option in a selection list.
    <output>Represents the result of a calculation.
    <p>Defines a paragraph.
    <param>Defines a parameter for an object or applet element.
    <picture>Defines a container for multiple image sources.
    <pre>Defines a block of preformatted text.
    <progress>Represents the completion progress of a task.
    <q>Defines a short inline quotation.
    <rp>Provides fall-back parenthesis for browsers that don't support ruby annotations.
    <rt>Defines the pronounciation of character presented in a ruby annotation.
    <ruby>Represents a ruby annotation.
    <s>Represents contents that are no longer accurate or no longer relevant.
    <samp>Specifies text as sample output from a computer program.
    <script>Places script in the document for a client-side processing.
    <section>Defines a section of a document, such as header, footer, etc.
    <select>Defines a selection list within a form.
    <small>Displays text in a smaller size.
    <source>Defines alternative media resources for the media elements like <audio> or <video>.
    <span>Defines an inline styleless section in a document.
    <strong>Indicate strongly emphasized text.
    <style>Inserts style information (commonly CSS) into the head of a document.
    <sub>Defines subscripted text.
    <summary>Defines a summary for the <details> element.
    <sup>Defines superscripted text.
    <svg>Embed SVG (Scalable Vector Graphics) content in an HTML document.
    <table>Defines a data table.
    <tbody>Groups a set of rows defining the main body of the table data.
    <td>Defines a cell in a table.
    <template>Defines the fragments of HTML that should be hidden when the page is loaded, but can be cloned and inserted in the document by JavaScript.
    <textarea>Defines a mutli-line text input control (text area).
    <tfoot>Groups a set of rows summarizing the columns of the table.
    <th>Defines a header cell in a table.
    <thead>Groups a set of rows that describes the column labels of a table.
    <time>Represents a time and/or date.
    <title>Defines a title for the document.
    <tr>Defines a row of cells in a table.
    <track>Defines text tracks for the media elements like <audio> or <video>.
    <u>Displays text with an underline.
    <ul>Defines an unordered list.
    <var>Defines a variable.
    <video>Embeds video content in an HTML document.
    <wbr>Represents a line break opportunity.
    <!DOCTYPE html>
    <html lang="en">
        <head>
            <meta charset="utf-8">
            <title>A quote</title>
        </head>
    
       <body>
            <h1>This is a header element.</h1>
    
            <blockquote>
                <p>This is a paragraph element. It is inside a blockquote element.</p>
            </blockquote>
    
            
        </body>
    </html>
    

    Chapter 1.3 - Homework


    Congratulations on making it all the way here! That was a lot to learn in just one chapter. Don't worry about memorizing all the terminology—this book always be available if you need to come back and look something up. Additionally, no single programmer remembers all of the HTML & CSS functionalities and they always consult search engines—don't be afraid to search up information as well! In fact, we encourage you to do that.

    Now that you know how to stylize and write more advanced HTML, let's add more interesting elements to our personal website that we set up in the last homework!

    Milestone 1: Creating a stylesheet file

    For the first milestone, create a file called style.css and place it in assets/css/ subdirectory of your project repository which you set up last time.

    Milestone 2: CSS Resets

    Because different web browsers might render our website differently, the practice of adding CSS resets to our HTML files has become a common practice. CSS resets take every common HTML element with a predefined style and provide one unified style for all browsers. These resets generally involve removing any sizing, margins, paddings, or additional styles and toning these values down.

    There are numerous types of resets available but the two most common are Eric Meyer's reset and Normalize.css. Normalize.css requires a stronger understanding of CSS so hold off on implementing it until you have mastered the language! For now, create another file called reset.css inside assets/css/ and paste the following code (use the "Copy to clipboard" button in the top-right):

    /* http://meyerweb.com/eric/tools/css/reset/ 
       v2.0 | 20110126
       License: none (public domain)
    */
    
    html, body, div, span, applet, object, iframe,
    h1, h2, h3, h4, h5, h6, p, blockquote, pre,
    a, abbr, acronym, address, big, cite, code,
    del, dfn, em, img, ins, kbd, q, s, samp,
    small, strike, strong, sub, sup, tt, var,
    b, u, i, center,
    dl, dt, dd, ol, ul, li,
    fieldset, form, label, legend,
    table, caption, tbody, tfoot, thead, tr, th, td,
    article, aside, canvas, details, embed, 
    figure, figcaption, footer, header, hgroup, 
    menu, nav, output, ruby, section, summary,
    time, mark, audio, video {
    	margin: 0;
    	padding: 0;
    	border: 0;
    	font-size: 100%;
    	font: inherit;
    	vertical-align: baseline;
    }
    /* HTML5 display-role reset for older browsers */
    article, aside, details, figcaption, figure, 
    footer, header, hgroup, menu, nav, section {
    	display: block;
    }
    body {
    	line-height: 1;
    }
    ol, ul {
    	list-style: none;
    }
    blockquote, q {
    	quotes: none;
    }
    blockquote:before, blockquote:after,
    q:before, q:after {
    	content: '';
    	content: none;
    }
    table {
    	border-collapse: collapse;
    	border-spacing: 0;
    }
    

    Milestone 3: Adding CSS to HTML files

    To get CSS talking to HTML, we reference our CSS file within our HTML file. The best practice for referencing CSS is to include our styles in external stylesheets (as we've done in the first two milestones) and include them from within the <head> element of our HTML document, like below:

    <!DOCTYPE html>
    <html lang="en">
    
    	<head>
    		<meta charset="utf-8">
    		<title>Example Website</title>
    
    		<link rel="stylesheet"  href="assets/css/style.css">
    	</head>
    
    	<body>
    		<!-- this is a comment -->
    	</body>
    
    </html>
    

    If our CSS file is within a subdirectory or subfolder, the href (stands for hyper-reference) attribute value needs to correlate to this path accordingly. For example, if our main.css file were stored within a subdirectory named css inside another subdirectory called assets, the href attribute value would be assets/css/main.css, using a forward slash to indicate moving into a subdirectory. This is identical to moving between directories in Unix! However, keep in mind that writing /assets/css/main.css instead of assets/css/main.css would break the website, since the first / would point to the root directory in your filesystem, not the directory in which your file is located! As a rule of thumb, use relative directories (like the one in the example above). You can also input real URLs here! However, sometimes websites that host CSS files go down, so it's better to store CSS locally for your own website.

    Now, open the index.html file we create last time and append the <head> tag with two elements below. Do not copy-paste the code from above, but make sure to place the elements below in the same place as in the example above.

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

    Milestone 4: Adding content

    Now, inside <body> of your index.html, add a header <h1> with the name of your website (it can be just your name) and a paragraph <p> with the description of your website (or a little bit about yourself).

    Milestone 5: Adding images

    Find an image that you want to appear on your website (it could be you!), add it to assets/img/, and incorporate it to your website using

    <img src="assets/img/{yourimage}" />
    

    where {yourimage} is the name of the your image file

    Don't forget to include the extension! Some operating systems don't show them by default, so either enable that setting on your machine or use ls inside the command line to see its full name.

    Milestone 6: Styling content

    Now, let's experience what you can do with CSS. It is up to you how you want to implement this milestone—feel free to play around with any of the CSS knowledge that we covered in this chapter or search up additional material online. However, here are just a few things that you could do:

    • Change the font size of your paragraph:
    p {
      font-size: 20px;
    }
    
    • Add an id attribute to your image (for example, id="my-image") and change its top margin:
    #my-image {
      margin-top: 4rem;
    }
    

    Now, experiment with your website—try adding classes, more HTML elements, <div> containers, etc. The best way to learn web development is by doing! In class, we'll ask you to spend a few minutes and showcase what you've learned from this exercise and share your knowledge with others.

    Milestone 7: Commit and push to Github

    Once you complete all the milestones above, you should commit your changes and push them too Github. This way, you'll be able to return to these changes later, and you can share your Github repository with other people.

    Chapter 2.1 — Introduction to User Interface Design.

    Interface design is not a science, and so it is hard to get right without trying to do it yourself and hearing what others think. After all, the point of interface design is to make interfaces that are enjoyable to use, visually appealing, and intuitive. Luckily, there are thousands of designers who have already done the hard work of trying different designs and seeing which ones work. Some of them decided to compile years of experience into books so that aspiring designers across the world can pick up the field easily.

    We have found what we think is the best book on interface design, Refactoring UI, and we thought it will be most effective if we provide it as is instead of trying to summarize it in this chapter. As part of this course, you should have received an email indicating how to obtain your copy of the PDF. If you didn't or you are struggling to find it—let us know!

    Homework

    Please do the following:

    • Read half of Refactoring UI. It may look like an overwhelming 100-page read, but it actually has only 10-20% text—the rest are image examples. We promise it won't take you long.
    • Start thinking about the website you want to make. To reiterate, it is up to you what you will produce. However, we encourage you develop a personal website since it can serve as your calling card online and will be useful on many occasions—for example, when applying to schools or jobs, or simply when developing your network. Draw a few sketches, search up inspirational personal websites online. In class, we will ask you to talk about the website that you want to have developed by the end of the course and to show your sketches.

    In the next homework, you will start to actually design this website! Yay!

    Chapter 2.2 — Advanced UI/UX design and tools.

    This chapter is a natural continuation of the previous one, and therefore our supplementary material is located in Refactoring UI. It would be inefficient to also require you to read the course reader for this section, and so we ended up putting most of the required material in the slides and will require you to read some advanced techniques in the textbook.

    Homework

    We are almost done covering the design concepts that will be useful for your website. You just need to do the following:

    • Read the rest of Refactoring UI. We covered a lot of material in class, but there are advanced techniques which we believe you'll find useful as you design your website.

    • Finalize your website idea and sketch a few designs for it. Be prepared to present them in class and talk about your speficic choices! Make sure to use some of the techniques we covered in the last two lectures, especially what you learned about hierarchy, spacing, and prototyping.

    Chapter 3.1 — Programming in JavaScript.


    What is JavaScript?

    You've learned about how the core architecture of a website is built, how it is styled, and what good design looks like. The question remains: how do we make our websites interactive?

    We use JavaScript, an object-oriented programming language, to write logic that allows our webistes to have interactivity. For example, we can:

    • Implement user registration
    • Book a ticket
    • Create an online store
    • Share photos
    • Write messages

    The possibilites are endless!

    JavaScript

    JavaScript is a frontend programming language, meaning that it is used by frontend web developers to create interfaces and user-centered features. You can think of HTML, CSS, and even JavaScript files as simple text files that contain keywords. Browsers use these keywords at the time of running your site to create a stunning website to your specifications. The browser can differentiate between HTML, CSS, and JavaScript files at runtime because of the extension you add at the end.

    HTML files will use a .html extention. CSS and JavaScript files use .css and .js, respectively.

    Chapter 3.1.1 - Variables


    Variables

    Variables store values that can be used and changed throughout your code. You can think of these as book titles that hold information inside.

    Creating and declaring a variabe has the following syntax: [keyword] [name].

    • Keyword: can be let or var.

    let gives your variable block scope. We recommend you use let over var to keep your variables within appropriate scope. We will cover scopes in the next chapter.

    • Name: can be any name you choose that follows these rules:
      • The first character must be a letter or an underscore (_). You cannot use a number as the first character.
      • The rest of the variable name can include any letter, number, or underscore. You cannot use any other characters, including spaces, symbols and punctuation marks.
      • Variable names are case sensitive.
      • There's no limit to the lenght of the variable name.
      • You cannot use JavaScript's reserved words as a variable name nor its keywords. Doing so confuses the program and can lead to undesired consequences.

    Task - working with variables

    1. Declare a variable. Let's declare a variable using the let keyword:

      let myVariable;
      

      myVariable has now been declared using the let keyword. It currently doesn't have a value.

    2. Assign a value. Store a value in a variable with the = operator, followed by the expected value.

      myVariable = 123;
      

      Note: the use of = in this lesson means we make use of an "assignment operator", used to set a value to a variable. It doesn't denote equality.

      myVariable has now been initialized with the value 123.

    3. Refactor. Replace your code with the following statement.

      let myVariable = 123;
      

      The above is called an explicit initialization when a variable is declared and is assigned a value at the same time.

    4. Change the variable value. Change the variable value in the following way:

      myVariable = 321;
      

      Once a variable is declared, you can change its value at any point in your code with the = operator and the new value.

      ✅ Try it! You can write JavaScript right in your browser. Open a browser window and navigate to Developer Tools. In the console, you will find a prompt; type let myVariable = 123, press return, then type myVariable. What happens? Note, you'll learn more about these concepts in subsequent lessons.

    Constants

    Declaration and initialization of a constant follows the same concepts as a variable, with the exception of the const keyword. Constants are typically declared with all uppercase letters.

    const MY_VARIABLE = 123;
    

    Constants are similar to variables, with two exceptions:

    • Must have a value. Constants must be initialized, or an error will occur when running code.

    • Reference cannot be changed. The reference of a constant cannot be changed once initialized, or an error will occur when running code. Let's look at two examples:

      • Simple value. The following is NOT allowed:
      const PI = 3;
      PI = 4; // not allowed
      
      • Object reference is protected. The following is NOT allowed.
      const obj = { a: 3 };
      obj = { b: 5 } // not allowed
      
      • Object value is not protected. The following IS allowed:
      const obj = { a: 3 };
      obj.a = 5;  // allowed
      

      Above you are changing the value of the object but not the reference itself, which makes it allowed.

      Note, a const means the reference is protected from reassignment. The value is not immutable though and can change, especially if it's a complex construct like an object.

    Data Types

    Variables can store many different types of values, like numbers and text. These various types of values are known as the data type. Data types are an important part of software development because it helps developers make decisions on how the code should be written and how the software should run. Furthermore, some data types have unique features that help transform or extract additional information in a value.

    ✅ Data Types are also referred to as JavaScript data primitives, as they are the lowest-level data types that are provided by the language. There are 6 primitive data types: string, number, bigint, boolean, undefined, and symbol. Take a minute to visualize what each of these primitives might represent. What is a zebra? How about 0? true?

    Numbers

    In the previous section, the value of myVariable was a number data type.

    let myVariable = 123;

    Variables can store all types of numbers, including decimals or negative numbers. Numbers also can be used with arithmetic operators, covered in the next section.

    Arithmetic Operators

    There are several types of operators to use when performing arithmetic functions, and some are listed here:

    SymbolDescriptionExample
    +Addition: Calculates the sum of two numbers1 + 2 //expected answer is 3
    -Subtraction: Calculates the difference of two numbers1 - 2 //expected answer is -1
    *Multiplication: Calculates the product of two numbers1 * 2 //expected answer is 2
    /Division: Calculates the quotient of two numbers1 / 2 //expected answer is 0.5
    %Remainder: Calculates the remainder from the division of two numbers1 % 2 //expected answer is 1

    ✅ Try it! Try an arithmetic operation in your browser's console. Do the results surprise you?

    Strings

    Strings are sets of characters that reside between single or double quotes.

    • 'This is a string'
    • "This is also a string"
    • let myString = 'This is a string value stored in a variable';

    Remember to use quotes when writing a string, or else JavaScript will assume it's a variable name.

    Formatting Strings

    Strings are textual, and will require formatting from time to time.

    To concatenate two or more strings, or join them together, use the + operator.

    let myString1 = "Hello";
    let myString2 = "World";
    
    myString1 + myString2 + "!"; // HelloWorld!
    myString1 + " " + myString2 + "!"; // Hello World!
    myString1 + ", " + myString2 + "!"; // Hello, World!
    
    

    ✅ Why does 1 + 1 = 2 in JavaScript, but '1' + '1' = 11? Think about it. What about '1' + 1?

    Template literals are another way to format strings, except instead of quotes, the backtick is used. Anything that is not plain text must be placed inside placeholders ${ }. This includes any variables that may be strings.

    let myString1 = "Hello";
    let myString2 = "World";
    
    `${myString1} ${myString2}!` //Hello World!
    `${myString1}, ${myString2}!` //Hello, World!
    

    You can achieve your formatting goals with either method, but template literals will respect any spaces and line breaks.

    ✅ When would you use a template literal vs. a plain string?

    Booleans

    Booleans can be only two values: true or false. Booleans can help make decisions on which lines of code should run when certain conditions are met. In many cases, operators assist with setting the value of a Boolean and you will often notice and write variables being initialized or their values being updated with an operator.

    • let myTrueBool = true
    • let myFalseBool = false

    ✅ A variable can be considered 'truthy' if it evaluates to a boolean true. Interestingly, in JavaScript, all values are truthy unless defined as falsy.

    Chapter 3.1.2 - Conditional Statements


    Comparison Operators and Booleans

    Operators are used to evaluate conditions by making comparisons that will create a Boolean value. The following is a list of operators that are frequently used.

    SymbolDescriptionExample
    <Less than: Compares two values and returns the true Boolean data type if the value on the left side is less than the right5 < 6 // true
    <=Less than or equal to: Compares two values and returns the true Boolean data type if the value on the left side is less than or equal to the right5 <= 6 // true
    >Greater than: Compares two values and returns the true Boolean data type if the value on the left side is larger than the right5 > 6 // false
    >=Greater than or equal to: Compares two values and returns the true Boolean data type if the value on the left side is larger than or equal to the right5 >= 6 // false
    ===Strict equality: Compares two values and returns the true Boolean data type if values on the right and left are equal AND are the same data type.5 === 6 // false
    !==Inequality: Compares two values and returns the opposite Boolean value of what a strict equality operator would return5 !== 6 // true

    ✅ Check your knowledge by writing some comparisons in your browser's console. Does any returned data surprise you?

    If statement

    The if statement will run code in between its blocks if the condition is true.

    if (condition) {
        // Condition was true. Code in this block will run.
    }
    

    Logical operators are often used to form the condition.

    if (currentMoney >= laptopPrice) {
        // Condition was true. Code in this block will run.
        console.log("Getting a new laptop!");
    }
    

    If-else statement

    The else statement will run the code in between its blocks when the condition is false. It's optional with an if statement.

    if (currentMoney >= laptopPrice){
        // Condition was true. Code in this block will run.
        console.log("Getting a new laptop!");
    } else {
        // Condition was false. Code in this block will run.
        console.log("Can't afford a new laptop, yet!");
    }
    

    ✅ Test your understanding of this code and the following code by running it in a browser console. Change the values of the currentMoney and laptopPrice variables to change the output of console.log().

    Logical operators and booleans

    Decisions might require more than one comparison, and can be strung together with logical operators to produce a Boolean value.

    Logical AND: Compares two Boolean expressions. Returns true only if both sides are true:

    (5 > 6) && (5 < 6 ) // One side is false, other is true. Returns false.
    

    Logical OR: Compares two Boolean expressions. Returns true if at least one side is true

    (5 > 6) || (5 < 6) // One side is false, other is true. Returns true.
    

    Logical NOT: Returns the opposite value of a Boolean expression

    !(5 > 6) // 5 is not greater than 6, but "!" will return true
    

    Conditions and Decisions with Logical Operators

    Logical operators can be used to form conditions in if..else statements.

    let currentMoney;
    let laptopPrice;
    // Laptop price at 20 percent off
    let laptopDiscountPrice = laptopPrice - (laptopPrice * .2)
    
    if (currentMoney >= laptopPrice || currentMoney >= laptopDiscountPrice) {
        // Condition was true. Code in this block will run.
        console.log("Getting a new laptop!");
    } else {
        // Condition was true. Code in this block will run.
        console.log("Can't afford a new laptop, yet!");
    }
    

    Negation operator

    You've seen so far how if you can use an if...else statement to create conditional logic. Anything that goes into an if needs to evaluate to true/false. By using the ! operator you can negate the expression. It would look like so:

    if (!condition) {
      // runs if condition is false
    } else {
      // runs if condition is true
    }
    

    Ternary expressions

    if...else isn't the only way to express decision logic. You can also use something called a ternary operator. The syntax for it looks like this:

    let variable = condition ? <this if true> : <this if false>
    

    Below is a more tangible example:

    let firstNumber = 20;
    let secondNumber = 10
    let biggestNumber = firstNumber > secondNumber ? firstNumber: secondNumber;
    

    ✅ Take a minute to read this code a few times. Do you understand how these operators are working?

    The above states that

    • if firstNumber is larger than secondNumber
    • then assign firstNumber to biggestNumber
    • else assign secondNumber.

    The ternary expression is just a compact way of writing the code below:

    let biggestNumber;
    if (firstNumber > secondNumber) {
      biggestNumber = firstNumber;
    } else {
      biggestNumber = secondNumber;
    }
    

    Chapter 3.1.3 - Arrays & Loops


    Arrays

    Working with data is a common task for any language, and it's a much easier task when data is organized in a structural format, such as arrays. With arrays, data is stored in a structure similar to a list. One major benefit of arrays is that you can store different types of data in one array.

    ✅ Arrays are all around us! Can you think of a real-life example of an array, such as a solar panel array?

    The syntax for an array is a pair of square brackets.

    let myArray = [];

    This is an empty array, but arrays can be declared already populated with data. Multiple values in an array are separated by a comma.

    let iceCreamFlavors = ["Chocolate", "Strawberry", "Vanilla", "Pistachio", "Rocky Road"];

    The array values are assigned a unique value called the index, a whole number that is assigned based on its distance from the beginning of the array. In the example above, the string value "Chocolate" has an index of 0, and the index of "Rocky Road" is 4. Use the index with square brackets to retrieve, change, or insert array values.

    ✅ Does it surprise you that arrays start at the zero index? In some programming languages, indexes start at 1. There's an interesting history around this, which you can read on Wikipedia.

    let iceCreamFlavors = ["Chocolate", "Strawberry", "Vanilla", "Pistachio", "Rocky Road"];
    iceCreamFlavors[2]; // "Vanilla"
    

    You can leverage the index to change a value, like this:

    iceCreamFlavors[4] = "Butter Pecan"; // Changed "Rocky Road" to "Butter Pecan"
    

    And you can insert a new value at a given index like this:

    iceCreamFlavors[5] = "Cookie Dough"; // Added "Cookie Dough"
    

    ✅ A more common way to push values to an array is by using array operators such as array.push()

    To find out how many items are in an array, use the length property.

    let iceCreamFlavors = ["Chocolate", "Strawberry", "Vanilla", "Pistachio", "Rocky Road"];
    iceCreamFlavors.length; // 5
    

    ✅ Try it yourself! Use your browser's console to create and manipulate an array of your own creation.

    Loops

    Loops allow for repetitive or iterative tasks, and can save a lot of time and code. Each iteration can vary in their variables, values, and conditions. There are different types of loops in JavaScript, and they have small differences, but essentially do the same thing: loop over data.

    For Loop

    The for loop requires 3 parts to iterate: - counter A variable that is typically initialized with a number that counts the number of iterations. - condition Expression that uses comparison operators to cause the loop to stop when true - iteration-expression Runs at the end of each iteration, typically used to change the counter value

    // Counting up to 10
    for (let i = 0; i < 10; i++) {
      console.log(i);
    }
    

    i++ is a shortcut for i = i + 1 called "postfix increment". It increments the given variable by one after it's used. For example, for i = 1, console.log(i++) will output 1 and then increment the value of i. If you need the shortcut than increments first and then uses the value, use ++i, known as "prefix increment."

    ✅ Run this code in a browser console. What happens when you make small changes to the counter, condition, or iteration expression? Can you make it run backwards, creating a countdown?

    While loop

    Unlike the syntax for the for loop, while loops only require a condition that will stop the loop when true. Conditions in loops usually rely on other values like counters, and must be managed during the loop. Starting values for counters must be created outside the loop, and any expressions to meet a condition, including changing the counter must be maintained inside the loop.

    // Counting up to 10
    let i = 0;
    while (i < 10) {
      console.log(i);
      i++;
    }
    

    ✅ Why would you choose a for loop vs. a while loop? 17K viewers had the same question on StackOverflow, and some of the opinions might be interesting to you.

    Loops and Arrays

    Arrays are often used with loops because most conditions require the length of the array to stop the loop, and the index can also be the counter value.

    let iceCreamFlavors = ["Chocolate", "Strawberry", "Vanilla", "Pistachio", "Rocky Road"];
    
    for (let i = 0; i < iceCreamFlavors.length; i++) {
      console.log(iceCreamFlavors[i]);
    } // Ends when all flavors are printed
    

    ✅ Experiment with looping over an array of your own making in your browser's console.

    Chapter 3.1 - Homework


    The best and only way to really understand any programming concept is to try it in action. That is why we designed a few programming exercises for you to complete using the concepts you've learned in this chapter—variables, conditional statements, arrays, and loops. We will ask you to explain some of these in class, as well as to show your code and provide feedback!

    Exercises with variables

    As you know, different variables can hold different data types. In some other languages you need to explicitly state what type should a variable hold: integer, character, string, boolean, etc. In JavaScript, you don't need to specify that, and instead you just use var, let, or const, depending on your use case. This approach has pros and cons: you don't have to worry about defining data types, but it often leads to unexpected bugs in your code (for example, 3 + '3' == '33' but 3 - '3' == 0). To fix this, Microsoft actually designed a typed version of JavaScript called TypeScript, but we won't get into that. For now, experiment with different types in plain JavaScript. Open the console in your browser (Right Click, Inspect, Console) and do the following:

    1. Create a variable called myName and assign your own name to it. Remember that strings can be defined as follows:
      let string1 = "Hello, string1"
      let string2 = 'Hello, string2'
      let string3 = `Hello, string3`
      
    2. Create a variable called myAge and assign your age to it. Numbers don't have to have quotation marks around them.
    3. Create a variable called myAgeInTenYears and assign your age in ten years to it. However, you have to use myAge to set myAgeInTenYears. Remember that you can assign arithmetic operations to variables!
    4. Similarly, create a variable called halfOfMyAge and assign half of your age to it using myAge.
    5. Finally, create another variable called myMessage as follows:
      let myMessage = `I'm ${myName} and I'll be ${myAge + 10} years old soon.`
      
      Now, print it out, using console.log(myMessage). As you can see, using back quotes allows you to embed JavaScript code inside your strings with ${code} syntax!

    Exercises with conditional statements

    Earlier, we've learned about if-else statements. However, there is another way to improve them, using else if statements. It allows to merge more sophisticated conditions. For example,

    if (condition1) {
      console.log("condition1 is true")
    } else if (condition2) {
      console.log("condition2 is true")
    } else {
      console.log("condition1 and condition2 are both false")
    }
    

    Note that you don't have to have the last else statements. To practice this structure, do the following simple challenge:

    1. It creates a variable called pockedMoney with some sum of money.
    2. If that sum of money exceeds $1000, it prints I can afford the new iPhone!. If it is less than $1000 but more than $900, it prints I almost have enough money!. Otherwise, it prints I can't afford the new iPhone..

    Use if-else statements and logic operators!

    Exercises with loops

    Loops allow to repeat the same code multiple times with different values, without having to repeat the code itself. Sometimes, it just helps simplify the code, but often it is impossible to avoid, as you may need to execute the same code millions of times or you may not know variable values in advance. For example, the following code will print five consecutive integers starting from one:

    console.log(1)
    console.log(2)
    console.log(3)
    console.log(4)
    console.log(5)
    

    However, what if you wanted to print 1000 consecutive integers? Writing 1000 lines of code will take a long time... Similarly, what if you want to print n consecutive numbers but you don't know what n is? This is where loops come into play.

    Loops Challenge 1

    Using the while loop, print powers of the first 16 integers. Your code should produce the following:

    1
    4
    9
    16
    25
    36
    49
    64
    81
    100
    121
    144
    169
    196
    225
    256
    

    However, you may only have one line that contains console.log(). As a hint, here is how a while loop would like:

    let i = 0;
    while (condition) {
      // code
      i++;
    }
    

    In JavaScript, everything after // indicates a "comment" and doesn't affect anything.

    In order to input multiple lines in your console, hold Shift before creating a new line.

    Loops Challenge 2

    Using the for loop, print the sum of the first 100 integers. As a hint, you may use the following template code:

    // code
    for (let i = 0; i < 100; i++) {
      // code
    }
    // print
    

    You will probably need other variable(s) besides i! Once you complete this, rewrite this code using the while loop. After all, they are identical! (At least using the features that we have learned so far.)

    Exercises with arrays

    Arrays in JavaScript can hold multiple variable types at the same time. For example, this is a valid array in JavaScript:

    let arr = ['Hello', 2021]
    

    Remember also that you can access elements by their index, starting from. For example,

    console.log(arr[0])
    

    will print Hello.

    For the final part of your homework, create an array that holds any 5 elements, and print it out using a loop!

    Note about homework

    Please save the code that you are going to write somewhere convenient so that you can show it in class!

    Chapter 3.2. - Advanced Programming Concepts


    In the last chapter, we covered programming fundamentals that are the building blocks of all coding languages. Now that you are equipped with the knowledge about variables, arrays, boolean logic, conditional statements, and loops, you are ready to learn about more advanced topics. Once you master those, you will know most of JavaScript!

    Chapter 3.2.1 - Functions


    At its core, a function is a block of code we can execute on demand. This is perfect for scenarios where we need to perform the same task multiple times; rather than duplicating the logic in multiple locations (which would make it hard to update when the time comes), we can centralize it in one location, and call it whenever we need the operation performed - you can even call functions from other functions!.

    Just as important is the ability to name a function. While this might seem trivial, the name provides a quick way of documenting a section of code. You could think of this as a label on a button. If I click on a button which reads "Cancel timer", I know it's going to stop running the clock.

    Creating and calling a function

    The syntax for a function looks like the following:

    function nameOfFunction() { // function definition
      // function definition/body
    }
    

    If I wanted to create a function to display a greeting, it might look like this:

    function displayGreeting() {
      console.log('Hello, world!');
    }
    

    Whenever we want to call (or invoke) our function, we use the name of the function followed by (). It's worth noting the fact our function can be defined before or after we decide to call it; the JavaScript compiler will find it for you.

    // calling our function
    displayGreeting();
    

    NOTE: There is a special type of function known as a method, which you've already been using! In fact, we saw this in our demo above when we used console.log. What makes a method different from a function is a method is attached to an object (console in our example), while a function is free floating. You will hear many developers use these terms interchangeably.

    Function best practices

    There are a handful of best practices to keep in mind when creating functions

    • As always, use descriptive names so you know what the function will do
    • Use camelCasing to combine words
    • Keep your functions focused on a specific task

    Passing information to a function

    To make a function more reusable you'll often want to pass information into it. If we consider our displayGreeting example above, it will only display Hello, world!. Not the most useful function one could create. If we want to make it a little more flexible, like allowing someone to specify the name of the person to greet, we can add a parameter. A parameter (also sometimes called an argument), is additional information sent to a function.

    Parameters are listed in the definition part within parenthesis and are comma separated like so:

    function name(param, param2, param3) {
    
    }
    

    We can update our displayGreeting to accept a name and have that displayed.

    function displayGreeting(name) {
      const message = `Hello, ${name}!`;
      console.log(message);
    }
    

    When we want to call our function and pass in the parameter, we specify it in the parenthesis.

    displayGreeting('Christopher');
    // displays "Hello, Christopher!" when run
    

    Default values

    We can make our function even more flexible by adding more parameters. But what if we don't want to require every value be specified? Keeping with our greeting example, we could leave name as required (we need to know who we're greeting), but we want to allow the greeting itself to be customized as desired. If someone doesn't want to customize it, we provide a default value instead. To provide a default value to a parameter, we set it much in the same way we set a value for a variable - parameterName = 'defaultValue'. To see a full example:

    function displayGreeting(name, salutation='Hello') {
      console.log(`${salutation}, ${name}`);
    }
    

    When we call the function, we can then decide if we want to set a value for salutation.

    displayGreeting('Christopher');
    // displays "Hello, Christopher"
    
    displayGreeting('Christopher', 'Hi');
    // displays "Hi, Christopher"
    

    Return values

    Up until now the function we built will always output to the console. Sometimes this can be exactly what we're looking for, especially when we create functions which will be calling other services. But what if I want to create a helper function to perform a calculation and provide the value back so I can use it elsewhere?

    We can do this by using a return value. A return value is returned by the function, and can be stored in a variable just the same as we could store a literal value such as a string or number.

    If a function does return something then the keyword return is used. The return keyword expects a value or reference of what's being returned like so:

    return myVariable;
    

    We could create a function to create a greeting message and return the value back to the caller

    function createGreetingMessage(name) {
      const message = `Hello, ${name}`;
      return message;
    }
    

    When calling this function we'll store the value in a variable. This is much the same way we'd set a variable to a static value (like const name = 'Christopher').

    const greetingMessage = createGreetingMessage('Christopher');
    

    Functions as parameters for functions

    As you progress in your programming career, you will come across functions which accept functions as parameters. This neat trick is commonly used when we don't know when something is going to occur or complete, but we know we need to perform an operation in response.

    As an example, consider setTimeout, which begins a timer and will execute code when it completes. We need to tell it what code we want to execute. Sounds like a perfect job for a function!

    If you run the code below, after 3 seconds you'll see the message 3 seconds has elapsed.

    function displayDone() {
      console.log('3 seconds has elapsed');
    }
    // timer value is in milliseconds
    setTimeout(displayDone, 3000);
    

    Anonymous functions

    Let's take another look at what we've built. We're creating a function with a name which will be used one time. As our application gets more complex, we can see ourselves creating a lot of functions which will only be called once. This isn't ideal. As it turns out, we don't always need to provide a name!

    When we are passing a function as a parameter we can bypass creating one in advance and instead build one as part of the parameter. We use the same function keyword, but instead we build it as a parameter.

    Let's rewrite the code above to use an anonymous function:

    setTimeout(function() {
      console.log('3 seconds has elapsed');
    }, 3000);
    

    If you run our new code you'll notice we get the same results. We've created a function, but didn't have to give it a name!

    Fat arrow functions

    One shortcut common in a lot of programming languages (including JavaScript) is the ability to use what's called an arrow or fat arrow function. It uses a special indicator of =>, which looks like an arrow - thus the name! By using =>, we are able to skip the function keyword.

    Let's rewrite our code one more time to use a fat arrow function:

    setTimeout(() => {
      console.log('3 seconds has elapsed');
    }, 3000);
    

    When to use each strategy

    You've now seen we have three ways to pass a function as a parameter and might be wondering when to use each. If you know you'll be using the function more than once, create it as normal. If you'll be using it for just the one location, it's generally best to use an anonymous function. Whether or not you use a fat arrow function or the more traditional function syntax is up to you, but you will notice most modern developers prefer =>.

    Chapter 3.2.2 - Scope


    Scope, in programming, is the availability of a certain varaible or set of variables. We can have local and global variables.

    For instance, let’s say you define a variable message:

    const message = 'Hello';
    console.log(message); // 'Hello'
    

    Then, you could easily log this variable in the next line after the declaration. No questions here.

    Now, let’s move the declaration of message inside of an if code block:

    if (true) {
      const message = 'Hello';
    }
    console.log(message); // ReferenceError: message is not defined
    

    This time, when trying to log the variable, JavaScript throws ReferenceError: message is not defined.

    Why does it happen?

    The if code block creates a scope for message variable. And message variable can be accessed only within this scope.

    At a higher level, the accessibility of variables is limited by the scope where they’re created. You are free to access the variable defined within its scope. But outside of its scope, the variable is inaccessible.


    Block Scope

    A code block in JavaScript defines a scope for variables declared using let and const:

    if (true) {
      // "if" block scope
      const message = 'Hello';
      console.log(message); // 'Hello'
    }
    console.log(message); // throws ReferenceError
    

    The first console.log(message) correctly logs the variable because message is accessed from the scope where it is defined.

    But the second console.log(message) throws a reference error because message variable is accessed outside of its scope: the variable doesn’t exist here.

    The code block of if, for, while statements also create a scope.

    In the following example for loop defines a scope:

    for (const color of ['green', 'red', 'blue']) {
      // "for" block scope
      const message = 'Hi';
      console.log(color);   // 'green', 'red', 'blue'
      console.log(message); // 'Hi', 'Hi', 'Hi'
    }
    console.log(color);   // throws ReferenceError
    console.log(message); // throws ReferenceError
    

    color and message variables exist within the scope of while code block.

    for (const el of arr) is a shortcut to iterate over arrays using a for loop in JavaScript!

    Same way the code block of while statement creates a scope for its variables:

    while (/* condition */) {
      // "while" block scope
      const message = 'Hi';
      console.log(message); // 'Hi'
    }
    console.log(message); // => throws ReferenceError
    

    message is defined within while() body, consequently message is accessible only within while() body.

    In JavaScript you can define standalone code blocks. The standalone code blocks also delimit a scope:

    {
      // block scope
      const message = 'Hello';
      console.log(message); // 'Hello'
    }
    console.log(message); // throws ReferenceError
    

    Note: var is not block scoped. The snippet below declares a variable count using a var statement:

    if (true) {
      // "if" block scope
      var count = 0;
      console.log(count); // 0
    }
    console.log(count); // 0
    

    count variable, as expected, is accessible within the scope of if code block. However, count variable is also accessible outside!

    A code block does not create a scope for var variables, but a function body does.


    Function Scope

    A function in JavaScript defines a scope for variables declared using var, let and const.

    Let’s declare a var variable within a function body:

    function run() {
      // "run" function scope
      var message = 'Run, Forrest, Run!';
      console.log(message); // 'Run, Forrest, Run!'
    }
    
    run();
    console.log(message); // throws ReferenceError
    

    run() function body creates a scope. The variable message is accessible inside of the function scope, but inaccessible outside.

    Same way, a function body creates a scope for let, const and even function declarations.

    function run() {
      // "run" function scope
      const two = 2;
      let count = 0;
      function run2() {}
    
      console.log(two);   // 2
      console.log(count); // 0
      console.log(run2);  // function
    }
    
    run();
    console.log(two);   // throws ReferenceError
    console.log(count); // throws ReferenceError
    console.log(run2);  // throws ReferenceError
    

    Scopes Can Be Nested

    An interesting property of scopes is that they can be nested.

    In the following example the function run() creates a scope, and inside an if condition code block creates another scope:

    function run() {
      // "run" function scope
      const message = 'Run, Forrest, Run!';
    
      if (true) {
        // "if" code block scope
        const friend = 'Bubba';
        console.log(message); // 'Run, Forrest, Run!'
      }
    
      console.log(friend); // throws ReferenceError
    }
    
    run();
    

    If code block scope is nested inside the run() function scope. Scopes of any type (code block, function, module) can be nested.

    The scope contained within another scope is named inner scope. In the example, if code block scope is an inner scope of run() function scope.

    The scope that wraps another scope is named outer scope. In the example, run() function scope is an outer scope to if code block scope.

    The inner scope can access the variables of its outer scope.


    Global Scope

    The global scope is the outermost scope. It is accessible from any inner (aka local) scope.

    In a browser environment, the topmost scope of JavaScript file loaded using <script> tag is a global scope:

    <script src="myScript.js"></script>
    
    // myScript.js
    
    // "global" scope
    let counter = 1;
    

    A variable declared inside the global scope is named global variable. Global variables are accessible from any scope.

    In the previous code snippet, counter is a global variable. This variable can be accessed from any place of the webpage’s JavaScript.

    The global scope is a mechanism that lets the host of JavaScript (browser, Node) supply applications with host-specific functions as global variables.

    window and document, for example, are global variables supplied by the browser. In a Node environment, you can access process object as a global variable.


    Variable Isolation

    An immediate property of scope arises: the scope isolates the variables. And what’s good different scopes can have variables with the same name.

    You can reuse common variables names (count, index, current, value, etc.) in different scopes without collisions.

    foo() and bar() function scopes have their own, but same named, variable count:

    function foo() {
      // "foo" function scope
      let count = 0;
      console.log(count); // 0
    }
    
    function bar() {
      // "bar" function scope
      let count = 1;
      console.log(count); // 1
    }
    
    foo();
    bar();
    

    Chapter 3.2.3 - Objects & Classes


    In concept...

    To start with, let's give you a simplistic, high-level view of what Object-oriented programming (OOP) is. We say simplistic, because OOP can quickly get very complicated, and giving it a full treatment now would probably confuse more than help. The basic idea of OOP is that we use objects to model real world things that we want to represent inside our programs, and/or provide a simple way to access functionality that would otherwise be hard or impossible to make use of.

    Objects can contain related data and code, which represent information about the thing you are trying to model, and functionality or behavior that you want it to have. Object data (and often, functions too) can be stored neatly (the official word is encapsulated) inside an object package (which can be given a specific name to refer to, which is sometimes called a namespace), making it easy to structure and access; objects are also commonly used as data stores that can be easily sent across the network.

    Let's consider a simple program that displays information about the students and teachers at a school. Here we'll look at OOP theory in general, not in the context of any specific programming language.

    There are lots of things you could know about a person (their address, height, shoe size, DNA profile, passport number, significant personality traits ...) , but in this case we are only interested in showing their name, age, gender, and interests, and we also want to be able to write a short introduction about them based on this data, and get them to say hello. This is known as abstraction — creating a simple model of a more complex thing, which represents its most important aspects in a way that is easy to work with for our program's purposes.

    ID Tag for person

    Creating Actual Objects

    From our class, we can create object instances — objects that contain the data and functionality defined in the class. From our Person class, we can now create some actual people: ID tag graphic

    When an object instance is created from a class, the class's constructor function is run to create it. This process of creating an object instance from a class is called instantiation — the object instance is instantiated from the class.

    Specialist Classes

    In this case we don't want generic people — we want teachers and students, which are both more specific types of people. In OOP, we can create new classes based on other classes — these new child classes (also known as subclasses) can be made to inherit the data and code features of their parent class, so you can reuse functionality common to all the object types rather than having to duplicate it. Where functionality differs between classes, you can define specialized features directly on them as needed.

    Specialist classes graphic

    This is really useful — teachers and students share many common features such as name, gender, and age, so it is convenient to only have to define those features once. You can also define the same feature separately in different classes, as each definition of that feature will be in a different namespace. For example, a student's greeting might be of the form "Yo, I'm [firstName]" (e.g Yo, I'm Sam), whereas a teacher might use something more formal, such as "Hello, my name is [Prefix] [lastName], and I teach [Subject]." (e.g Hello, My name is Mr Griffiths, and I teach Chemistry).

    Note: The fancy word for the ability of multiple object types to implement the same functionality is polymorphism.

    You can now create object instances from your child classes.

    Graphic showcasing child classes

    In practice...

    JavaScript uses special functions called constructor functions to define and initialize objects and their features. They are useful because you'll often come across situations in which you don't know how many objects you will be creating; constructors provide the means to create as many objects as you need in an effective way, attaching data and functions to them as required.

    In the following example we define a normal function:

    function createNewPerson(name) {
      const obj = {};
      obj.name = name;
      obj.greeting = function() {
        alert('Hi! I\'m ' + obj.name + '.');
      };
      return obj;
    }
    

    Then, we create a new person by calling the function:

    const salva = createNewPerson('Salva');
    salva.name;
    salva.greeting();
    

    It works well enough. If we know we want to create an object, why do we need to explicitly create a new empty object and return? Luckily, JavaScript provides uss with constructor functions so that we may do this with more ease.

    We replace the previous function with:

    function Person(name) {
      this.name = name;
      this.greeting = function() {
        alert('Hi! I\'m ' + this.name + '.');
      };
    }
    

    The constructor function is JavaScript's version of a class. Notice that it has all the features you'd expect in a function, although it doesn't return anything or explicitly create an object — it basically just defines properties and methods.

    Notice also the this keyword being used here as well — it is basically saying that whenever one of these object instances is created, the object's name property will be equal to the name value passed to the constructor call, and the greeting() method will use the name value passed to the constructor call too.

    Note: A constructor function name usually starts with a capital letter — this convention is used to make constructor functions easier to recognize in code.

    To call a constructor to creat objects...

    let person1 = new Person('Bob');
    let person2 = new Person('Sarah');
    

    In each case, the new keyword is used to tell the browser we want to create a new object instance, followed by the function name with its required parameters contained in parentheses, and the result is stored in a variable — very similar to how a standard function is called.

    You can access some of the values and/or functions try...

    person1.name
    person1.greeting()
    person2.name
    person2.greeting()
    

    The full constructor for our person would look like this:

    function Person(first, last, age, gender, interests) {
      this.name = {
         first : first,
         last : last
      };
      this.age = age;
      this.gender = gender;
      this.interests = interests;
      this.bio = function() {
        alert(this.name.first + ' ' + this.name.last + ' is ' + this.age + ' years old. He likes ' + this.interests[0] + ' and ' + this.interests[1] + '.');
      };
      this.greeting = function() {
        alert('Hi! I\'m ' + this.name.first + '.');
      };
    }
    

    And to create an object instance from it:

    let person1 = new Person('Bob', 'Smith', 32, 'male', ['music', 'skiing']);
    

    Finally, to access the variables and functions:

    person1['age']
    person1.interests[1]
    person1.bio()
    // etc.
    

    Chapter 3.2 - Homework


    Warmup

    To get a bit of practice with functions and objects, create a function called convertFahrenheitToCelsius that accepts an object that contains a fahrenheit field, converts it to Celsius and saves to celsius field, and returns the whole object. Your function should look like this:

    function convertFahrenheitToCelsius(temperature) {
        // your code goes here
    }
    

    Once you implement it, if we run the following code:

    let temp = { fahrenheit: 100 }
    temp = convertFahrenheitToCelsius(temp)
    console.log(temp.celsius)
    

    it will print the temperature in Celsius!

    Animations using JavaScript libraries

    Go to this link to complete this assignment. We are going to be using the I2Djs framework to create a fun animation!

    Picture of animation using JS

    JavaScript can be used as a drawing tool, bringing HTML and CSS elements to life on a web browser screen. Being able to make static pages look more appealing with graphical elements is a key part of web development, so learning how to make the most out of JavaScript’s drawing capabilities is critical.

    First, we are going to create some variables in the global scope. For the purpose of this assignment, we will not modify the HTML nor the CSS files.

    var renderer_ = i2d.svgLayer('#MySVG', { });
    var parallelChain = i2d.chain.parallelChain().loop(10)
    var circlesCount = 100
    var radius = 100
    

    Here, we created an SVG layer by invoking the svgLayer method with ContainerID "#mySvg". It returns the SVG renderer instance and saves a reference point to the variable renderer_. Then, we created an instance of a parallelChain() which is used to perform one or more animations simultaneously. The .loop(10) specification changes configures the animation to run 10 times. circlesCount set the number of circles created to 100 and their radius to 100 pixels.

    var g = renderer_.createEl({
        el: 'group',
        attr: {
            transform: {
                translate: [renderer_.width / 2, renderer_.height / 2]
            }
        }
    })
    

    .createEl({...}) is used to create the Element of type el with attr attributes. The element is saved to the var g.

    g.createEls((new Array(circlesCount)).fill().map(function(d, i) {
            return i
        }), {
            el: 'circle',
            attr: {
                r: 5,
                cx: 0,
                cy: 0
            },
            style: {
                fill: function(d) {
                    return 'hsl(' + ((d % 50) / 50) * 360 + ',70%, 50%)'
                }
            }
        })
        .exec(animateEachCircle)
    

    The .createEls function is used to create more than one element fo type g based on the information given in the form of an array.

    function animateEachCircle(d) {
        parallelChain.add(this.animateExe({
            duration: 2000,
            delay: (d % 50) * 30,
            ease: 'easeInOutSin',
            attr: function(f) {
                this.setAttr({
                    cx: radius * Math.cos(f * Math.PI * 2 + Math.PI * Math.floor(d / 50)) + (-radius + Math.floor(d / 50) * radius * 2),
                    cy: radius * Math.sin(f * Math.PI * 2 + Math.PI * Math.floor(d / 50))
                })
            }
        }))
    }
    

    We define a function animateEachCircle that takes an element d and animates it using the parallelChain we defined earlier. This is not imperative that you undestand in great detail since the assignment is only meant to demonstrate a high level function-usage to you.

    Ensure your animation runs by adding this at the bottom of your code:

    parallelChain.start()
    

    Here is what the complete code should look like:

    var renderer_ = i2d.svgLayer('#MySVG', { });
    var parallelChain = i2d.chain.parallelChain().loop(10)
    var circlesCount = 100
    var radius = 100
    
    var g = renderer_.createEl({
        el: 'group',
        attr: {
            transform: {
                translate: [renderer_.width / 2, renderer_.height / 2]
            }
        }
    })
    
    g.createEls((new Array(circlesCount)).fill().map(function(d, i) {
            return i
        }), {
            el: 'circle',
            attr: {
                r: 5,
                cx: 0,
                cy: 0
            },
            style: {
                fill: function(d) {
                    return 'hsl(' + ((d % 50) / 50) * 360 + ',70%, 50%)'
                }
            }
        })
        .exec(animateEachCircle)
    
    function animateEachCircle(d) {
        parallelChain.add(this.animateExe({
            duration: 2000,
            delay: (d % 50) * 30,
            ease: 'easeInOutSin',
            attr: function(f) {
                this.setAttr({
                    cx: radius * Math.cos(f * Math.PI * 2 + Math.PI * Math.floor(d / 50)) + (-radius + Math.floor(d / 50) * radius * 2),
                    cy: radius * Math.sin(f * Math.PI * 2 + Math.PI * Math.floor(d / 50))
                })
            }
        }))
    }
    
    parallelChain.start()
    

    Chapter 3.3 - Manipulating the DOM using JavaScript


    Manipulating the DOM, or the "Document Object Model", is a key aspect of web development. According to MDN, "The Document Object Model (DOM) is the data representation of the objects that comprise the structure and content of a document on the web." The challenges around DOM manipulation on the web have often been the impetus behind using JavaScript frameworks instead of vanilla JavaScript to manage the DOM, but we will manage on our own!

    In addition, this lesson will introduce the idea of a JavaScript closure, which you can think of as a function enclosed by another function so that the inner function has access to the outer function's scope.

    JavaScript closures are a vast and complex topic. This lesson touches on the most basic idea that in this terrarium's code, you will find a closure: an inner function and an outer function constructed in a way to allow the inner function access to the outer function's scope. For much more information on how this works, please visit the extensive documentation.

    We will use a closure to manipulate the DOM.

    Think of the DOM as a tree, representing all the ways that a web page document can be manipulated. Various APIs (Application Program Interfaces) have been written so that programmers, using their programming language of choice, can access the DOM and edit, change, rearrange, and otherwise manage it.

    Tree Diagram for DOM

    A representation of the DOM and the HTML markup that references it. From Olfa Nasraoui

    We will use a closure to manipulate the DOM.

    What is the DOM?


    The HTML code you write is parsed by the brower and turned into the DOM. If you right click on any website while you are in your web broswer and choose, 'View Page Source' some familiar HTML code witll pop up--that is a visual representation of the DOM!

    So is the

    Think of the DOM as a tree, representing all the ways that a web page document can be manipulated. Various APIs (Application Program Interfaces) have been written so that programmers, using their programming language of choice, can access the DOM and edit, change, rearrange, and otherwise manage it.

    Tree Diagram for DOM

    A representation of the DOM and the HTML markup that references it. From Olfa Nasraoui

    Prerequisite

    To complete learn about the DOM it is best to build a small project that showcases the capabilities of understanding exactly how to use all of the tools DOM manipulation schematics offer.

    Go to https://codepen.io/rommelnunez/pen/QWvqGmL to access the project you will be working on.

    Modifying the DOM with JavaScript


    You will see in your CodePen.io project that there is a panel available for JavaScript. This is equivalent to you creating a file script.js in the same directory as you .html in your local directory.

    If you were doing this project locally you would create a script.js file in your computer and link it to the html document by specifying:

    <script src="./script.js" defer></script>
    

    in the <head> section of the .html file.

    The DOM Elements

    The first thing you need to do is to create references to the elements that you want to manipulate in the DOM. In our case, they are the 14 plants currently waiting in the side bars.

    dragElement(document.getElementById('plant1'));
    dragElement(document.getElementById('plant2'));
    dragElement(document.getElementById('plant3'));
    dragElement(document.getElementById('plant4'));
    dragElement(document.getElementById('plant5'));
    dragElement(document.getElementById('plant6'));
    dragElement(document.getElementById('plant7'));
    dragElement(document.getElementById('plant8'));
    dragElement(document.getElementById('plant9'));
    dragElement(document.getElementById('plant10'));
    dragElement(document.getElementById('plant11'));
    dragElement(document.getElementById('plant12'));
    dragElement(document.getElementById('plant13'));
    dragElement(document.getElementById('plant14'));
    

    What's going on here? You are referencing the document and looking through its DOM to find an element with a particular Id. You can see in the HTML file on the left-most panel that each img is labeled with the class=plant and id=plant1 through id=plant14 respectively. With the above code you are calling .getElementByID(...) from the DOM module called document. We pass that item to the dragElement function that we will build in a minute.

    The Closure

    Now you are ready to create the dragElement closure, which is an outer function that encloses an inner function or functions (in our case, we will have three).

    Closures are useful when one or more functions need to access an outer function's scope. Here's an example:

    function displayCandy(){
    	let candy = ['jellybeans'];
    	function addCandy(candyType) {
    		candy.push(candyType)
    	}
    	addCandy('gumdrops');
    }
    displayCandy();
    console.log(candy)
    

    In this example, the displayCandy function surrounds a function that pushes a new candy type into an array that already exists in the function. If you were to run this code, the candy array would be undefined, as it is a local variable (local to the closure).

    How can you make the candy array accessible? Try moving it outside the closure. This way, the array becomes global, rather than remaining only available to the closure's local scope.

    Under the element declarations in script.js, create a function:

    function dragElement(terrariumElement) {
    	//set 4 positions for positioning on the screen
    	let pos1 = 0,
    		pos2 = 0,
    		pos3 = 0,
    		pos4 = 0;
    	terrariumElement.onpointerdown = pointerDrag;
    }
    

    dragElement get its terrariumElement object from the declarations at the top of the script. Then, you set some local positions at 0 for the object passed into the function. These are the local variables that will be manipulated for each element as you add drag and drop functionality within the closure to each element. The terrarium will be populated by these dragged elements, so the application needs to keep track of where they are placed.

    JavaScript events

    In addition, the terrariumElement that is passed to this function is assigned a pointerdown event, which is part of the web APIs designed to help with DOM management. onpointerdown fires when a button is pushed, or in our case, a draggable element is touched. This event handler works on both web and mobile browsers, with a few exceptions.

    The event handler onclick has much more support cross-browser; why wouldn't you use it here? Think about the exact type of screen interaction you're trying to create here.

    The pointerdrag Function

    The terrariumElement is ready to be dragged around; when the onpointerdown event is fired, the function pointerDrag is invoked. Add that function right under this line: terrariumElement.onpointerdown = pointerDrag;:

    function pointerDrag(e) {
    	e.preventDefault();
    	console.log(e);
    	pos3 = e.clientX;
    	pos4 = e.clientY;
    }
    

    Several things happen. First, you prevent the default events that normally happen on pointerdown from occurring by using e.preventDefault();. This way you have more control over the interface's behavior.

    Second, right click on one plant in your browser and select Inspect Element then click on console. When you click a plant, you can see how the 'e' event is captured. Dig into the event to see how much information is gathered by one pointer down event!

    Next, note how the local variables pos3 and pos4 are set to e.clientX. You can find the e values in the inspection pane. These values capture the x and y coordinates of the plant at the moment you click on it or touch it. You will need fine-grained control over the behavior of the plants as you click and drag them, so you keep track of their coordinates.

    Is it becoming more clear why this entire app is built with one big closure? If it wasn't, how would you maintain scope for each of the 14 draggable plants?

    Complete the initial function by adding two more pointer event manipulations under pos4 = e.clientY:

    document.onpointermove = elementDrag;
    document.onpointerup = stopElementDrag;
    

    Now you are indicating that you want the plant to be dragged along with the pointer as you move it, and for the dragging gesture to stop when you deselect the plant. onpointermove and onpointerup are all parts of the same API as onpointerdown. The interface will throw errors now as you have not yet defined the elementDrag and the stopElementDrag functions, so build those out next.

    The elementDrag and stopElementDrag Functions

    You will complete your closure by adding two more internal functions that will handle what happens when you drag a plant and stop dragging it. The behavior you want is that you can drag any plant at any time and place it anywhere on the screen. This interface is quite un-opinionated (there is no drop zone for example) to allow you to design your terrarium exactly as you like it by adding, removing, and repositioning plants.

    Add the elementDrag function right after the closing curly bracket of pointerDrag:

    function elementDrag(e) {
    	pos1 = pos3 - e.clientX;
    	pos2 = pos4 - e.clientY;
    	pos3 = e.clientX;
    	pos4 = e.clientY;
    	console.log(pos1, pos2, pos3, pos4);
    	terrariumElement.style.top = terrariumElement.offsetTop - pos2 + 'px';
    	terrariumElement.style.left = terrariumElement.offsetLeft - pos1 + 'px';
    }
    

    In this function, you do a lot of editing of the initial positions 1-4 that you set as local variables in the outer function. What's going on here?

    As you drag, you reassign pos1 by making it equal to pos3 (which you set earlier as e.clientX) minus the current e.clientX value. You do a similar operation to pos2. Then, you reset pos3 and pos4 to the new X and Y coordinates of the element. You can watch these changes in the console as you drag. Then, you manipulate the plant's css style to set its new position based on the new positions of pos1 and pos2, calculating the plant's top and left X and Y coordinates based on comparing its offset with these new positions.

    offsetTop and offsetLeft are CSS properties that set an element's position based on that of its parent; its parent can be any element that is not positioned as static.

    All this recalculation of positioning allows you to fine-tune the behavior of the terrarium and its plants.

    Final Task

    The final task to complete the interface is to add the stopElementDrag function after the closing curly bracket of elementDrag:

    function stopElementDrag() {
    	document.onpointerup = null;
    	document.onpointermove = null;
    }
    

    This small function resets the onpointerup and onpointermove events so that you can either restart your plant's progress by starting to drag it again, or start dragging a new plant.

    Now you have compoleted your terrarium!

    Completed Terrarium Photo

    Solution: https://codepen.io/rommelnunez/pen/OJmxbyw

    Advanced JavaScript Features


    Anonymous functions

    An anonymous function is a function without a name. An anonymous function is often not accessible after its initial creation.

    The following shows an anonymous function that displays a message:

    let show = function () {
        console.log('Anonymous function');
    };
    
    show();
    

    In this example, the anonymous function has no name between the function keyword and parentheses ().

    Because we need to call the anonymous function later, we assign the function to the show variable.

    Using anonymous functions as arguments of other functions

    We often use anonymous functions as arguments of other functions. For example:

    setTimeout(function () {
        console.log('Execute later after 1 second')
    }, 1000);
    

    In this example, we pass an anonymous function into the setTimeout() function. The setTimeout() function executes this anonymous function one second later.

    Immediately invoked function execution

    If you want to create a function and execute it immediately after declaration, you can use the anonymous function like this:

    (function() {
        console.log('IIFE');
    })();
    

    This is how it works:

    • First, the following defines a function expression:
    (function () {
        console.log('Immediately invoked function execution');
    })
    
    • Second, the trailing parentheses () allow you to call the function:
    (function () {
        console.log('Immediately invoked function execution');
    })();
    
    • and sometimes, you may want to pass arguments into it, like this:
    let person = {
        firstName: 'John',
        lastName: 'Doe'
    };
    
    (function () {
        console.log(`${person.firstName} ${person.lastName}`);
    })(person);
    

    Arrow functions

    ES6 introduced arrow function expression that provides a shorthand for declaring anonymous functions. For example, this function:

    let show = function () {
        console.log('Anonymous function');
    };
    

    ...can be shortened using the following arrow function:

    let show = () => console.log('Anonymous function');
    

    Similarly, the following anonymous function:

    let add = function (a, b) {
        return a + b;
    };
    

    ...is equivalent to the following arrow function:

    let add = (a, b)  => a + b;   
    

    Homework

    If you have already done the work terrarium project in this chapter then you have finished the first part of the homework! Otherwise, start from the top of UNIT 3.3.

    Homework part 2

    The homework for this week is more open ended then usual. Now that you have learned about the different properties of the DOM and ways to manipulate it, add some dynamic capabilites to your website! Create a draggable title, change the color of text on click, make an interactive bio about yourself where a certain word changes every few seconds... The possiblities are endless.

    Chapter 4.1 — Tailwind CSS.


    Tailwind CSS is a recent and popular CSS framework that provides utility-based classes. That means that you shouldn't worry about establishing a design system or even creating classes anymore—all the necessary CSS classes you'll ever need are already created for you and follow a predetermined design system!

    Note for students in China

    The default Tailwind's website may not be available in China. However, there is a separate Chinese version of the exact same website that you can use to access documentation: https://docs.tailwindchina.com/.

    Installing Tailwind CSS

    Usually, websites are written using various web frameworks (which will be described in Lecture 11). Tailwind CSS is supposed to be integrated with those frameworks, and installing it takes a bit of effort—even for experienced web developers. The reason why it's hard to get Tailwind up and running is that it is a highly customizable framework with many features not covered in this class. That is why Tailwind itself depends on other plugins like PostCSS and autoprefixer. But we don't want you to worry about setting all of that infrastructure up. Luckily, Tailwind also ships in a simplified form via a CDN (Content Delivery Network). Setting it up in this way requires you to add only one attribute to the <head> of your HTML page:

    <link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet">
    

    This way of installing Tailwind has its disadvantages:

    • You can't customize Tailwind's default theme
    • You can't use any directives
    • You can't enable additional variants like group-focus
    • You can't install third-party plugins
    • You can't tree-shake (remove) unused styles

    However, we don't think you will need any of these features anyway. At least in this class, we haven't covered any of them as we don't believe they would be useful for you yet.

    Homework

    The best way to learn how to use Tailwind CSS is to put it to practice. For this homework, we would like you to work on the website that you've been setting up in Unit 1 and designing in Unit 2. Specifically, we want you to implement all components of your website that you want to have included in your final website. Don't worry about the layout yet—feel free to just stack everything in vertically. We will learn more about layout and positioning of the elements in the next and final lecture.

    For example, if you are building a website about yourself, you may have designed a simple webpage that has your photo, your name, your background, perhaps a list of your projects organized as cards, and a list of your interests. In this homework, we want you to build these HTML elements. However, you shouldn't worry about positioning them on the screen yet—you will actually position the elements on the website in the next homework. After that, you will deploy it online!

    For this homework, we also want you to consult Tailwind's documentation very often. It's not possible to memorize all Tailwind classes, so you should feel free to search up what you need in the documentation. In fact, you are encouraged to do so!

    You might also find Tailwind CSS IntelliSense plugin—which you set up in the very first homework—very useful for this assignment. Make sure you have it!

    Commit and push to Github

    As you work on this homework, don't forget to commit often. Once you implement everything that's required, push it to Github!

    Chapter 4.2 — Layout, Positioning, and Responsive Design.

    In this lecture, you have learned about positioning elements on the screen and organizing them into containers: block (default), inline-block, flex, and grid. By now, you have all the skills you need to build a website—congrats!

    Homework

    You are on the finishing line! By now, you should have a design for your website and all its elements. In this homework, your job is to position them on the screen and add responsive utilities. Most often, you will need to use Flexbox utilities to set up your containers. Feel free to consult the slides, Tailwind's documentation, search engines, and other websites as you are completing this homework. Once you do this, you should have an almost completed version of your website. Commit and push it to Github!

    If you run out of time, you will have a bit of time during the office hours to keep working. However, we encourage to try your very best to complete so that if you get stuck on something you can clarify it with us during the office hours!

    Deploying Your Website

    Once you have built the website and published all the code to Github, you can deploy it online! There are many ways to do that. For example, in the US, you can use Cloudflare Pages (also available in China), Netlify, and Vercel, among other services. However, the easiest way to host your website is to use Github Pages—a free webpage hosting from Github that serves content directly from your repository! Here is how to do it:

    Step 1: Rename your repository

    In order to have the simplest possible experience and a nice looking domain name, rename your Github repository to <your-github-username>.github.io.

    Step 2: Enable Pages in the settings

    Go to the "Settings" tab of your repository (should be available at https://github.com/<your-github-username>/<your-repository-name>/settings/pages; make sure to replace the placeholders with your Github handle and repository name). Then, on the left panel, click "Pages". In the newly opened tab, select the source by choosing the "main" branch. A new selection should appear, set by default to "root"—leave it as that. Now, click "Save". The page should refresh and indicate that the website is currently building.

    Step 3: Wait for a few minutes

    Now, wait for a few minutes (this may take up to 20 minutes). If you've set up everything properly, your website should be available to anyone on the Internet at https://<your-github-username>.github.io/.

    For your reference, here is the official guide on deploying your website to Github Pages: https://docs.github.com/en/pages/getting-started-with-github-pages/creating-a-github-pages-site.

    Alternative option

    If, for some reason, you don't want to use Github Pages, another simple way to publish your website online is to use Cloudflare Pages. For that, you would need to register an account, link your Github account, choose your repository (you don't have to rename it in this case), and publish it. Feel free to follow this tutorial to proceed: https://developers.cloudflare.com/pages/getting-started. Note that, in this case, you will have a different domain name. However, you can purchase a new one using Cloudflare Registrar and connect it to your Cloudflare Pages deployment. You don't need to do that, though.