Front End Web Development: The Big Nerd Ranch Guide (opal Opal Parris' Library) (Big Guides) Chris Aquino, Todd Gandee Development Gu

User Manual: Pdf

Open the PDF directly: View PDF PDF.
Page Count: 576

DownloadFront-End Web Development: The Big Nerd Ranch Guide (opal Opal Parris' Library) (Big Guides) Chris Aquino, Todd Gandee-Front-End Development Gu
Open PDF In BrowserView PDF
Front-End Web Development: The Big
Nerd Ranch Guide
by Chris Aquino and Todd Gandee
Copyright © 2016 Big Nerd Ranch, LLC
All rights reserved. Printed in the United States of America. This publication is protected
by copyright, and permission must be obtained from the publisher prior to any prohibited
reproduction, storage in a retrieval system, or transmission in any form or by any means,
electronic, mechanical, photocopying, recording, or likewise. For information regarding
permissions, contact
Big Nerd Ranch, LLC
200 Arizona Ave NE
Atlanta, GA 30307
(770) 817-6373
The 10-gallon hat with propeller logo is a trademark of Big Nerd Ranch, LLC.
Exclusive worldwide distribution of the English edition of this book by
Pearson Technology Group
800 East 96th Street
Indianapolis, IN 46240 USA
The authors and publisher have taken care in writing and printing this book but make no
expressed or implied warranty of any kind and assume no responsibility for errors or
omissions. No liability is assumed for incidental or consequential damages in connection
with or arising out of the use of the information or programs contained herein.
Many of the designations used by manufacturers and sellers to distinguish their products
are claimed as trademarks. Where those designations appear in this book, and the
publisher was aware of a trademark claim, the designations have been printed with initial
capital letters or in all capitals.
ISBN-10 0134432533
ISBN-13 978-0134432533

First edition, first printing, July 2016
Release E.1.1.1

To Mom and Dad, for buying us that computer. To Dave and Glenn, for letting your
little brother completely hog it. And to Angela, for giving me a life away from the
— C.A.

To my mom and dad, thank you for giving me room to find my own way. To my wife,
thank you for loving a nerd.
— T.G.

As authors, we can take full credit for typing the words and creating the diagrams. (Yay,
us!) But the whole truth is that we would still be staring at a blank page if not for the
efforts of an army of contributors, collaborators, and mentors.
Aaron Hillegass, for believing that the two of us could produce a work worthy of
the Big Nerd Ranch name. Thank you for your immeasurable faith and support.
Matt Mathias, for guiding us through the development of this book, especially
during the crucial last mile. You made sure that time that would have been spent
watching cat videos or Downton Abbey reruns was instead dedicated to writing.
Brandy Porter, for the care and (literal) feeding of the authors on numerous
occasions. You worked your magic behind the curtain, orchestrating a sequence
of events that made finishing this work possible. Thank you.
Jonathan Martin, our coinstructor and language maven. Thank you for
enthusiastically teaching the in-progress course materials on which this book is
based and offering thoughtful criticism throughout the many revisions.
Our proofreaders, technical reviewers, and guinea pigs: Mike Zornek, Jeremy
Sherman, Josh Justice, Jason Reece, Garry Smith, Andrew Jones, Stephen
Christopher, and Bill Phillips. Thank you for volunteering as tribute.
Elizabeth Holaday, our infinitely patient and reassuring editor. Thank you for
breaking us out of the echo chamber, being the voice of reason, and reminding us
always of our readers.
Ellie Volckhausen, who designed our cover.
Simone Payment, our proofreader, who kept things consistent.
Chris Loper at, who designed and produced the print and
ebook versions of the book. His DocBook toolchain made life much easier, too.
Lastly, thank you to the countless students who have taken the week-long training.
Without your curiosity and your questions, none of this matters. This work is a reflection
of the insight and inspiration you have given us over the span of those many weeks. We
hope the otters made the training a little lighter.

Table of Contents
Learning Front-End Web Development
How This Book Is Organized
How to Use This Book
For the More Curious
Using an eBook
I. Core Browser Programming
1. Setting Up Your Development Environment
Installing Google Chrome
Installing and Configuring Atom
Atom plug-ins
Documentation and Reference Sources
Crash Course in the Command Line
Finding out what directory you are in
Creating a directory
Changing directories
Listing files in a directory
Getting administrator privileges
Quitting a program
Installing Node.js and browser-sync
For the More Curious: Alternatives to Atom
2. Setting Up Your First Project
Setting Up Ottergram
Initial HTML
Linking a stylesheet
Adding content

Adding images
Viewing the Web Page in the Browser
The Chrome Developer Tools
For the More Curious: CSS Versions
For the More Curious: The favicon.ico
Silver Challenge: Adding a favicon.ico
3. Styles
Creating a Styling Baseline
Preparing the HTML for Styling
Anatomy of a Style
Your First Styling Rule
The box model
Style Inheritance
Making Images Fit the Window
Adjusting the Space Between Items
Relationship selectors
Adding a Font
Bronze Challenge: Color Change
For the More Curious: Specificity! When Selectors Collide…
4. Responsive Layouts with Flexbox
Expanding the Interface
Adding the detail image
Horizontal layout for thumbnails
Creating a flex container
Changing the flex-direction
Grouping elements within a flex item
The flex shorthand property
Ordering, justifying, and aligning flex items
Centering the detail image

Absolute and Relative Positioning
5. Adaptive Layouts with Media Queries
Resetting the Viewport
Adding a Media Query
Bronze Challenge: Portrait
For the More Curious: Common Solutions (and Bugs) with Flexbox
Gold Challenge: Holy Grail Layout
6. Handling Events with JavaScript
Preparing the Anchor Tags for Duty
Your First Script
Overview of the JavaScript for Ottergram
Declaring String Variables
Working in the Console
Accessing DOM Elements
Writing the setDetails Function
Accepting arguments by declaring parameters
Returning Values from Functions
Adding an Event Listener
Accessing All the Thumbnails
Iterating Through the Array of Thumbnails
Silver Challenge: Link Hijack
Gold Challenge: Random Otters
For the More Curious: Strict Mode
For the More Curious: Closures
For the More Curious: NodeLists and HTMLCollections
For the More Curious: JavaScript Types
7. Visual Effects with CSS
Hiding and Showing the Detail Image
Creating styles to hide the detail image
Writing the JavaScript to hide the detail image
Listening for the keypress event

Showing the detail image again
State Changes with CSS Transitions
Working with the transform property
Adding a CSS transition
Using a timing function
Transition on class change
Triggering transitions with JavaScript
Custom Timing Functions
For the More Curious: Rules for Type Coercion
II. Modules, Objects, and Forms
8. Modules, Objects, and Methods
The module pattern
Modifying an object with an IIFE
Setting Up CoffeeRun
Creating the DataStore Module
Adding Modules to a Namespace
A constructor’s prototype
Adding methods to the constructor
Creating the Truck Module
Adding orders
Removing orders
Locating bugs with the DevTools
Setting the value of this with bind
Initializing CoffeeRun on Page Load
Creating the Truck instance
Bronze Challenge: Truck ID for Non-Trekkies
For the More Curious: Private Module Data
Silver Challenge: Making data Private

For the More Curious: Setting this in forEach’s Callback
9. Introduction to Bootstrap
Adding Bootstrap
How Bootstrap works
Creating the Order Form
Adding text input fields
Offering choices with radio buttons
Adding a dropdown menu
Adding a range slider
Adding Submit and Reset buttons
10. Processing Forms with JavaScript
Creating the FormHandler Module
Introduction to jQuery
Importing jQuery
Configuring instances of FormHandler with a selector
Adding the submit Handler
Extracting the data
Accepting and calling a callback
Using FormHandler
Registering createOrder as a submit handler
UI Enhancements
Bronze Challenge: Supersize It
Silver Challenge: Showing the Value as the Slider Changes
Gold Challenge: Adding Achievements
11. From Data to DOM
Setting Up the Checklist
Creating the CheckList Module
Creating the Row Constructor
Creating DOM elements with jQuery
Creating CheckList Rows on Submit
Manipulating this with call

Delivering an Order by Clicking a Row
Creating the CheckList.prototype.removeRow method
Removing overwritten entries
Writing the addClickHandler method
Calling addClickHandler
Bronze Challenge: Adding the Strength to the Description
Silver Challenge: Color Coding by Flavor Shot
Gold Challenge: Allowing Order Editing
12. Validating Forms
The required Attribute
Validating with Regular Expressions
Constraint Validation API
Listening for the input event
Associating the validation check with the input event
Triggering the validity check
Styling Valid and Invalid Elements
Silver Challenge: Custom Validation for Decaf
For the More Curious: The Webshims Library
13. Ajax
XMLHttpRequest Objects
RESTful Web Services
The RemoteDataStore Module
Sending Data to the Server
Using jQuery’s $.post method
Adding a callback
Inspecting the Ajax request and response
Retrieving Data from the Server
Inspecting the response data
Adding a callback argument
Deleting Data from the Server
Using jQuery’s $.ajax method

Replacing DataStore with RemoteDataStore
Silver Challenge: Validating Against the Remote Server
For the More Curious: Postman
14. Deferreds and Promises
Promises and Deferreds
Returning Deferred
Registering Callbacks with then
Handling Failures with then
Using Deferreds with Callback-Only APIs
Giving DataStore a Promise
Creating and returning Promises
Resolving a Promise
Promise-ifying the other DataStore methods
Silver Challenge: Fallback to DataStore
III. Real-Time Data
15. Introduction to Node.js
Node and npm
npm init
npm scripts
Hello, World
Adding an npm Script
Serving from Files
Reading a file with the fs module
Working with the request URL
Using the path module
Creating a custom module
Using your custom module
Error Handling
For the More Curious: npm Module Registry
Bronze Challenge: Creating a Custom Error Page
For the More Curious: MIME Types

Silver Challenge: Providing a MIME Type Dynamically
Gold Challenge: Moving Error Handling to Its Own Module
16. Real-Time Communication with WebSockets
Setting Up WebSockets
Testing Your WebSockets Server
Creating the Chat Server Functionality
First Chat!
For the More Curious: WebSockets Library
For the More Curious: WebSockets as a Service
Bronze Challenge: Am I Repeating Myself?
Silver Challenge: Speakeasy
Gold Challenge: Chat Bot
17. Using ES6 with Babel
Tools for Compiling JavaScript
The Chattrbox Client Application
First Steps with Babel
Class syntax
Using Browserify for Packaging Modules
Running the build process
Adding the ChatMessage Class
Creating the ws-client Module
Connection handling
Handling events and sending messages
Sending and echoing a message
For the More Curious: Compiling to JavaScript from Other Languages
Bronze Challenge: Default Import Name
Silver Challenge: Closed Connection Alert
For the More Curious: Hoisting
For the More Curious: Arrow Functions
18. ES6, the Adventure Continues
Installing jQuery as a Node Module

Creating the ChatForm Class
Connecting ChatForm to the socket
Creating the ChatList Class
Using Gravatars
Prompting for Username
User Session Storage
Formatting and Updating Message Timestamps
Bronze Challenge: Adding Visual Effects to Messages
Silver Challenge: Caching Messages
Gold Challenge: Separate Chat Rooms
IV. Application Architecture
19. Introduction to MVC and Ember
Ember: An MVC Framework
Installing Ember
Creating an Ember application
Starting up the server
External Libraries and Addons
For the More Curious: npm and Bower Install
Bronze Challenge: Limiting Imports
Silver Challenge: Adding Font Awesome
Gold Challenge: Customizing the NavBar
20. Routing, Routes, and Models
ember generate
Nesting Routes
Ember Inspector
Assigning Models
For the More Curious: setupController and afterModel
21. Models and Data Binding

Model Definitions
get and set
Computed Properties
For the More Curious: Retrieving Data
For the More Curious: Saving and Destroying Data
Bronze Challenge: Changing the Computed Property
Silver Challenge: Flagging New Sightings
Gold Challenge: Adding Titles
22. Data – Adapters, Serializers, and Transforms
Content Security Policy
For the More Curious: Ember CLI Mirage
Silver Challenge: Content Security
Gold Challenge: Mirage
23. Views and Templates
Loops with {{#each}}
Binding element attributes
Custom Helpers
Bronze Challenge: Adding Link Rollovers
Silver Challenge: Changing the Date Format
Gold Challenge: Creating a Custom Thumbnail Helper
24. Controllers
New Sightings

Editing a Sighting
Deleting a Sighting
Route Actions
Bronze Challenge: Sighting Detail Page
Silver Challenge: Sighting Date
Gold Challenge: Adding and Removing Witnesses
25. Components
Iterator Items as Components
Components for DRY Code
Data Down, Actions Up
Class Name Bindings
Data Down
Actions Up
Bronze Challenge: Customizing the Alert Message
Silver Challenge: Making the NavBar a Component
Gold Challenge: Array of Alerts
26. Afterword
The Final Challenge
Shameless Plugs
Thank You

Learning Front-End Web Development
Doing front-end web development may require a shift in perspective, as it is a very
different animal from development for other platforms. Here are a few things to keep in
mind as you are learning.
The browser is a platform.
Perhaps you have done native development for iOS or Android; written server-side code
in Ruby or PHP; or built desktop applications for OS X or Windows. As a front-end
developer, your code will target the browser – a platform available on nearly every phone,
tablet, and personal computer in the world.
Front-end development runs along a spectrum.
At one end of the spectrum is the look and feel of a web page: rounded corners, shadows,
colors, fonts, whitespace, and so on. At the other end of the spectrum is the logic that
governs the intricate behaviors of that web page: swapping images in an interactive photo
gallery, validating data entered into a form, sending messages across a chat network, etc.
You will need to become proficient with the core technologies all along this spectrum, and
you will often need to use multiple technologies in synergy to create a good web
Web technologies are open.
There is no one company that controls how browsers should work. That means that frontend developers do not get a yearly SDK release that contains all the changes they will
need to deal with for the next twelve months. Native platforms are a frozen pond on which
you can comfortably skate. The web is a river; it curves, moves quickly, and is rocky in
some places – but that is part of its appeal. The web is the most rapidly evolving platform
available. Adapting to change is a way of life for a front-end developer.
This book’s purpose is to teach you how to develop for the browser. As you follow this
guide, you will be taken through the process of building a series of projects. Each project
will call for a different mixture of technologies along the front-end spectrum. Because of
the sheer number of front-end tools, libraries, and frameworks available, this book will
focus on the most essential and portable patterns and techniques.

This book is not an introduction to programming. It assumes you have experience with the
fundamentals of writing code. You are expected to be familiar with basic types, functions,
and objects.
That said, it also does not assume you already know JavaScript. It introduces you to
JavaScript concepts in context, as you need them.

How This Book Is Organized
This book walks you through writing four different web applications. Each application has
its own section of the book. Each chapter in a section adds new features to the application
you are building.
Doing the work of building these four applications takes you from one extreme of the
front-end spectrum to the other.
Ottergram In your first project, you will create a web-based photo gallery. Building
Ottergram will teach you the fundamentals of programming for the
browser using HTML, CSS, and JavaScript. You will build the user
interface manually, learning how the browser loads and renders content.
CoffeeRun Part coffee order form, part checklist, CoffeeRun takes you through a
number of JavaScript techniques including writing modular code, taking
advantage of closures, and communicating with a remote server using
Ajax. Your focus will shift from manually creating the UI to creating and
manipulating it programmatically.
Chattrbox Chattrbox has the shortest section and is the most distinct of the apps. You
will use JavaScript to build a chat system, writing a chat server with
Node.js as well as a browser-based chat client.

Your final project uses Ember.js, one of the most powerful frameworks for
front-end development. You will create an application that catalogs
sightings of rare, exotic, and mythical creatures. Along the way, you will
learn your way around the rich ecosystem that powers the Ember.js

As you work through these applications, you will be introduced to a number of tools,
the Atom text editor and some useful plug-ins for working with code
documentation resources like the Mozilla Developer Network
the command line, using the OS X Terminal app or the Windows command prompt
Google Chrome’s Developer Tools

jQuery and libraries like crypto-js and moment
Node.js, the Node package manager (npm), and nodemon
WebSockets and the wscat module
Babel, Babelify, Browserify, and Watchify
Ember.js and addons like Ember CLI, Ember Inspector, Ember CLI Mirage, and

How to Use This Book
This book is not a reference book. Its goal is to get you over the initial hump to where you
can get the most out of the reference and recipe books available. It is based on our fiveday class at Big Nerd Ranch, and, as such, it is meant to be worked through from the
beginning. Chapters build on each other, and skipping around would be unproductive.
In our classes, students work through these materials, but they also benefit from the right
environment – a dedicated classroom, good food and comfortable board, a group of
motivated peers, and an instructor to answer questions.
As a reader, you want your environment to be similar. That means getting a good night’s
rest and finding a quiet place to work. These things can help, too:
Start a reading group with your friends or coworkers.
Arrange to have blocks of focused time to work on chapters.
Participate in the forum for this book at,
where you can discuss the book and find errata and solutions.
Find someone who knows front-end web development to help you out.

Most chapters in this book end with at least one challenge. Challenges are opportunities to
review what you have learned and take your work in the chapter one step further. We
recommend that you tackle as many of them as you can to cement your knowledge and
move from learning JavaScript development from us to doing JavaScript development on
your own.
Challenges come in three levels of difficulty:
Bronze challenges typically ask you to do something very similar to what you did
in the chapter. These challenges reinforce what you learned in the chapter and
force you to type in similar code without having it laid out in front of you.
Practice makes perfect.
Silver challenges require you to do more digging and more thinking. Sometimes
you will need to use functions, events, markup, and styles that you have not seen
before, but the tasks are still similar to what you did in the chapter.
Gold challenges are difficult and can take hours to complete. They require you to
understand the concepts from the chapter and then do some quality thinking and
problem solving on your own. Tackling these challenges will prepare you for the
real-world work of JavaScript development.
You should make a copy of your code before you work on the challenges for any chapter.
Otherwise, the changes that you make may not be compatible with subsequent exercises.
If you get lost, you can always visit for some

For the More Curious
Many chapters also have “For the More Curious” sections. These sections offer deeper
explanations or additional information about topics presented in the chapter. The
information in these sections is not absolutely essential, but we hope you will find it
interesting and useful.

Using an eBook
If you are reading this book on a eReader, reading the code may be tricky at times. Longer
lines of code may wrap to a second line, depending on your selected font size.
The longest lines of code in this book are 86 monospace characters, like this one.

You can play with your eReader’s settings to find the best for viewing long code lines.
If you are reading on an iPad with iBooks, we recommend you go to the Settings app,
select iBooks, and set Full Justification OFF and Auto-hyphenation OFF.
When you get to the point where you are actually typing in code, we suggest opening the
book on your Mac (or PC) in Adobe Digital Editions. (Adobe Digital Editions is a free
eReader application you can download from​products/​
digitaleditions.) Make the application window large enough so that you can see
the code with no wrapping lines. You will also be able to see the figures in full detail.

Part I
Core Browser Programming

Setting Up Your Development
There are countless tools and resources for front-end development, with more being built
all the time. Choosing the best ones is challenging for developers of all skill levels.
Throughout the projects in this book, we will guide you in the use of some of our
To get started, you will need three basic tools: a browser, a text editor, and good reference
documentation for the many technologies used in front-end development. Also, there are
several extras that – while not essential – will make your development experience
smoother and more enjoyable.
For the purposes of this book we recommend that you use the same software we use to get
the most benefit from our directions and screenshots. This chapter walks you through
installing and configuring the Google Chrome browser, the Atom text editor, Node.js, and a
number of plug-ins and extras. You will also find out about good documentation options
and get a crash course in using the command line on Mac and Windows. In the next
chapter, you will put all these resources to use as you begin your first project.

Installing Google Chrome
Your computer should already have a browser installed by default, but the best one to use
for front-end development is Google Chrome. If you do not already have the latest version of
Chrome, you can get it from​
(Figure 1.1).

Figure 1.1 Downloading Google Chrome

Installing and Configuring Atom
Of the many text editor programs out there, one of the best for front-end development is
the Atom editor by GitHub. It is a good choice because it is highly configurable, has many
plug-ins to help with writing code, and is free to download and use.
You can download Atom for Mac or Windows from (Figure 1.2).
Figure 1.2 Downloading Atom

Follow the installation instructions for your platform. After Atom is installed, there are
several plug-ins you will want to install as well.

Atom plug-ins
The primary things you want out of your text editor are documentation lookup,
autocompletion, code formatting, and code linting (more on that in a bit). Atom gives you
some of these features by default, but installing a few plug-ins will make it even better.
Open Atom and reveal its Settings screen. On a Mac, this is done by choosing Atom →
Preferences… or using the keyboard shortcut Command-, (that is, the Command key plus
the comma). On Windows, you can access it via File → Settings or using the keyboard
shortcut Ctrl-,.
On the lefthand side of the Settings screen, click + Install (Figure 1.3).

Figure 1.3 Atom’s Install Packages screen

Here, you can search for plug-in packages by name. Begin by searching for “emmet.”
Writing a lot of HTML can be very tedious and is error-prone. The emmet plug-in
(Figure 1.4) lets you write well-formatted HTML using a convenient shorthand. Click the
Install button to get emmet.
Figure 1.4 Installing emmet

Next, search for “atom-beautify.” The atom-beautify plug-in (Figure 1.5) helps with the
indentation of your code, which helps with readability. Again, click Install to get this plugin.
Figure 1.5 Installing atom-beautify

Search for and install the autocomplete-paths plug-in (Figure 1.6). Very often, your code will
need to refer to other files and folders in your project. This plug-in helps by offering
filenames in an autocomplete menu as you type.
Figure 1.6 Installing autocomplete-paths

Your next plug-in to install is the api-docs package (Figure 1.7), which lets you look up
documentation based on keyword. It displays the documentation in a separate tab in the
Figure 1.7 Installing api-docs

Next, search for and install the linter package (Figure 1.8). A linter is a program that checks
the syntax and style of your code. Make sure you find and install the package that is just
named “linter.” This is a base linter that works with language-specific plug-ins. You will
need it in order to use the other linter plug-ins below.
Figure 1.8 Installing linter

There are three companions to linter that you will want to install to check your CSS,
HTML, and JavaScript code. Start with linter-csslint (Figure 1.9), which ensures that your
CSS is syntactically correct and also offers suggestions about writing performant CSS.

Figure 1.9 Installing linter-csslint

The next linter companion plug-in to install is linter-htmlhint (Figure 1.10), which confirms
that your HTML is well formed. It will warn you about mismatched HTML tags.
Figure 1.10 Installing linter-htmlhint

The last linter companion plug-in to install is linter-eslint (Figure 1.11). This plug-in checks
the syntax of your JavaScript and can be configured to check the style and formatting of
your code (for example, how many spaces lines are indented or how many blank lines
come before and after comments).
Figure 1.11 Installing linter-eslint

and Atom are now ready for front-end development. There are just a few more steps
to completing your coding environment: accessing documentation, learning command-line
basics, and downloading two final tools.

Documentation and Reference Sources
Front-end development is different from programming for platforms like iOS and
Android. Aside from the obvious differences, front-end technologies have no official
developer documentation other than the technical specifications. This means that you will
need to look elsewhere for guidance. We recommend that you familiarize yourself with the
resources below and consult them regularly as you work through the book and continue on
with front-end development.
The Mozilla Developer Network (MDN) is the best reference for anything to do with
HTML, CSS, and JavaScript. One way to access it is, an excellent
documentation interface (Figure 1.12). It pulls documentation from MDN for core frontend technologies – and it can work offline, so you can check it even when you do not have
an internet connection.
Figure 1.12 Accessing documentation via

Note that Safari currently does not support the offline caching mechanism used by You will need to use a different browser, such as Chrome, to access it.
You can also use MDN’s website,​en-US (Figure 1.13),
or simply add “MDN” as a search engine keyword to find the information you need.

Figure 1.13 The Mozilla Developer Network website

Another site to know about is (Figure 1.14). Officially, this is
not a source of documentation. It is a place where developers can ask each other about
code. The answers vary in quality, but are often very thorough and quite helpful. So it is a
useful resource – as long as you bear in mind that the answers are not definitive, due to its
crowdsourced nature.
Figure 1.14 The Stack Overflow website

Web technologies are always changing. Support for features and APIs will vary from
browser to browser and over time. Two websites that can help you determine which
browsers (and which versions of individual browsers) support what features are and When you need information about feature
support, we suggest starting with to know whether a feature is
recommended for use. For more detailed information about which browser versions
support a specific feature, go to

Crash Course in the Command Line
Throughout this book, you will be instructed to use the command line or terminal. Many
of the tools you will be using run exclusively as command-line programs.
To access the command line on a Mac, open Finder and go to the Applications folder, then the
Utilities folder. Find and open the program named Terminal (Figure 1.15).
Figure 1.15 Finding the Terminal app on a Mac

You should see a window that looks like Figure 1.16.
Figure 1.16 Mac command line

To access the command line on Windows, go to the Start menu and search for “cmd.” Find
and open the program named Command Prompt (Figure 1.17).

Figure 1.17 Finding the Command Prompt program on Windows

Click it to run the standard Windows command-line interface, which looks like
Figure 1.18.
Figure 1.18 Windows command line

From now on, we will refer to “the terminal” or “the command line” to mean both the Mac
Terminal and the Windows Command Prompt. If you are unfamiliar with using the command
line, here is a short walkthrough of some common tasks. All commands are entered by
typing at the prompt and pressing the Return key.

Finding out what directory you are in
The command line is location based. That means that at any given time it is “in” a

particular directory within the file structure, and any commands you enter will be applied
within that directory. The command-line prompt shows an abbreviated version of the
directory it is in. To see the whole path on a Mac, enter the command pwd (which stands
for “print working directory”), as in Figure 1.19.
Figure 1.19 Showing the current path using pwd on a Mac

On Windows, use the command echo %cd% to see the path, as in Figure 1.20.
Figure 1.20 Showing the current path using echo %cd% on Windows

Creating a directory
The directory structure of front-end projects is important. Your projects can grow quickly,
and it is best to keep them organized from the beginning. You will create new directories
regularly during your development. This is done using the mkdir or “make directory”
command followed by the name of the new directory.
To see this command in action, set up a directory for the projects you will build as you
work through this book. Enter this command:

mkdir front-end-dev-book

Next, create a new directory for your first project, Ottergram, which you will begin in the
next chapter. You want this new directory to be a subdirectory of the front-end-devbook directory you just created. You can do this from your home directory by prefacing
the new directory name with the name of the projects directory and, on a Mac, a slash:
mkdir front-end-dev-book/ottergram

On Windows, you use the backslash instead:
mkdir front-end-dev-book\ottergram

Changing directories
To move around the file structure, you use the command cd, or “change directory,”
followed by the path of the directory you want to move into.
You do not always need to use the complete directory path in your cd command. For
example, to move down into any subdirectory of the directory you are in, you simply use
the name of the subdirectory. So when you are in the front-end-dev-book directory,
the path of the ottergram folder is just ottergram.
Move into your new project directory:
cd front-end-dev-book

Now, you can move into the ottergram directory:
cd ottergram

To move up to the parent directory, use the command cd .. (that is, cd followed by a
space and two periods). The pair of periods represents the path of the parent directory.
cd ..

Remember that you can check your current directory by using the pwd command (or echo
%cd% on Windows). Figure 1.21 shows the author creating directories, moving between
them, and checking the current directory.

Figure 1.21 Changing and checking directories

You are not limited to moving up or down one directory at a time. Let’s say that you had a
more complex directory structure, like the one shown in Figure 1.22.
Figure 1.22 An example file structure

Suppose you are in the ottergram directory and you want to go directly to the
stylesheets directory inside of coffeerun. You would do this with cd followed by
a path that means “the stylesheets directory inside the coffeerun directory inside
the parent directory of where I am now”:
cd ../coffeerun/stylesheets

On Windows, you would use the same command but with backslashes:
cd ..\coffeerun\stylesheets

Listing files in a directory

You may need to see a list of files in your current directory. On a Mac, you use the ls
command for that (Figure 1.23). If you want to list the files in another directory, you can
supply a path:
ls ottergram

Figure 1.23 Using ls to list files in a directory

By default, ls will not print anything if a directory is empty.
On Windows, the command is dir (Figure 1.24), which you can optionally give a path:
dir ottergram

Figure 1.24 Using dir to list files in a directory

By default, the dir command will print information about dates, times, and file sizes.

Getting administrator privileges
On some versions of OS X and Windows, you will need superuser or administrator
privileges in order to run some commands, such as commands that install software or
make changes to protected files.

On a Mac, you can give yourself privileges by prefixing a command with sudo. The first
time you use sudo on a Mac, it will give you a stern warning, shown in Figure 1.25.
Figure 1.25 sudo warning

will prompt you for your password before it runs the command as the superuser. As
you type, your keystrokes will not be echoed back, so type carefully.

On Windows, if you need to give yourself privileges you do so in the process of opening
the command-line interface. Find the command prompt in the Windows Start Menu, rightclick it, and choose Run as Administrator (Figure 1.26). Any commands you run in this
command prompt will be run as the superuser, so be careful.

Figure 1.26 Opening the command prompt as an administrator

Quitting a program
As you proceed through the book, you will run many apps from the command line. Some
of them will do their job and quit automatically, but others will run until you stop them. To
quit a command-line program, press Control-C.

Installing Node.js and browser-sync
There is one final set-up step before you begin your first project.
(or simply “Node”) lets you use programs written in JavaScript from the command
line. Most front-end development tools are written for use with Node.js. You will learn lots
more about Node.js in Chapter 15, but you will begin using one tool that depends on it,
browser-sync, right away.

Install Node by downloading the installer from (Figure 1.27). The version
of Node.js used in this book is 5.11.1, and you will likely see a different version available
for download.
Figure 1.27 Downloading Node.js

Double-click the installer and follow the prompts.
When you install Node, it provides two command-line programs: node and npm. The node
program does the work of running programs written in JavaScript. You will not need to
use it until Chapter 15. The other program is the Node package manager, npm, which is
needed for installing open-source development tools from the internet.
is one such tool, and it will be invaluable to you throughout the book. It
makes your example code easier to run in the browser and automatically reloads the
browser when you save changes to your code.

Install browser-sync using this command at the command line:
npm install -g browser-sync

(The -g in the command stands for “global.” Installing the package globally means that
you will be able to run browser-sync from any directory.)
It does not matter what directory you are in when you run this command, but you will
probably need superuser privileges. If that is the case, run the command using sudo on a

sudo npm install -g browser-sync

If you are on Windows, first open a command prompt as the administrator, as shown
When you start browser-sync, as you will in the next chapter, it will run until you press
Control-C. It is a good idea to quit browser-sync when you are done working on a project
for a while. That means that you will need to start browser-sync each time you begin
work on the first two projects in this book (Ottergram and CoffeeRun).
With that, you have the tools you need to get started on your Ottergram project!

For the More Curious: Alternatives to Atom
There are many, many text editors to choose from. If you are not that keen on Atom, when
you are done working through the projects in this book you may want to try out one of the
following two options. Both are available for free for Mac and Windows, and both have a
large number of plug-ins to customize your development experience. Also, like Atom, both
are built using HTML, CSS, and JavaScript, but run as desktop applications.
is Microsoft’s open source text editor, made specifically for developing
web applications. It can be downloaded from
(Figure 1.28).
Visual Studio Code

Figure 1.28 The Visual Studio Code website

Adobe’s Brackets text editor is particularly good for building user interfaces with HTML
and CSS. In fact, it provides an extension for helping you work with Adobe’s layered PSD
image files. Brackets is available from (Figure 1.29).

Figure 1.29 The Adobe Brackets website

Setting Up Your First Project
When you visit a website, your browser has a conversation with a server, another
computer on the internet.
Browser: “Hey there! Can I please have the contents of the file named catvideos.html?”
Server: “Certainly. Let me take a look around … here it is!”
Browser: “Ah, it’s telling me that I need another file named styles.css.”
Server: “Sure thing. Let me take a look around … here it is!”
Browser: “OK, that file says that I need another file named animatedbackground.gif.”
Server: “No problem. Let me take a look around … here it is!”
That conversation goes on for some time, sometimes lasting thousands of milliseconds
(Figure 2.1).
Figure 2.1 The browser sends a request, the server responds

It is the browser’s job to send requests to the server; interpret the HTML, CSS, and
JavaScript it receives in the response from the server; and present the result to the user.
Each of these three technologies plays a part in the user’s experience of a website. If your
app were a living creature, the HTML would be its skeleton and organs (the mechanics),
the CSS would be its skin (the visible layer), and the JavaScript would be its personality
(how it behaves).
In this chapter, you are going to set up the basic HTML for your first project, Ottergram.
In the next chapter, you will set up your CSS, which you will refine in Chapter 4. In
Chapter 6, you will begin adding JavaScript.

Setting Up Ottergram
In Chapter 1, you created a folder for the projects in this book as well as a folder for
Ottergram. Start your Atom text editor and open the ottergram folder by clicking File →
Open (or File → Open Folder… on Windows). In the dialog box, navigate to the frontend-dev-book folder and choose the ottergram folder. Click Open to tell Atom to use
this folder (Figure 2.2).
Figure 2.2 Opening your project folder in Atom

You will see the ottergram folder in the lefthand panel of Atom. This panel is for
navigating among the files and folders in your project.
You are going to create some files and folders within the ottergram project folder using
Atom. Control-click (right-click) ottergram in the lefthand panel and click New File in the
pop-up menu. You will be prompted for a name for the new file. Enter index.html and
press the Return key (Figure 2.3).

Figure 2.3 Creating a new file in Atom

You can use the same process to create folders using Atom. Control-click (right-click)
ottergram in the lefthand panel again, but this time click New Folder in the pop-up. Enter
the name stylesheets in the prompt that appears (Figure 2.4).
Figure 2.4 Creating a new folder in Atom

Finally, create a file named styles.css in the stylesheets folder: Control-click
(right-click) stylesheets in the lefthand panel and choose New File. The prompt will
pre-fill the text “stylesheets/”. After this, enter styles.css and press the Return key
(Figure 2.5).
Figure 2.5 Creating a new CSS file in Atom

When you are finished, your project folder should look like Figure 2.6.

Figure 2.6 Initial files and folders for Ottergram

There are no rules about how to structure your files and folders or what to name them.
However, Ottergram (like the other projects in this book) follows conventions used by
many front-end developers. Your index.html file will hold your HTML code. Naming
the main HTML file index.html dates back to the early days of the web, and the
convention continues today.
The stylesheets folder, as the name suggests, will hold one or more files with styling
information for Ottergram. These will be CSS, or “cascading style sheets,” files.
Sometimes developers give their CSS files names that describe what part of the page or
site they pertain to, such as header.css or blog.css. Ottergram is a simple project
and only needs one CSS file, so you have named it styles.css to reflect its global

Initial HTML
Time to get coding. Open index.html in Atom and add some basic HTML to get started.
Start by typing html. Atom will offer you an autocomplete option, as shown in Figure 2.7.
(If it does not, make sure you installed the emmet plug-in as directed in Chapter 1.)
Figure 2.7 Atom’s autocomplete menu

Press the Return key, and Atom will provide bare-bones HTML elements to get you started
(Figure 2.8).

Figure 2.8 HTML created using autocomplete

Your cursor is between  and  – the opening and closing title tags. Type
“ottergram” to give the project a name. Now, click to put your cursor in the blank line
between the opening and closing body tags. There, type “header” and press the Return key.
Atom will convert the text “header” into opening and closing header tags with a blank line
between them (Figure 2.9).
Figure 2.9 Header tag created with autocomplete

Next, type “h1” and press Return. Again, your text is converted into tags, this time without
a blank line. Enter the text “ottergram” again. This will be the heading that will appear on
your web page.
Your file should look like this:



and emmet have together saved you some typing and helped you build well-formed initial HTML. Atom Let’s examine your code. The first line, , defines the doctype – it tells the browser which version of HTML the document is written in. The browser may render, or draw, the page a little differently based the doctype. Here, the doctype specifies HTML5. Earlier versions of HTML often had long, convoluted, and hard to remember doctypes, such as: Often, folks had to look up the doctype each time they created a new document. With HTML5, the doctype is short and sweet. It is the one that will be used throughout all of the projects in this book, and you should use it for your apps. After the doctype is some basic HTML markup consisting of a head and a body. The head will hold information about the document and how the browser should handle the document. For example, the title of the document, what CSS or JavaScript files the page uses, and when the document was last modified are all included in the head. Here, the head contains a tag. tags provide the browser with information about the document itself, such as the name of the document’s author or keywords for search engines. The tag in Ottergram, , specifies that the document is encoded using the UTF-8 character set, which encompasses all Unicode characters. Use this tag in your documents so that the widest range of browsers can interpret them correctly, especially if you expect international traffic. The body will hold all of the HTML code that represents the content of your page: all the images, links, text, buttons, and videos that will appear on the page. Most tags enclose some other content. Take a look at the h1 heading you included; its anatomy is shown in Figure 2.10. Figure 2.10 Anatomy of a simple HTML tag HTML stands for “hypertext markup language.” Tags are used to “mark up” your content, designating their purpose – such as headings, list items, and links. The content enclosed by a set of tags can also include other HTML. Notice, for example, that the
tags enclose the

tag shown above (and the tags enclose the
!). There are a lot of tags to choose from – more than 140. To see a list of them, visit MDN’s HTML element reference, located at​en-US/​docs/​ Web/​HTML/​Element. This reference includes a brief description of each element and groups elements by usage (e.g., text content, content sectioning, or multimedia). Linking a stylesheet In Chapter 3, you will write styling rules in your stylesheet, styles.css. But remember the conversation between the browser and the server at the beginning of this chapter? The browser only knows to ask for a file from the server if it has been told that the file exists. You have to link to your stylesheet so that the browser knows to ask for it. Update the head of index.html with a link to your styles.css file. ottergram ... The tag is how you attach an external stylesheet to an HTML document. It has two attributes, which give the browser more information about the tag’s purpose (Figure 2.11). (The order of HTML attributes does not matter.) Figure 2.11 Anatomy of a tag with attributes You set the rel (or “relationship”) attribute to "stylesheet", which lets the browser know that the linked document provides styling information. The href attribute tells the browser to send a request to the server for the styles.css file located in the stylesheets folder. Note that this file path is relative to the current document. Save index.html before you move on. Adding content A web page without content is like a day without coffee. Add a list after your header to give your project a reason for living. You are going to add an unordered list (that is, a bulleted list) using the . You should end up with 10 list items, containing images otter1.jpg through otter5.jpg twice. Be sure to save index.html when you are done. Duplicating content while you are developing is a good technique for simulating a more robust project. It allows you to see how your code handles real-world situations. For a horizontally scrolling list of thumbnails, each thumbnail must be constrained to a specific width and the thumbnails should be laid out horizontally on a single line. The display: block property, which you have used several times, will not create the desired effect. It causes the browser to render a line break before and after the element. However, a related style, display: inline-block, is perfect for this situation. With inline-block, the element’s box is drawn as if you declared display: block, but without the line breaks – allowing your thumbnails to stay lined up in a row. Add a width declaration and change the display declaration for the .thumbnail-item class in styles.css. ... .thumbnail-item { display: block; display: inline-block; width: 120px; border: 1px solid rgb(100%, 100%, 100%, 0.8); border: 1px solid rgba(100%, 100%, 100%, 0.8); } ... (Note that Atom’s linter may warn you that “Using width with border can sometimes make elements larger than you expect.” This is because the width property only applies to the content portion – not the padding or border – of the element’s box. You do not need to do anything about this warning.) With the .thumbnail-item element’s width set to an absolute value of 120px, the .thumbnail-image is effectively fixed as well, since the .thumbnail-image adjusts to its container’s width. Why not just set the .thumbnail-image to width: 120px? You want the .thumbnailimage and the .thumbnail-title to be the same width. Instead of setting the width property for each of these, you set it on their common parent element. That way, if you need to change the width, you only need to change it in one place. Generally, it is a good practice to have inner elements adapt to their containers. Save styles.css and check your page in Chrome. You can see that the .thumbnailitem elements line up side by side – but when they fill the width of their container, they wrap around (Figure 4.4). Figure 4.4 inline-block creates rows that wrap To get the scrolling behavior you want, set .thumbnail-list to prevent wrapping and allow scrolling in styles.css. ... .thumbnail-list { list-style: none; padding: 0; white-space: nowrap; overflow-x: auto; } ... The white-space: nowrap declaration prevents the .thumbnail-item elements from wrapping. The overflow-x: auto tells the browser that it should add a scrollbar along the horizontal space (the x axis) of the .thumbnail-list element to accommodate content that overflows – i.e., does not fit within the .thumbnail-list. Without this declaration, you would have to scroll the entire web page to see the additional thumbnails. Save your file again and take a look at the results in your browser. The thumbnails are now in a single row, and you should be able to scroll through them horizontally (Figure 4.5). Figure 4.5 Horizontally scrolling thumbnails This is a good start to the enhanced Ottergram interface. It works just fine for some screen sizes. However, it is not perfect, because it does not adapt well to a wide range of sizes – especially those that are much larger or smaller than the computer you are currently using. In the next two sections, you will add code that gives Ottergram a more fluid layout and allows its UI - its user interface - to shift between different layouts to adapt to ranges of screen sizes. Flexbox You have seen display styles specifying the properties block and inline. Inline elements, like the thumbnail items in your newly scrolling list, are laid out next to one another, while block elements occupy their own horizontal line. Another way to think of this is that block elements flow from top to bottom and inline elements flow from left to right (Figure 4.6). Figure 4.6 Block vs inline elements The display property tells the browser how an element should flow in the layout. For blogs or online encyclopedias, the inline and block values work well. But for application-style layouts like web-based email and social media sites, there is a new CSS specification that allows elements to flow more dynamically. This is the flexible box model, or flexbox. Flexbox CSS properties can ensure that thumbnail and detail areas fill the screen and maintain their proportions relative to one another. This is exactly what you need for Ottergram. You can also use flexbox properties to center the contents of the detail area both horizontally and vertically, a task which is notoriously difficult using standard box model properties. Creating a flex container Before you add your first flexbox property, set your and elements to height: 100% in styles.css. The element is the root element of your DOM tree, with the as a child element drawn inside of it. Setting the height to 100% for both of them allows the content to fill the browser or device window. @font-face { ... } html, body { height: 100%; } body { font-size: 10px; background: rgb(149, 194, 215); } ... Notice that you have grouped two selectors, separated by a comma, in this styling rule. Selectors of any type can be combined in this way to set common styles. Notice also that you now have two styling rules with the body element selector. When the browser sees additional styling declarations for a selector, it simply adds to its existing styling information for that selector. In this case, it first sees that the should have a height of 100% and stores that information. When it reads the next styling rule for the , it stores the background and font-size information along with the height style. Now you are ready to create your first flex container. When an element is a flex container, it can control how its child elements (its flex items) are laid out. Inside a flex container, the size and placement of flex items occurs along the main axis and the cross axis (Figure 4.7). Figure 4.7 The main and cross axes of a flex container Make your element a flex container by adding a display: flex declaration to its styling rule in styles.css. ... body { display: flex; font-size: 10px; background: rgb(149, 194, 215); } ... If you saved now, your browser would display a rather sad-looking Ottergram, as in Figure 4.8. This is because the main axis goes from left to right, laying the flex items (all the children of the ) out in a row. Figure 4.8 Flex items laid out along the main axis However, you can see that the individual items shrink to accommodate the space, instead of wrapping. That is the first piece of good news. The second piece of good news is that you can fix the layout with just one style. (Well, almost.) Changing the flex-direction To fix the layout, set the element’s flex-direction to column in styles.css: ... body { display: flex; flex-direction: column; font-size: 10px; background: rgb(149, 194, 215); } ... This swaps the main and cross axes for the flex container, as illustrated in Figure 4.9. Figure 4.9 Main and cross axes with flex-direction: column After changing the flex-direction to column, Ottergram is back to normal – almost. There is a visual bug in the layout when the browser window is a lot wider than it is tall, shown in Figure 4.10. Figure 4.10 Missing thumbnails when the page is stretched wide You will remedy this by adding a wrapper element and applying new flexbox properties. Grouping elements within a flex item The has three flex items: the
, the .thumbnail-list, and the .detailimage-container. No matter what happens during the development (and use) of Ottergram, the
is not likely to change much in its layout or complexity. It is going to be at the top of the page, displaying text. That is about it. On the other hand, as you develop Ottergram the .thumbnail-list and .detail-imagecontainer and their contents may very well change in layout and complexity. Also, changes to one of these items are likely to affect the other. For these reasons, you are going to group the .thumbnail-list and the .detail-imagecontainer in their own flex container. To do this, you will wrap them in a
tag with a class name of .main-content (Figure 4.11). Figure 4.11 Wrapping the .thumbnail-list and .detail-image-container Make it so in index.html: Give the
element the class main-header, then wrap the .thumbnail-list (
    ) and the .detail-image-container (
    ) in a
    element with the class main-content. ...


    Stayin' Alive
    ... .main-header and .main-content are now the two flex items inside the . By wrapping the .thumbnail-list and .detail-image-container in the .main-content element, you are now free to declare a height for the
    , leaving the rest of the ’s vertical space for the .main-content to occupy. That way, the space inside of can be distributed to .thumbnail-list and .detail-image-container without affecting the header. .main-content Save index.html. Now that you have the markup for the two flex items inside the body, you can set their sizes relative to one another using the flex property. The flex shorthand property A flex container distributes its space to the flex items inside of it. If the flex items do not specify their size along the main axis, then the container distributes the space evenly based on the number of flex items, with each flex item getting the same share of space along the main axis. This is the default, illustrated in Figure 4.12. Figure 4.12 Equal distribution of space between three flex items But imagine that one of the three flex items in Figure 4.12 is a bit greedier than the others and claims two shares of the total space. In that case, the flex container divides the space along the main axis into four shares. The greedy item occupies two of them (half the space) and the other items get one share each (Figure 4.13). Figure 4.13 Unequal distribution of space between three flex items In Ottergram, you want the .main-content element to be the greedy element, taking up as much space along the main axis as possible. The .main-header, on the other hand, should take up as little space as possible. The flex property lets your flex items specify how much of the available space they will take up. It is a shorthand property, as shown in Figure 4.14. Figure 4.14 The flex shorthand property and its values We strongly recommend that you use flex instead of the individual properties it represents. It protects you from inadvertently leaving a property out and getting unexpected results. The first value is the one to focus on right now, as it determines how much the flex item can grow. By default flex items do not grow at all. You want that default behavior for your .main-header, but not your .main-content. In styles.css, add a declaration block for the .main-header class selector, specifying a flex shorthand property with default values: 0 1 auto. ... a { text-decoration: none; } .main-header { flex: 0 1 auto; } .logo-text { background: white; ... The value 0 1 auto can be read as, “I do not want to grow any larger; I will shrink as needed; please calculate my size for me.” The end result will be that the .main-header will take up only as much space as it needs, and no more. Next, add a declaration block for .main-content, setting its flex to 1 1 auto. ... .logo-text { ... } .main-content { flex: 1 1 auto; } .thumbnail-item + .thumbnail-item { ... The first value in .main-content’s flex declaration corresponds to the flex-grow property. A value of 1 tells the container, “I would like to grow as much as possible.” Because its only sibling has declared that it will not grow, the .main-content element will grow to take up all the space not needed for the .main-header. The ’s two flex items, the .main-header and the .main-content elements, occupy the flexible space according to their needs. Now it is time to adjust the layout of the .main-content element. Ordering, justifying, and aligning flex items Flexbox also allows you to subdivide flex items into flex containers. This technique lets you focus on the layers. In a moment, you are going to make your .main-content a flex container. Working with nested flex containers is an exception to the atomic styling approach to creating the look and feel of visual components. Instead of styling the smallest, innermost elements first and then working your way out to the largest elements, when working on a layout with flexbox it is more useful to start with the outermost elements and work your way in. Here is what you will tackle next. You will change the .main-content to a flex container with a vertical main axis. Also, you will specify the flex properties for .main-content’s flex items so that the .thumbnail-list takes the default amount of space and .detailimage-container grows to fill the space left over. Finally, you will move the .thumbnail-list below the .detail-image-container (Figure 4.15). Figure 4.15 Making .main-content a flex container Make these changes in styles.css by adding display: flex and flex-direction: column to .main-content’s declaration block, adding flex properties to .thumbnaillist’s declaration block, and writing a new declaration block for the .detail-imagecontainer class. ... .main-content { flex: 1 1 auto; display: flex; flex-direction: column; } ... .thumbnail-list { flex: 0 1 auto; list-style: none; padding: 0; white-space: nowrap; overflow-x: auto; } ... .thumbnail-title { ... } .detail-image-container { flex: 1 1 auto; } .detail-image { ... You might be wondering why you are not defining the heights of the .thumbnail-list and .detail-image-container boxes with percentages, the way you defined the width of the .detail-image. Setting the height of the .thumbnail-list at, for example, 25% and the .detail-image-wrapper at 75% seems logical – but it would not work the way you intend. The interaction with the width property of the .detail-image would result in the .detail-image-container being much too large, and the .thumbnail-list would end up either too small or too large, depending on the window size. In short, using the flex property to set the flex items’ sizes in conjunction with the one fixed size you care about – the width of the .detail-image – is the way to go. Now to move the thumbnail list below the detail image. By default, flex items are drawn in the order that they appear in the HTML. This is known as source order and is the main way that developers control the order in which elements are drawn. One option for moving the detail image up would be to cut and paste the markup for the detail image so that it came before the markup for the .thumbnail-list – to change the source order. However, it can also be done using a new flexbox property. To change the order using flexbox, add an order declaration to the .thumbnail-list selector in styles.css. ... .thumbnail-list { flex: 0 1 auto; order: 2; list-style: none; padding: 0; white-space: nowrap; overflow-x: auto; } ... The order property can be assigned any integer value. The default value is 0, which tells the browser to use the source order. Any other values, including negative numbers, tell the browser to draw a flex item before or after other flex items. Giving .thumbnail-list the declaration order: 2 tells the browser to draw it after any of its siblings that have a lower value for order – such as .detail-image-container, which is using the default. Save styles.css and switch to Chrome. You will see that the thumbnails are rendered along the bottom of the page (Figure 4.16). Figure 4.16 Changing the order elements are drawn Next, you will continue to apply display: flex as you work on the layout of the Ottergram UI. So far, you have worked with flex containers that hold only a couple of flex items. Make the .thumbnail-list a flex container so that you can further explore what flexbox can offer you. ... .thumbnail-list { flex: 0 1 auto; order: 2; display: flex; list-style: none; padding: 0; white-space: nowrap; overflow-x: auto; } ... Do not panic if you save your changes and see that the thumbnails are rendered oddly, as in Figure 4.17. Figure 4.17 Otters, askew To fix this, replace the .thumbnail-item’s width declaration with a pair of declarations, one for min-width and another for max-width. This will remove the variations in size that are causing the strange layout. You can also remove the declaration block that sets the margin-top for .thumbnail-item + .thumbnail-item elements. It is no longer needed for this layout. ... .thumbnail-item + .thumbnail-item { margin-top: 10px; } .thumbnail-item { display: inline-block; width: 120px; min-width: 120px; max-width: 120px; border: 1px solid rgb(100%, 100%, 100%); border: 1px solid rgba(100%, 100%, 100%, 0.8); } ... Next, you will work with the spacing of the flex items inside of .thumbnail-list. In styles.css, add a declaration for justify-content to the .thumbnail-list selector. ... .thumbnail-list { flex: 0 1 auto; order: 2; display: flex; justify-content: space-between; list-style: none; padding: 0; white-space: nowrap; overflow-x: auto; } ... The justify-content property lets a flex container control how flex items are drawn on the main axis. You used space-between as the value to make sure there is an even amount of spacing around each individual flex item. There are five different values you can specify for justify-content. Figure 4.18 illustrates how each of these values works. Figure 4.18 Values for the justify-content property You have tackled the layout of the .thumbnail-list. Next, you will work with the .detail-image-container and its contents. Centering the detail image The detail image should be Ottergram’s main focus. It should be front and center to make sure that the user is admiring the majesty of the otter. It should also be adorned with a snazzy title. To center the detail image, you will first wrap the image and its title in a container, then center the wrapper inside the .detail-image-container. This idea is illustrated in Figure 4.19. Figure 4.19 Framing the .detail-image and .detail-image-title While you could center the .detail-image itself inside the .detail-image-container, it would be difficult to correctly offset the .detail-image-title, because both the .detail-image and the .detail-image-container are dynamically resizing. An intermediary wrapper element is a useful technique for this situation. It will constrain the size of the .detail-image and serve as a reference for positioning the .detailimage-title. In index.html, begin by adding a
    with the class name detail-image-frame: ...
Stayin' Alive
Save index.html. Now, in styles.css, add a declaration block for .detail-imageframe with a single style declaration: text-align: center. This is one way to center content without flexbox, but note that it only works horizontally. ... .detail-image-container { flex: 1 1 auto; } .detail-image-frame { text-align: center; } .detail-image { width: 90%; } Next, to center the .detail-image-frame inside the .detail-image-container, update styles.css to make .detail-image-container a flex container. Draw its flex items in the center of the main axis (in this case, horizontally – the default) with justifycontent: center, and add a new flexbox property, align-items: center, to draw its flex items in the center of the cross axis (vertically). ... .detail-image-container { flex: 1 1 auto; display: flex; justify-content: center; align-items: center; } ... Save your changes and enjoy the proud otter, nobly centered in the .detail-imagecontainer (Figure 4.20). Figure 4.20 After centering .detail-image-frame inside .detail-imagecontainer Absolute and Relative Positioning Sometimes you need to place an element in an exact spot inside of another element. CSS gives you a way to do this using absolute positioning. You will use absolute positioning to place the detail-image-title in the lower left corner of the .detail-image-frame, as shown in Figure 4.21. Figure 4.21 Absolutely positioned .detail-image-title There are three requirements for absolute positioning. The absolutely positioned element must have: the property position: absolute, to tell the browser to take it out of the normal flow rather than laying it out along with its siblings coordinates, provided using one or more of the top, right, bottom, and left properties; absolute lengths (such as pixels) or relative lengths (such as percentages) may be used as values an ancestor element with an explicitly declared position property with a value of relative or absolute; this is important – if no ancestor has a declared position property, the absolutely positioned element will be placed relative to the element (the browser window) A word of warning: It might be tempting to use position: absolute for everything, but it should be used sparingly. A whole layout with absolute positioning is nearly impossible to maintain and will look terrible on any screen size other than the one it was developed for. When specifying a coordinate, you are really specifying the distance from the edge of the element to the edge of its container, as shown in Figure 4.22. Figure 4.22 Elements are absolutely positioned based on their edges Figure 4.22 has two examples of absolute positioning. In the first one, the element is positioned so that its top edge is 50px from its container’s top edge and its left edge is 200px from its container’s left edge. The second example shows a variation, where the element is positioned by its bottom and left edges. To position the .detail-image-title, start by declaring the .detail-image-frame to have position: relative in styles.css. You will position the .detail-image-title relative to it. ... .detail-image-frame { position: relative; text-align: center; } ... You used position: relative for .detail-image-frame because you want it to remain in normal flow. You also want it to serve as the container for an absolutely positioned descendant, so its position property must be explicitly defined. At the end of styles.css, add a declaration block for the .detail-image-title selector. For now, make the title white and set the font size to be four times the default. ... .detail-image { width: 90%; } .detail-image-title { color: white; font-size: 40px; } So far, so good (Figure 4.23). But so basic. Figure 4.23 Basic text styling for .detail-image-title For a touch of style, let’s add some text effects to the .detail-image-title. When positioning styled text elements, bear in mind that the element’s box may change due to the visual characteristics of a custom typeface or other effects. For this example, you will do all of the text styling for .detail-image-title before you set its position. Add a text-shadow property to .detail-image-title in styles.css. ... .detail-image-title { color: white; text-shadow: rgba(0, 0, 0, 0.9) 1px 2px 9px; font-size: 40px; } As the name suggests, the text-shadow property adds a shadow to text. It accepts a color for the shadow, a pair of lengths for the offset (i.e., whether the shadow falls above or below and to the left or right of the text), and a length for the blur radius – an optional part of a text-shadow declaration that makes the shadow larger and lighter in color as you make the value higher. You gave your shadow the color attribute rgba(0, 0, 0, 0.9) to make it a slightly transparent black. It is offset, or shifted, 1px to the right and 2px below the text (negative values would place it to the left or above the text). The last value of 9px is the blur radius. Figure 4.24 shows your new shadow. Figure 4.24 A text-shadow for the .detail-image-title Try adjusting the text-shadow values in the styles pane of the DevTool’s elements panel to get a feel for how they work (Figure 4.25). Figure 4.25 Exaggerating the text shadow using the DevTools When you are ready, add one last flourish with a custom font. As you did in Chapter 3, add an @font-face declaration in styles.css to add the Airstream font to your project. Add a font-family: airstreamregular declaration to .detail-image-title to put it to use. @font-face { font-family: 'airstreamregular'; src: url('fonts/Airstream-webfont.eot'); src: url('fonts/Airstream-webfont.eot?#iefix') format('embedded-opentype'), url('fonts/Airstream-webfont.woff') format('woff'), url('fonts/Airstream-webfont.ttf') format('truetype'), url('fonts/Airstream-webfont.svg#airstreamregular') format('svg'); font-weight: normal; font-style: normal; } @font-face { font-family: 'lakeshore'; ... } ... .detail-image-title { font-family: airstreamregular; color: white; text-shadow: rgba(0, 0, 0, 0.9) 1px 2px 9px; font-size: 40px; } So far, so stylish (Figure 4.26)! Figure 4.26 I gotta have more fancy Now that you have finished the styling of .detail-image-title, give it a position: absolute declaration so that the browser will place it at a precise location within .detail-image-frame. Specify that location with bottom: -16px and left: 4px, to put it just below the bottom edge of .detail-image-frame and a little bit inside the left edge of .detail-image-frame. (Negative values are fine for the coordinates.) ... .detail-image-title { position: absolute; bottom: -16px; left: 4px; font-family: airstreamregular; color: white; text-shadow: rgba(0, 0, 0, 0.9) 1px 2px 9px; font-size: 40px; } Save styles.css, and you will see in the browser that the .detail-image-title now sits below and near the left of the otter photo. You now have a positively chic Ottergram in your browser (Figure 4.27). Figure 4.27 Hello, gorgeous! Take a step back to enjoy the fruits of your labor. Ottergram has a dynamic, fluid layout thanks to the addition of flexbox to your styles. In the next chapter you will make the layout adapt to different browser window sizes. 5 Adaptive Layouts with Media Queries In this chapter, you will explore a technique for turning styles on and off based on the size of the browser window and other characteristics. You will provide an alternate layout for larger screens using a minimal amount of code. The browser will be able to switch between the different layouts in real time, as the browser window changes size – without reloading the page. Figure 5.1 shows the original layout and the alternate layout. Figure 5.1 Two Ottergram layouts The industry term for this behavior is responsive website. Unfortunately, this term is often a point of confusion. Some think that it means “fast website” or “website with visual animations.” We prefer to call it an adaptive layout. There are several ways of including alternate styles to be used based on the current browser conditions. The recommended approach is to write your styles for the smallest screen and then provide override styles in media queries that are triggered when the viewport – the browser’s viewable area – is larger than a set threshold. On a traditional browser (like the one you are using while developing Ottergram), the viewport is the area shown by the browser window. This is pretty intuitive. On a mobile browser, it gets more complicated. Mobile browsers have multiple viewports, and each one plays a role in how a page is rendered. Front-end developers need to focus on the layout viewport (sometimes called the actual viewport). The layout viewport tells the browser, “Pretend that I’m actually 980 pixels wide and then draw the page.” Users are more concerned with a mobile browser’s visual viewport. This is the thing that they can pinch to zoom in and out on a page (Figure 5.2). Figure 5.2 Visual viewport vs layout viewport If you viewed Ottergram on your smartphone right now, you would see something like Figure 5.2, with the browser zoomed in on the upper-left corner of the page. Needless to say, even though a mobile user can zoom out manually, you do not want Ottergram to behave like this by default. Earlier we mentioned that you are taking a mobile-first approach to developing Ottergram. That was mostly true. Your markup and styles were written in a mobile-friendly way – using a minimal amount of markup and styling the smallest elements first. Now, you just need to give the browser information about the layout viewport it should use. Resetting the Viewport In Chapter 3 you added normalize.css to Ottergram. This ensured that any browser viewing Ottergram would have the same set of default styles. On top of these defaults, you could confidently add your own CSS, knowing it would work consistently from browser to browser. You will do something similar for the layout viewport. Just as every browser may have a different user agent stylesheet, every browser may have a different default layout viewport. However, unlike using normalize.css, you are not going to reset the viewport for all browsers to the same value. Instead, you will use a tag to tell all browsers to display Ottergram at the best size for the device’s physical screen. In index.html, add a tag that tells the browser that the width of the layout viewport is the same as the device’s screen width. Make sure to set the zoom to 100% by setting the initial-scale to 1. Ottergram ... Save your changes. This technique sets the layout viewport to the ideal viewport. The ideal viewport is best viewport size for a specific device, as recommended by the browser maker. This varies significantly, since there are many, many different devices and quite a number of different browsers. Table 5.1 summarizes the different types of viewports. Table 5.1 Summary of the different viewports Viewport Description viewport The area equal to the browser’s window. It serves as the element’s container. Device desktop, laptop layout A virtual screen, larger than the actual device screen, used for viewport calculating the page layout. mobile visual The zoomable area that a user can see on a device’s screen. viewport Zooming has no effect on the page layout. mobile ideal The optimal dimensions for a specific browser on a specific viewport device. mobile Start browser-sync and make sure the DevTools are open in Chrome. Look to the left of the Elements menu item and find the Toggle Device Mode button, which looks like this: . It is shown in context in Figure 5.3. Figure 5.3 Toggle Device Mode button Click this button to activate device mode. You will see that the web page view now shows Ottergram on a simulated smartphone screen. There is a menu for choosing between different screen sizes based on popular devices. You can also click the gray bar below the presets to toggle between small, medium, and large screen sizes. And there is a menu for quickly choosing a screen orientation of landscape or portrait. Figure 5.4 shows a screenshot of the device mode at the time of this writing. Yours may look quite different, as the DevTools undergo regular updates. Figure 5.4 Using device mode for responsive testing You can see that, thanks to your new element, Ottergram displays well on a small screen, such as a smartphone. For devices with larger screens, such as tablets or laptops, a slightly different layout may be more appropriate. Next, you will apply different layout styles using a combination of flexbox and media queries. Click the button again to deactivate device mode before you continue. Adding a Media Query Media queries let you group CSS declaration blocks and specify the conditions under which they should be applied. Those conditions may be something like “if the screen is at least 640 pixels wide” or “if the screen is wider than it is tall and has a high pixel density.” The syntax begins with @media, followed by the conditions to be matched. Next is a set of curly braces that wraps around entire declaration blocks. Let’s see what this looks like. Begin your first media query at the end of styles.css. You will create a media query that will activate styles when being viewed on any kind of device when the viewport is at least 768 pixels wide, which is a common device width for tablets. ... .detail-image-title { ... } @media all and (min-width: 768px) { /* Styles will go here */ } is followed by the media type all. Media types were originally intended to differentiate between devices, such as smart televisions and handheld devices. Unfortunately, browsers do not implement this accurately, so you should always specify all. The only time you might not use all is when you want to specify styles for printing, when you can safely use the media type print. @media After the media type, you write the conditions for applying the styles. Here, you are using the useful condition min-width. You can see that conditions look similar to style declarations. To achieve the effect shown in Figure 5.1, you will need to change the flex-direction of the .main-content element. This will let the thumbnails and the detail image sit next to one another. You do not want the thumbnails to cause the browser to scroll. Instead, they should continue to scroll independently of the browser window. For that, you will add overflow: hidden. Add those styles to your media query at the end of styles.css. ... @media all and (min-width: 768px) { /* Styles will go here */ .main-content { flex-direction: row; overflow: hidden; } } You would be in for a shock if you saved and then stretched your browser wide enough to trigger your media query. At the moment, your page looks like Figure 5.5. Not to worry. You will fix this with only a few more lines of code. Figure 5.5 Otters in disarray The thumbnails need to be displayed in a column instead of a row. This is easy to do, because you used flexbox for laying them out. Add a declaration block inside the body of the media query in styles.css setting .thumbnail-list’s flex-direction to column. ... @media all and (min-width: 768px) { .main-content { flex-direction: row; overflow: hidden; } .thumbnail-list { flex-direction: column; } } Save styles.css. That has improved things significantly (Figure 5.6)! Figure 5.6 After setting flex-direction to column According to your design, the thumbnails should go on the left. You can solve this by changing .thumbnail-list’s order. Earlier, you set it to 2 so that it would be drawn after the .detail-image-container. Now, set it to 0 within the media query in styles.css so that it follows the source order and is drawn before the .detail-image-container. ... @media all and (min-width: 768px) { .main-content { flex-direction: row; overflow: hidden; } .thumbnail-list { flex-direction: column; order: 0; } } Save your changes and confirm that the thumbnails are drawn on the left side of the page. You are almost there! Add a few more styles in styles.css for the .thumbnail-list and .thumbnail-items to make the sizing and spacing a little nicer. ... @media all and (min-width: 768px) { .main-content { flex-direction: row; overflow: hidden; } .thumbnail-list { flex-direction: column; order: 0; margin-left: 20px; } .thumbnail-item { max-width: 260px; } .thumbnail-item + .thumbnail-item { margin-top: 20px; } } Once again, save styles.css and switch to your browser. Your layout now looks sharp whether the viewport is narrower or wider (Figure 5.7). Figure 5.7 Responsive otters Ottergram is making steady progress! You have created a good-looking website with a layout that can adapt to many screen sizes. In the next chapter, you will begin using JavaScript to add a layer of interactivity to Ottergram. Bronze Challenge: Portrait Your current media query changes the layout based on the width of the viewport. You could look at this in a different way. One is for viewports that are taller than they are wide, and the other is for viewports that are wider than they are tall. These are two orientation modes that your viewport can be in. Check MDN’s documentation for media queries and update your media query so that the layout changes according to orientation and not based on width. For the More Curious: Common Solutions (and Bugs) with Flexbox Layouts Philip Walton is a developer who maintains two very important flexbox resources. The first is the Solved by Flexbox site (​solved-byflexbox), which offers demos of common layouts implemented using flexbox and all the information you need to create them yourself. Some of the layouts are very difficult to achieve without flexbox. The second resource is the Flexbugs page at​philipwalton/​ flexbugs. Flexbox is wonderful, but it is not perfect. Flexbugs provides solutions and workarounds for common problems that developers run into when using flexbox. The information is provided by members of the development community who have encountered these bugs, and the list is well maintained. Gold Challenge: Holy Grail Layout Be sure to make a copy of your code before attempting this challenge! It will require significant changes to the markup and styles. Use your copy for working on the challenge and leave the original intact for starting the next chapter. Using Solved by Flexbox as a reference, implement the Holy Grail layout in Ottergram. Create a second navigation bar with thumbnails, but place it on the other side of the viewport. Make sure to add a footer element to the bottom of your page. Use the