Learning Responsive Data Visualization - Sample Chapter
Learning Responsive Data Visualization - Sample Chapter
$ 44.99 US
28.99 UK
P U B L I S H I N G
Christoph Krner
Learning Responsive
Data Visualization
ee
pl
C o m m u n i t y
E x p e r i e n c e
D i s t i l l e d
Learning Responsive
Data Visualization
Master the art of building responsive visualizations on the Web
Sa
m
Christoph Krner
Preface
Data visualizations are the best way to understand complex information and data.
The human brain perceives visual information easily; it can make connections and is
able to understand the complete process easier than without visualizations.
I am always delighted with the positive feedback from users whenever they
understand a complex system easily by looking at a data visualization, instead
of going through explanatory text and raw data. With the power of the Web and
modern browsers, I can share these visualizations with everyone and make them
interactive and animated.
To power cross-browser interactive visualization, I didn't want any compromise
with regards to performance, debugging, quality, and interactivity, which led me
to SVG. After deciding for SVG, I looked for a framework for SVG transformations
giving raw access to all its underlying standards while also providing a rich set of
visualization features - the D3.js library provides all of these.
D3.js is a visualization toolkit that facilitates the generation and manipulation of
web-based vector graphics and provides full access to underlying SVG standards.
Moreover, animations and interactive visualizations change the way users perceive
web applications, and D3.js offers everything you need to make a visualization
interactive out of the box.
While this has been working for the last few years, I realized that users are
increasingly accessing visualizations with their mobile devices, though mostly
through smartphone and tables. On most tablets, visualizations looked good, though
interactions did not work anymore. Smartphone users experienced this as well when
they tried to zoom into a browser but it somehow interfered with the zoom of the
visualization and randomly toggled interactive features instead. For me, this was the
sign I needed to fix the problem.
With the rise of responsive web design, there were already plenty of ideas for
creating cross-browser and cross-platform applications that adapt to a user's device,
screen size, and resolution. Apart from this, modern browsers already provide solid
CSS and JavaScript functionality to implement responsive designs for all kinds of
web applications.
Preface
The only logical step for me was to combine rich tools in order to create responsive
applications and introduce the same ideas into data visualizations. I want my
visualizations to adapt to the user's device, screen size, and resolution while providing
cross-platform interactivity for mouse and touch gestures. In this book, I will share my
knowledge, experience, and best practices on responsive data visualizations with you.
What is a Media Query and how it can be used to design visualizations for
various devices
[1]
First, you will learn about Responsive Design and how it can be used to design a
visualization for various screen sizes and resolutions. Then, we will discuss the
importance of some key technologies such as CSS3 (especially Media Queries) and
HTML5 (especially the viewport meta tag).
In the following chapter, we will get acquainted to the popular CSS and HTML
framework called Bootstrap. Don't worry if you have never heard about it; it helps
us to build the application on the existing and well-tested components, such as grids
and LESS Media Queries.
In the last section of this chapter, you will learn about Scalable Vector Graphics
(SVG) in the browser; and you will understand why and when it is great to use
vector graphics for visualizations. Then, we will see a brief introduction to D3.js,
which is a versatile JavaScript library for data transformations and graphics
generation. At the end of this chapter, you will understand why SVG is a great choice
for designing interactive responsive visualizations for the web.
[2]
Chapter 1
In Responsive Design, we are mostly interested in querying the min-width or maxwidth property to apply different styles to devices that have different widths.
Let's see an example where we can apply a different background color depending on
the minimal width of the browser window:
div {
background-color: blue;
}
@media screen and (min-width: 992px) {
div {
background-color: red;
}
}
In the preceding example, all the div elements in the page have the background
color red as long as the browser window's width is larger or equal to, 992 px
(see the following figure):
[3]
Once the window width is smaller than 992 px, the background color of the div
elements jumps to blue (see the following figure):
As we can see in the following figure, Media Queries are supported across all major
browsers and Internet Explorer starting from version 9:
Understanding Breakpoints
In Responsive Design, we call a state when a certain layout and Media Query is
active, and we call a breakpoint the transition from one state to another.
Let's look at an example. First, we define some screen dimensions for the
following devices:
[4]
Chapter 1
Create a CSS snippet using Media Queries for these device dimensions:
/* phones, default no query */
/* tablets */
@media (min-width: 768px) { ... }
/* desktops */
@media (min-width: 992px) { ...}
/* large devices */
@media (min-width: 1200px) { ... }
In the preceding code, we defined four states with three breakpoints between these
states where each state corresponds to a typical screen dimension and device type.
We can also see these breakpoints by reducing the size of a browser window while
looking at a responsive web page; we observe how the design breaks at a certain
width of the browser window. In the following figure, the breakpoint is visualized as
a dashed line, showing the moment when one state breaks into a new one:
We can observe the same effect when we look at the Google Plus web page in the
following figure. In the first two figures, the size of browser window changes, but the
three-column layout stays the same. In the third image, the design breaks into a new
layout with only two columns:
[5]
More information about all the valid viewport options can be found
on MDN at https://developer.mozilla.org/en-US/docs/
Mozilla/Mobile/Viewport_meta_tag.
These units have a big advantage; they are affected by the changes of the font-size
setting in the browser. A simple example can be the adaption of the paddings when
the user increases the font size of the browser.
[6]
Chapter 1
Mobile first
Desktop first
In the desktop first method, we design for desktop devices and mouse input first,
then we adjust and scale the design down for mobile devices and touch interactions.
This often results in a web application with a reduced functionality for mobile
devices due to a much smaller screen dimension and the lack of touch support.
In the mobile first method, we design for mobile devices and touch interactions
first, and then we adjust and scale the design up for bigger devices and mouse
interactions. This approach makes sure that mobile devices support a complete set of
features, which can even be used on desktop clients.
Both methods are equally correct, accepted, and popular nowadays. The only
exception is that mobile first became a buzzword due to an increase of mobile
devices accessing the web during the previous years. Throughout the book, we will
choose a mobile first approach and design for mobile devices and touch support.
However, we will, of course, extend the visualizations to support mouse input and
bigger screens. That's what the responsive design is all about.
[7]
Bootstrap is a very popular HTML and CSS framework built by former Twitter
employees for easy, fast, and modern frontend development; it provides loads
of responsive CSS and LESS layouts as well as a huge collection of HTML and
JavaScript components. Thanks to its MIT license, it can be used in open source
and commercial software.
The current stable version 3.3.5 includes LESS styling with these features:
Styles for common components such as forms, input fields, and tables
The new version 4 (which is currently in the alpha stage) will be shipped with SASS
layouts and loads of other great features and improvements:
There also exists an official fork for the SASS precompiler on
GitHub at https://github.com/twbs/bootstrap-sass.
Throughout this book, we will use Bootstrap 3.3.5 version (with LESS) for all the
examples and explanations if they are not stated differently. We will also give some
hints about the latest version where it is appropriate.
[8]
Chapter 1
Including Bootstrap
Make sure you have the Bower package manager installed; this can be done by
running the following command from the terminal:
npm install -g bower
Throughout this book, we will make use of only the CSS components of Bootstrap
and thus we only need to include the bootstrap.css file to our project. There are
multiple ways of doing so:
I strongly recommend using the bower package manager to manage your frontend
dependencies (or similar ones, such as npm or component). However, in the examples
of this book, we will link Bootstrap directly from MaxCDN for simplicity reasons;
therefore, all examples in the source of the book require an active Internet connection.
[9]
For more detailed information and examples, I recommend reading the Unraveling
Bootstrap 3.3 book by Istvan Novak.
We then distinguish two different types of responsive grids that adapt the number of
columns to the screen resolution of the client:
Normal grids with a fixed width per breakpoint (see following figure on the left)
Fluid grids that always scale to the full width of the current breakpoint
(see the following figure on the right)
[ 10 ]
Chapter 1
It's actually quite simple to build a grid system yourself; let's first take a look at how
to create a fluid grid layout, and afterwards, we will better understand how we can
use Bootstrap components to get things done quickly and properly.
If we think about a grid as a (flexible) table layout, we need two basic components:
rows and columns. A popular approach is to use the 12-column grid where we divide
the width of a row into 12 columns and define column combinations that sum up
to the full width of 12. The following figure illustrates some of these combinations:
12 columns of width 1, 6 columns of width 2, 4 columns of width 3, and so on. Also
other combinations that sum up to 12 are allowed, such as 2, 6 and 4 or 1, 10 and 1
and many more.
Let's start and build the .row class that spans to the full width of the parent element:
.row {
position: relative;
width: 100%;
}
Next, we want to create column classes .col-1, .col-2, ., and .col-12 that define
the width of the column in the percent relative to the width of the row. We define a
text wrap with the float attribute and add padding for the cells. The float attribute
indicates that the block element should not appear in the original flow but "float" on
the left side. By doing so, we align the elements in the same line instead of placing
them into the normal text flow:
[class*="col-"] {
float: left;
[ 11 ]
In the preceding code, we see that we can use the wildcard attribute selector called
[class*="col-"] to select all the columns at once (all the classes that contain the
col- letters). The widths have to be defined as per column type.
[ 12 ]
Chapter 1
Finally, we need to clear the text-wrapping property of the columns after each row.
We can do this by adding a clearfix pseudo element after each .row class:
.row:after {
content: " ";
display: block;
clear: both;
}
This is already a nice implementation of a basic grid system. Let's test this layout and
create an HTML page with the following content:
<div class="row">
<div class="col-1">.col-1</div>
<div class="col-1">.col-1</div>
<div class="col-1">.col-1</div>
<div class="col-1">.col-1</div>
<div class="col-1">.col-1</div>
<div class="col-1">.col-1</div>
<div class="col-1">.col-1</div>
<div class="col-1">.col-1</div>
<div class="col-1">.col-1</div>
<div class="col-1">.col-1</div>
<div class="col-1">.col-1</div>
<div class="col-1">.col-1</div>
</div>
<div class="row">
<div class="col-2">.col-2</div>
<div class="col-2">.col-2</div>
<div class="col-2">.col-2</div>
<div class="col-2">.col-2</div>
<div class="col-2">.col-2</div>
[ 13 ]
If we add a little bit of coloring (the complete example can be found in the code files
of the book) and open the HTML page in the browser, we get a layout similar to the
following figure:
[ 14 ]
Chapter 1
Let's take a look at the responsive grid system provided by Bootstrap, which looks
very similar to the one that we have just created. Bootstrap defines Media Queries for
four device types (the so-called grid tiers) and their corresponding typical viewport
widths (in pixel) for the responsive breakpoints:
768px for small devices (sm) such as tablets and phones in landscape mode
1200px for large devices (lg) such as large desktops and TVs
In Bootstrap 4, the breakpoints are now defined in
em units:
It requires a container element with the class called .container for fixed
widths or .container-fluid for fluid containers
[ 15 ]
Let's take a look at some code. First, we need to include the Bootstrap CSS to the
header of the web page:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/
bootstrap/3.3.5/css/bootstrap.min.css">
<title>Simple Grid System</title>
...
</head>
<body>
...
</body>
</html>
Now, we can add the grid layout according to the previous example, but this time,
we need to wrap it in a fluid container:
<div class="container-fluid">
<div class="row">
<div class="col-lg-1">.col-lg-1</div>
<div class="col-lg-1">.col-lg-1</div>
...
</div>
<div class="row">
...
</div>
</div>
If we open the web page and look at the output of the web browser, we see an
example similar to the following figure:
[ 16 ]
Chapter 1
We remark that the preceding figure looks very similar to the grid layout that we
created in the beginning of this section. The only small difference in the code was
the .container element to wrap the rows and the usage of the .col-lg-* classes.
However, Bootstrap's grid is responsive, and the columns are arranged according to
the breakpoints and the browser width. If we reduce the size of the browser window
smaller than 1200px, we see that the grid jumps into a different layout. We can see
this effect in the following figure:
Browser output of grid layout with window size smaller than 1200px
The reason for this is that the browser window is no longer in the state of a very
large device (greater than 1200px) and has jumped to a smaller state. Therefore, the
col-lg-* columns are not applied anymore, and they appear in the full width of
the row. We can now start to define certain column combinations to create a flexible
responsive grid:
<div class="container-fluid">
<div class="row">
<div class="col-lg-3 col-md-6 col-sm-12"></div>
<div class="col-lg-3 col-md-6 col-sm-12"></div>
<div class="col-lg-3 col-md-6 col-sm-12"></div>
[ 17 ]
.hidden-xs
.hidden-sm
.hidden-md
.hidden-lg
The classes for showing elements on certain browser widths come for each
breakpoint in three different variations depending on the CSS display property of
the element:
.visible-*-block
.visible-*-inline
.visible-*-inline-block
The reason for these additional types is undesired line breaks
and behaviors that occur when the display mode changes
from none to block. Therefore, Bootstrap forces the user to
specify the display property via the class name.
[ 18 ]
Chapter 1
For these three blocks, all the breakpoint classes are available:
.visible-xs-*
.visible-sm-*
.visible-md-*
.visible-lg-*
Make sure you have the LESS compiler installed; this can be done by running the
following command from the terminal:
npm install -g less
[ 19 ]
Now, we can use Bootstrap's Media Query breakpoints in our LESS file. Let's add
some device-specific padding to all the div containers:
/* Extra small devices */
/* No media query since this is the default in Bootstrap */
div {
padding: 4em;
}
/* Small devices */
@media (min-width: @screen-sm-min) {
div {
padding: 8em;
}
}
/* Medium devices */
@media (min-width: @screen-md-min) {
div {
padding: 16em;
}
}
/* Large devices */
@media (min-width: @screen-lg-min) {
div {
padding: 24em;
}
}
Now, we use the LESS compiler to compile the stylesheet with CSS by running the
following command in the terminal:
lessc style.less style.css
The resulting CSS looks similar to this:
/* Extra small devices */
/* No media query since this is the default in Bootstrap */
div {
padding: 4em;
}
/* Small devices */
@media (min-width: 768px) {
div {
[ 20 ]
Chapter 1
padding: 8em;
}
}
/* Medium devices */
@media (min-width: 992px) {
div {
padding: 16em;
}
}
/* Large devices */
@media (min-width: 1200px) {
div {
padding: 24em;
}
}
Perfect! This means that we can now use the predefined breakpoints in our
LESS styles.
Sometimes, it is also necessary to limit your styles to a narrow set of devices.
Therefore, one can also use the max-width Media Queries in LESS. Again, the
following code snippet is taken from the Bootstrap documentation at http://
getbootstrap.com/css/#grid-media-queries:
@media
@media
... }
@media
... }
@media
This can be useful when we want to define styles for a single device type rather than
all the devices with a screen width greater than or equal to the defined one.
Canvas API (or using, for example, Paper.js, Processing.js, and more)
WebGL API (or using, for example, Three.js, Pixi.js, and more)
SVG specification (or using for example RaphalJS, D3.js, and more)
[ 21 ]
To better understand which technology suits the best for our purpose of
implementing responsive visualizations, we need to take a closer look and discuss
their advantages and disadvantages.
A Pixel Graphic is an image that contains all the information about the color of each
pixel of the image for a certain resolution. Let's assume we have an image with 8 x 8
pixels where each of these 64 pixels contains the information about its color; we draw
a circle in this image:
<canvas id="canvas"></canvas>
<script>
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var centerX = 10, centerY = 10, radius = 10;
ctx.beginPath();
ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
ctx.fillStyle = "red";
ctx.fill();
</script>
[ 22 ]
Chapter 1
In the following figure, one can see how the so-called rasterization process defines
which pixels of this image gets colored (pixels in the blue region) for the circle shape
and which pixels stays transparent (pixels in the white region):
If we display this image with a high resolution (see the following figure at the left),
we see a small circle with crisp edges. On the other hand, if we zoom into the image,
we see a very pixelated 8 x 8 pixel image (see the following figure on the right); this
effect is the direct cause of the resolution-dependent rasterization process:
This effect makes it really difficult to use Pixel Graphics for Responsive Design; we
have to always generate and reload our visualization for the current resolution and
screen size.
Another drawback is that the final image is composed of pixels, which make it
very difficult to attach event listeners, such as mouseover or click events, to
certain components of the image. The reason for this is that there are no shapes or
components encoded in the image but only color values for each pixel.
[ 23 ]
Due to WebGL's use of the Canvas element, it doesn't solve any of the limitations
of Pixel Graphics that we discussed in the Canvas section. Thus, we will look at a
different type of image representation next.
[ 24 ]
Chapter 1
Vector Graphics are images where all the information about the image is encoded
as numerical expressions of geometric shapes (such as rectangles, circles, ellipses,
paths, and texts) of the elements of the image. The browser always uses this
information to draw and render the graphic in the best resolution possible. In the
following figure, we can see a Vector Graphic of a circle with a high resolution,
whereas on the right, we see a zoom of the image. It's easy to see that the zoomed
image is displayed with perfectly crisp edges; this effect of lossless scaling results
from the resolution-dependent rendering of the browser.
You can find detailed information about the SVG specification
on the W3 website: http://www.w3.org/Graphics/SVG/.
More advantages result from the fact that the visualization's elements are simply
embedded in the HTML page. Now, we can easily attach native JavaScript event
listeners, such as the mouseover or click events, on every component of the graphic
and use CSS to style them together with the rest of the application.
[ 25 ]
Another great benefit is that we can simply look into the Developer Console of
the web browser, play around, and debug the visualization. We can click on each
element of the image to see its attached event handlers, and we can modify the CSS
styling in real time. Anyone who has ever dealt with OpenGL or WebGL debugging
will agree that this is a comfort that you can't miss while developing visualizations
for the web.
Now, we already have many arguments in favor of using SVG for responsive crossbrowser visualizations:
Sharp rendering on all screen resolutions because the browser renders the
graphic according to the client's screen resolution
Native JavaScript event handlers can be attached to all elements of the image
Mike Bostock and other members of the Stanford Visualization Group for DOM
manipulation, data transformation, and graphic creation. It uses a jQuery-like,
data-driven approach and leverages all the capabilities of modern browsers and
underlying web standards (such as HTML, CSS, and SVG).
under a slightly modified BSD 3-clause license; therefore, it can be used in open source
and commercial products without being required to release any modifications. GitHub
itself uses D3.js to visualize the contribution history of repositories.
Throughout this book, we will use the stable version 3.5.6, but most examples should
also work with different minor versions.
[ 26 ]
Chapter 1
Including D3.js
There are multiple ways to include D3.js to your project:
Using the package manager called bower (recommended), fetch the library
by running the bower install d3#3.5.6 command from the terminal.
Then, link the minified CSS file from the bower_components/ directory in
the head section of the web page:
<link rel="stylesheet" href="bower_components/d3/d3.min.css">.
I strongly recommend using the package manager called bower to manage your
frontend dependencies. However, in the examples of the book, we will link D3.js
directly from cdnjs for simplicity reasons; therefore, all the examples in the source of
the book require an active Internet connection.
[ 27 ]
Summary
In this chapter, we saw a brief introduction to Responsive Design, Media Queries,
and Viewport settings. You learned about relative units and the mobile first design
approach for responsive applications.
Later, we introduced Bootstrap and implemented a simple grid system ourselves.
This helped us to understand how the responsive fluid grid in Bootstrap works. We
saw built-in responsive utilities as well as Media Queries in LESS.
In the last section of this book, we discussed the difference between Pixel and Vector
Graphics by comparing the advantages of Canvas, WebGL, and SVG for Responsive
Design. We realized that SVG suits very well to implementing responsive
visualizations. In the end, we saw a brief introduction to D3.js.
In the next chapter, we will get started with D3.js and implement a simple graphic
using data joins, dynamic properties, and simple transformations.
Downloading the example code
You can download the example code files for this book from your
account at http://www.packtpub.com. If you purchased this
book elsewhere, you can visit http://www.packtpub.com/
support and register to have the files e-mailed directly to you.
You can download the code files by following these steps:
Log in or register to our website using your e-mail address and
password.
Hover the mouse pointer on the SUPPORT tab at the top.
Click on Code Downloads & Errata.
Enter the name of the book in the Search box.
Select the book for which you're looking to download the code
files.
Choose from the drop-down menu where you purchased this
book from.
Click on Code Download.
Once the file is downloaded, please make sure that you unzip or
extract the folder using the latest version of:
WinRAR / 7-Zip for Windows
Zipeg / iZip / UnRarX for Mac
7-Zip / PeaZip for Linux
[ 28 ]
www.PacktPub.com
Stay Connected: