Lemieux Design

Flash | Interactive | Web | Graphics | Brand | Video

RWD – Vertical Rhythm – Part 1

Posted on: December 8th, 2014 by alemieux 1 Comment

Last time, we talked about the Em unit as being flexible when the body is set to 100%. Now, we’ll turn our attention to vertical rhythm and the typographic scale.

“Don’t compose without a scale” – Robert Bringhurst1

Typographic Scale

I once attended a Photoshop seminar in Boston. A local photographer was going through what she termed a Mathematically solid way of correcting images. She touted the formula as the best way to correct images. She started in with the Histograms in the Levels dialog and showed how adjusting for the 3 separate channels produced better results. She talked about the Gamma levels and what to look for when making adjustments. The crowd was in rapt attention. As she finished up her final adjustment in the Blue channel, she finished off by doing something very unformulaic, something very unmathematical, she adjusted the midtone gamma level range to either lighten or darken the photo to taste, describing this last option as something that would be different for everyone and to trust your eye.

“It’s not about knowing all the gimmicks and photo tricks. If you haven’t got the eye, no program will give it to you.” — David Carson

It turns out that trusting your eye when it comes to Typography is a skill that once attained, will serve well in crafting type both for print and on the web.

“Anyone can use typefaces, some can choose good typefaces, but only a few master typography” – Information Architects

Line Length & Legibility

When the internet was in its infancy, text ran from one side of the viewport to the other. At that time, screen resolutions were pretty low, 800 x 600, but the text on some sites was difficult to read because of something we call a measure or the line length in typography. This is a comfortable distance that the eye travels across the text and is able to get to the next line to continue the story. A wider measure tires the eye as it has to read a longer distance and then attach to the next line. A short measure makes for quick reading, but too short and the text starts to hyphenate more quickly and presents other challenges.

The measure can be an arbitrary value and there are some guidelines out there, but in the end the measure is largely governed by the font that’s being used. A bolder font can hold up well with a wider measure, whereas an italic face or a thin serif needs a shorter measure. Robert Bringhurst, author of The Elements of Typographic Style has this advice on the measure:

“Anything from 45 to 75 characters is widely regarded as a satisfactory length of line for a single-column page set in a serifed text face in a text size. The 66-character line (counting both letters and spaces) is widely regarded as ideal. For multiple-column work, a better average is 40 to 50 characters.”2

He goes on to make suggestion for what the measure might be in shorter or wider situations, but he at least gives us a baseline. This is especially important in the context of Responsive design. Say for example, you have text on a page that looks great on a desktop at 1024 x 768, but then if you look at that same page at a higher resolution, say 1440 x 900, the measure will increase ruining the legibility. This is where max-width might come in handy:

section {
max-width: 45em;
}

On smaller devices, the measure may be fine, but now your text flow is more compact, invariably tighter. You might need to adjust for the smallest screen size in your media queries.

In beginning a practical exercise, you should have your fonts picked out for the body and headlines, subheads and whatever applications are needed. You may even have just one font with variations in weights and styles. When you have the type set, adjust the width of the container to find a comfortable measure. I’ve found that with 16px (100%) font size, a 32em – 34em (somewhere between 480 – 420 pixels) seems to be a good measure.

Line Height

The next thing we’ll need to do is find a good leading value, but on the web that’s more difficult than in print.3 The problem on the web is that there is no concept of a baseline and the CSS line-height property doesn’t behave like prints counterpart leading. Each line of text is placed roughly in the middle of the elements total height. This is contrary to the basic principle of a baseline grid: the bottom of every line of text falls on a vertical grid set in even increments all the way down the page.

This is relatively easy to accomplish in InDesign or QuarkXPress, where we can enforce text to adhere to the baseline grid. It’s a little harder to do on the web though. The 3 factors that we need to control are font size, line height and margins (although some argue that padding is a better control mechanism4).

Baseline Grid

InDesign (left) and Quark (right) allow you to snap the text to the baseline grid.

Line height is a key value to determine though and there are many schools of thought on how to achieve the appropriate balance. Assuming a 16px (100%) font size for our body text, most desktop publishing applications will enforce a general leading rule of 120%. That would give us a leading value of 19.2. That appears to be a healthy amount of space between lines, but you may prefer a tighter or looser leading depending on the font you’ve chosen.

Font Sizing With a Typographic Scale

We have our body text set, but what about our headlines, subheads or callouts? We certainly can put a lot of guesswork and trial and error into selecting appropriate font sizes for these, but we can also rely on a typographic scale. Musicians, architects and artists have similar systems that continue to work in delivering pleasing work that’s balanced and harmonious. Musicians have musical scales with specific characteristics that are tonally pleasing to the ear. A half step off and the dissonance is quite noticeable. Architects use proportion and physics to create spaces that are inviting and dynamic, otherwise we’d all be living and working in boxes. The typographic scale is just one of many modular scales that can mathematically relay specific intervals that are harmonious and pleasing to the eye.

One such modular scale is the Golden Section. The mathematical ratio is 1:1.618. If we take that and apply it to typography, we can come up with a range of values that give us possibilities to choose from for font sizes:

16 x 1.618 = 25.888
25.888 x 1.618 = 41.886
41.886 x 1.618 = 67.772

And so on. If we need smaller values, we can divide to get them:

16 / 1.618 = 9.88
9.88 / 1.618 = 6.11

If you want an easier way to create a system like this, use Tim Brown’s Modular Scale. Input a value and then choose a scale and then click Submit Query.

Modularscale.com

Finding a Typographic Scale with Modularscale.com

So we might apply styles to our headings in the following manner:

h1 { font-size: 67.772px;
line-height: 67.772px;
color: #DC3522;
}
h2 { font-size: 41.886px;
line-height: 41.886px;
color: #374140;
}
h3 { font-size: 1em;
line-height: 1.2;
text-transform: uppercase;
color: #7D7D7D;
}

The heading is dramatic and the subhead feels like the right size, just twice the size of the body text. These are pixel values, but they can be converted to ems. For the font size, we use the standard RWD formula: target / context = result. If our body text is 16px, we would divide by that.

67.772 / 16 = 4.23575
41.886 / 16 = 2.617875
25.888 / 16 = 1.618

What about the leading values? Because the context changes, we take the line height and divide it by the font size. In the case of our heading and subhead, the font size and line height are equal values and when you divide them, you’ll get 1. So our styles now look like this:

h1 { font-size: 4.23575em;
line-height: 1;
color: #DC3522;
}
h2 { font-size: 2.617875em;
line-height: 1;
color: #374140;
}
h3 { font-size: 1em;
line-height: 1.2;
text-transform: uppercase;
color: #7D7D7D;
}

If you inspect the h1 element in Chrome or Firefox, you’ll see that the computed style shows the pixel values that we previously input for the font size and line height. Here’s what we have so far:

See the Pen Typographic Scale Example by Al Lemieux (@alemieux) on CodePen.

There’s a wonderful site that you can use to explore vertical rhythm. At Typecast.com, you can copy and paste all of your text into an interface that lets you play with your body text, headlines, and any other element you put on the page. You can then view and even export all of the CSS so that you can use it in your own project. You can even get a style guide that is created as you develop the page. You can try typecast for free, but then there are monthly payment plans for full usage.

Another tool you can use to find vertical rhythm is at drewish.com. Not as elegant as modularscale, but you can get some basic guidance on setting body text, headings, and subheadings.

There are other methods for arriving at vertical rhythm, which we’ll take a look at next time. This method is pretty sound, but not very practical. As you’ll see, there’s quite a bit of math involved and one thing will persist: pixel values will need to be converted to ems. So break out and dust off that calculator.

About Codepen

Some of you may already know about Codepen, which I’ve been using for the past couple of posts. It’s a great playground where you can play with HTML, CSS, and JavaScript in a browser environment and get instant feedback. Instead of flipping back and forth between an editor and a browser, you can do all of the work within one browser window. Sure, there are other playgrounds out there, but I just love the way things work in Codepen. You can check out some other experiments that I’m working at codepen here: http://codepen.io/alemieux/public/

Footnotes

  1. The Elements of Typographic Style. Robert Bringhurst. p. 26.
  2. Ibid. p. 45.
  3. Type on Screen: A Critical Guide for Designers, Writers, Developers, and Students (Design Briefs), by Ellen Lupton – May 2014
  4. Scale & Rhythm. Ian Lamb. 2009. http://lamb.cc/typograph/

RWD – Typography: The Almighty Em

Posted on: December 1st, 2014 by alemieux 1 Comment

In Ethan Marcotte’s tome Responsive Web Design, he begins setting a simple typography example with the following explanation:

Finally, you’ve probably noticed that the font-size has been set to 100%. In doing so, we’ve simply set our base type size to the browser’s default, which in most cases is 16 pixels. We can then use ems to size text up or down from that relative baseline.

There’s not a lot of explanation about why the base font size is set in a percentage and why ems is the unit of choice. Published in 2011, the book may have come at a time where this was standard practice or just the way Ethan went about doing his thing. There was a pretty popular method of setting the base font size to 62.5%, which makes the base font size 10pt – a nice round number that can be mathematically managed better than 16pt. In order to explore Ethan’s method, we need to understand a few things about the baseline type set in percentages and why ems are better than other units of measure.

Units of Measure

You can specify type sizes in CSS with pixels, points, inches, ems, percents, and other units of measure. It would seem at first glance that when working in a web-related dimension, that using pixels as the primary unit makes the most sense. The reason why we don’t use pixels or points is because they are not scalable – meaning they can’t be resized in all browsers. In IE6 & 7, it was particularly a problem. Most modern browsers can scale pixel-based text, but there are problems with it on mobile devices. If the base font size changes, say from 100% to 120%, pixel-based font sizes will stay the same. Another reason we can’t use pixels is that pixel sizes “aren’t constant – or at least the display of them isn’t. 16px text on an iPhone can be ~60% the size of 16px text on a Macbook.”1

Why not use percentages as the choice unit of measure? Ems and Percents are essentially the same, but scale differently depending on what the base font size is set to. Em-based font sizes tend to become exaggerated when resizing in IE6 & 7 when the base font is not set to percentages. When we define font sizes in percentages, it is a percentage of the body font size. So 150% is 150 percent of the font size, whereas 1.5em is 1.5 times larger.2

About That Em

Em Units Are Scaled

An Em unit is defined as the point size or classically, the size of an uppercase M in any font or slightly larger. Robert Bringhurst, author of the Elements of Typographic Style defines an Em as such:

[t]he em is a sliding measure. One em is a distance equal to the type size. In 6 point type, an em is 6 points; in 12 point type an em is 12 points and in 60 point type an em is 60 points. Thus a one em space is proportionately the same in any size.3

Perhaps that helps us to visualize the Em unit a little better, but it’s the flexibility of Ems. Setting up our baseline font size as 100% and then setting all other elements in Em-based font sizes makes that text relative. If you have all of your type set in pixels, changing the base font size doesn’t cascade and makes the rest of the text relatively update. If you set your text in Ems however, and change the base font size, you don’t have to touch your Em-based font sizes because they are relatively affected by that change.4

In Media Queries, this is pretty powerful. Instead of making individual changes, you can simply change the body font size and be done with it. The scaling that Ems employ allow for quick global changes.

Mathematical Operations

I never paid attention in Math class. In fact, some of the best doodling I ever did was in that class, much to my chagrin. To be perfectly honest, the first time I went through Responsive Web Design, I didn’t fully get the calculations and struggled with understanding why I had to use Ems. Of course, I – like many others – were using pixels for everything. If we can’t use pixel values for responsive design and Ems are a better unit, how do we use them? A handy dandy formula:

target ÷ context = result5

The target is the size of text that you want to use. The context (although it can change) is the base font size, which for our purposes is 1em or 16px. If all of our body text is 100%, which is 1em, which is 16px, what if we want text that is smaller or larger than that? Let’s start with a headline for example. If I have a 24px headline in my design I need to convert that to ems. So, I use the formula above and come up with the following:

24px ÷ 16px = 1.5em

Let’s say that I have some copyright text in the footer that needs to be 10px. Again, using the formula, we get:

10px ÷ 16px = 0.625em

See the Pen Calculating Font Sizes with Ems by alemieux3 (@alemieux3) on CodePen.

Other Considerations

The Rem unit is said to be more reliable than Em, but since Marcotte and others specifically advocate it, I’m sticking with that unit of measure for now. One thing about base font size is that the default 16px browser font size is not a given. Anyone can change their browser preferences and set the font size to anything they want. If they have a hard time seeing, for example, they might set the font to something a lot larger. The ability to zoom text or the viewport in most modern browsers will also alter the look of your type and that’s just a bit of control that you have to give up. One other note is that most web design templates have this system built into it already, like Twitter Bootstrap and others, so if you’re using one of those systems, it’s already built in.

Next time, we’ll look into setting a baseline grid and creating a vertical rhythm.

Footnotes

  1. The Goldilocks Approach to Responsive Web Design. Front design agency. http://goldilocksapproach.com/demo/
  2. Font Sizes in Responsive Design: px vs. pt vs. em vs. percent? Eclipse Web Media. https://www.eclipsewebmedia.com/font-sizes-in-responsive-design/
  3. The Elements of Typographic Style As Applied to the Web: 2.1.1 Define the word space to suit the size and natural letterfit of the font. http://webtypography.net/2.1.1
  4. Why Ems? CSS Tricks. Chris Coyier November 8, 2012. http://css-tricks.com/why-ems/
  5. Fluid Grids. Ethan Marcotte. A List Apart. March, 2009. http://alistapart.com/article/fluidgrids

RWD – Browser Tools for Responsive Design

Posted on: November 26th, 2014 by alemieux 1 Comment

Last time, we looked at the HTML5 Shiv for older versions of Internet Explorer. Next up, we’ll take a look at some of the browser tools that you have at your disposal when working responsive.

Chrome

Google Chrome’s Developer tools are a fantastic repertoire of debugging aids that are essential for any web workflow. Chrome also comes in another form called Canary, which is intended for developers and has all of the latest features Webkit.

To Open the Developer Tools, go to View > Developer > Developer Tools. Immediately, you will see the HTML and CSS source in the Elements tab. You can inspect any element in the DOM by hovering over them first to see what’s highlighted, and then by clicking on them. All of the computed styles for the selected element will appear in the Styles tab. You can see the cascade and how styles are overridden as you move downward. If you want to temporarily disable a style, you can uncheck it. If you wanted to experiment with a given style, you can change the values in the style properties that are displayed. You can also enter new property / value pairs on elements. If a color is present, you can click on the color to get a nice color picker and change the value. None of these changes affect the page you’re working on, it’s literally a playground to check your work. If you switch over to the Console tab, you’ll be able to see any errors that might happen during a page load or on JavaScript events. You can use the Console to test variables and write some simple scripts to test.

The Responsive portion of the Dev Tools is some very nice emulation tools. Click on the rectangular shape near the magnifying glass in the top of the Developer Tools Window, this is supposed to look like a cell phone. Now you’ve enable Device Emulation mode.

Device Emulation

On the left is a handy pixel ruler. On the far right is a page scale indicator. By default, it’s set at 1.0. You can click the plus (+) or minus (-) buttons to change the scale or hold shift and drag on the page. At the top, in the orange section, you can select which device you want to test and change the orientation. The device pixel ratio is shown as 1 for some devices and for retina displays and HD screens, it’s shown as a higher value. The iPhone 5, for example, is shown as 2.

In the blue Network section, you can also emulate network throttling and latency. Refresh your page to see the desired effect. Unless you’re testing specifically for interactions that might be affected by network throttling, you should have this set to No throttling, which is the default.

You can get to the emulation options inside Chrome itself or inside the Developer Tools window.

Device Emulation Options

The range of devices and the ability to change the orientation is pretty impressive. Download Chrome and try the Dev Tools today if you haven’t already.

Firefox

Mozilla’s Firefox is my default browser. One indispensable Add-on that I’ve been using for years is Chris Pedrick’s Developer Tools, which you can also get for Chrome. When you install this add-on, you can:

  • Get the HTML source code in a nice, readable format
  • Get all of the CSS from any page you’re looking at, which includes external CSS as well as relative files.
  • You can enable and disable JavaScript
  • You can view all of the image information, including background images
  • You can outline all Block Level elements
  • You can also validate your HTML and CSS

For the responsive side of things, there is a Resize option. Here, you can resize the browser window itself to any pre-defined settings or settings that you add. If you choose Resize > View Responsive Layouts, you’ll get Mobile and Tablet views of your page in both Portrait and Landscape.

Firefox Responsive Layout

Another great Add-on for Firefox, which is very similar to Chrome’s developer tools if Firebug. Firebug has a tabbed interface where you can inspect your HTML, CSS, Scripts, and network activity. In the HTML tab, you can inspect the DOM. Rolling over an element will highlight it in the browser. The Style sheet is visible in the related Style panel. Here you can disable properties by clicking near them. You can also see a color chip for any colors that are specified.

Firebug

There are even Add-ons for Firebug, like YSlow, an Add-on that gives you performance data on web page load times and gives you advice on how to improve performance, which I’ve been using lately.

Although Firebug is pretty powerful, Firefox has its own set of developer tools. Steadily getting better, this suite of tools has all the things you’d come to expect with some additional features, one of them being a Responsive Design View.

Firefox Developer Tools

Click on the icon to the left of the Gear and you’ll be put into this view. There’s a list of preset sizes for Mobile and Tablet devices. You can change the orientation of the view with the arrow icon. Click the pointer finger icon to enable touch events, and you can take snapshots of each view.

Responsive Design View

I’ve been using this view over the past few weeks to test a responsive design and it’s been pretty reliable.

I should mention that Mozilla has just introduced Firefox Developer Edition. I just started playing around with this, but it has a really nice looking interface that’s easier on the eyes.

Firefox Developer Edition

Safari

Apple’s Safari has some built-in developer tools that have to be enabled. Go to Safari > Preferences and in the Advanced tab, choose Show Develop menu in menu bar. You may have to restart Safari afterwards.

Safari Preferences

Comparable to Chrome and Firefox, Safari has a web inspector in the Resources tab. You can also get to the CSS by enabling the Styles panel on the right. You can also inspect Layers (Absolutely positioned Divs) and HTML Node information. External resources can be inspected, like fonts, images, JavaScript and Stylesheet files. Clicking on these items on the left gives you a nice preview in the center panel.

Safari Dev Tools

Out of the box though, there are no responsive views. There is an extension called ResponsiveResize that you can download and install for Safari that will allow you to view common mobile and tablet sizes. You can also add your own custom sizes.

ResponsiveResize Safari Extension

Simply click on a size button and the browser will resize for that particular dimension.

Internet Explorer

There have been occasions where I had to view a page in IE because something wasn’t working right. “Does IE have developer tools?” I asked myself, and yes it does, though not as robust as the other’s mentioned here. Go to Tools > Developer Tools or F12 (In IE 8), and you’ll see an HTML inspector. The Style panel will show the styles of an element that you click on. There is no highlighting as you hover over elements, but if you click on the cursor icon at the top left of the panel, and move your mouse over the page, it will outline those elements.

Internet Explorer Dev Tools

At the top of this panel is a menu and under Tools, there’s a resize option. You can choose from some preset sizes and you can add your own custom sizes. This resizes the browser window. Although it’s not an elegant experience, at least there are some tools available. I haven’t explored these tools for IE9 or 10, so if you have and think they’re better, by all means, comment on this post and let us know.

Summary

Browser emulation is nothing like viewing your page on an actual device and this approach is not meant to be a replacement of that method. I, like many other people, don’t have a lot of time and resources to develop a device testing lab. With responsive design, one of the key things is to see how the pages flex and how elements on the page resize and shift as the scale is reduced or expanded. I like Firefox’s built-in Responsive Design View for this.

Hopefully, this will be helpful information for those getting started with RWD or anyone who’s doing web development in general. Next time, we’ll start getting into Responsive Typography and talk about the almight Em.

RWD – The HTML5 Shim for Internet Explorer

Posted on: November 17th, 2014 by alemieux

HTML5 + IE

Last time, we took a look at the HTML Viewport Meta tag, which is important for getting your site to look good on mobile. Since our HTML standard is HTML5, we need to make sure it works in older versions of Internet Explorer. I’m not considering IE6 in this conversation, although according to this site, 1.7% of the world is still on it. So that leaves IE8 and 9. As you can see from HTML5 Readiness, that IE8 and 9 are lacking in HTML5 powers. So IE10 will have the fullest support of HTML5 and CSS3, but we can’t ignore IE8 and 9 users. In fact, in some workplace environments, those browsers are enforced by IT policies.

Since HTML5 tags like <section>, <aside>, <footer>, and <figure> are not in the XHTML spec, they won’t be recognized by IE. But IE will go into quirks mode when encountering these elements, but all of them will be styles as inline elements. There’s 2 issues at play here, the fact that IE won’t recognize the elements and how they are being styled. Most normalize style sheets, like this one from Nicholas Gallagher and Jonathan Neal, will take care of the styling of the elements as block level instead of inline elements. Here’s how we do that:

article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
main,
menu,
nav,
section,
summary {
display: block;
}

In order to make IE recognize the elements themselves, we could add them to the document with JavaScript, but Remy Sharp has already done that for us with a script called the HTML5 shiv. You’ll need to put this into a conditional statement in the head section of your document. One key thing about the shiv that I’ve discovered is that it needs to placed after all of your stylesheet calls, both external and internal:

<!–[if lt IE 9]>
<script src=”js/html5shiv.js”></script>
< ![endif]–>

The conditional statement says something like, if the browser is anything less than IE9, add this JavaScript to the document. Here, I’m referencing the script locally for other reasons, but you can also reference it this way:

<!–[if lt IE 9]>
<script src=”http://html5shiv.googlecode.com/svn/trunk/html5.js”></script>
< ![endif]–>

Break out the wineglass and celebrate! Now you are ready to use HTML5 in all its glory and be sure that it’s supported on those older browsers. Not so much though. You should still test on those browsers as I have seen odd things happen to HTML5 docs in them. As always, be sure to validate your HTML.

Next time, we’ll talk about Mobile site design testing and some tools and resources for simulating and testing.

RWD – Viewports

Posted on: November 14th, 2014 by alemieux

This will be the start of a series on responsive web design (RWD), a topic of great importance nowadays, with lots of directions and advice. I’ll focus on the necessary aspects for those who are just getting started.

The Viewport

Typical Viewports

One of the first aspects that needs to be addressed when developing a site for mobile devices is the viewport width and scale. When viewing sites on an iPhone, for example, the default experience (if the site has not been developed with Responsive Web Design in mind) is a lot of pinching, zooming, and scrolling on the users part. Without the viewport width and scale being considered, the iPhone is rendering the page in a way that it can be viewed entirely, which will make all of the text incredibly small and unreadable.

The viewport on the iPhone (and other devices) is the area that determines how content is laid out and where text wraps on the webpage. Additionally, the viewport can be larger or smaller than the visible area1.

With the default viewport setting, the content will appear in the viewport without any scaling and not necessarily at the width of the viewport. In order to change that, we need to apply a Meta tag in the head section of our HTML document:

<meta name=“viewport” content=“width=device-width, initial-scale=1” />

There are actually a bunch of attributes other than what’s being shown here, but this code snippet has been widely adopted 2. The 2 attributes we’re most concerned with are width and scaling.

Viewport Width

You could set this up to be whatever width you want to target, but since we’re talking about responsive design, the best thing to do is set the width to the device width. This will tell the browser to show the webpage at its own device width3. The effect will be that the page will be readable and will not require so much pinching, zooming, and scrolling.

Viewport Scaling

Here’s an example of a site viewed on an iPhone without the viewport scale set:

Setting the initial-scale does 2 things:

  1. It sets the inital zoom factor of the page to the defined value, calculated relative to the ideal viewport. Thus it generates a visual viewport width.
  2. It sets the layout viewport width to the visual viewport width it just calculated.4

The initial scale attribute is a ratio of 1 and will scale the content to the edge of the viewport. When it is set to 1 the page isn’t zoomed in.

Site with No Viewport Set Site with Viewport
In this example, the Viewport Meta tag is not included in the code and therefore, iOS uses its default width and scaling In this example, the Viewport Meta tag is set. Notice the scaling and width of the site.

Now your page will render correctly within the viewport on mobile devices.

Next time, we’ll tackle HTML5 and how to make it work with older browsers.

  1. Safari Developer Library: Configuring the Viewport https://developer.apple.com/library/safari/documentation/AppleApplications/Reference/SafariWebContent/UsingtheViewport/UsingtheViewport.html
  2. Responsive Meta Tag: http://css-tricks.com/snippets/html/responsive-meta-tag/
  3. Understanding The Viewport Meta Tag: http://www.paulund.co.uk/understanding-the-viewport-meta-tag
  4. Meta viewport: http://www.quirksmode.org/mobile/metaviewport/

Make a game with EaselJS and the HTML5 Canvas

Posted on: April 30th, 2013 by alemieux
Guessing Game

Play the game now

The HTML5 Canvas element is a container that can be used to dynamically draw graphics with a lot of help from JavaScript. The canvas tag itself is very simple:

                &lt;canvas id=<span style="color: #f32038;">"gamespace"</span> width=<span style="color: #f32038;">"800"</span> height=<span style="color: #f32038;">"600"</span>&gt;&lt;/canvas&gt;

An ID is given to the canvas so that we can reference it with JavaScript and a width and height is defined. Since the canvas is a graphical space, you’ll notice that when you right click on it, your browser will allow you to save it as an image.

You can draw some basic shapes and text into the canvas with JavaScript. You can also import graphics into the canvas. This makes the canvas a dynamic environment for building games, dynamic charts, and other web applications.

EaselJS

The native code for working with canvas is a little cumbersome. Having come from a Flash/ActionScript background, EaselJS is a much better way to work with canvas. Part of CreateJS, a robust JavaScript library specifically geared towards developers coming from an ActionScript background, EaselJS has a tremendously easy to read API and syntax that’s immediately recognizable.

Along with EaselJS, you can add animation to objects in the canvas with TweenJS. If you’ve ever worked with TweenLite from Greensock, you’ll feel right at home with TweenJS.

No HTML game is complete without sound effects and cheezy soundtracks. You can add audio to the canvas with SoundJS. Very similar to how AS3 handles sound, SoundJS lets you load sounds, and has complete and progress methods.

Finally, you can create attractive preloaders for loading all of the game content with PreloadJS. PreloadJS can monitor load events and can track the progress of loaded objects.

The online documentation and downloadable samples are a great starter. You can get the code via CDN, github, or zip.

Game Setup

In this example, I’m creating a simple guessing game using Star Wars as a theme. There will be a few visual questions presented to the user. If they answer correctly or incorrectly, visual and audio feedback will be provided. If they get all of the questions correct, they are presented with a congratulatory screen with visual and audio feedback. If they answer incorrectly on any questions, they are presented with a different screen with negative visual and audio feedback.

The HTML

There isn’t a lot going on in the HTML file itself. A few styles and a lot of JavaScript library loading. Here, I am keeping everything local, but you can use the CDN links for the libraries. It took a little while to figure out exactly which files needed to be loaded and in which order. I looked at the example files for help. These files were minified, but I changed the names before linking them to the HTML file. In total, there are 6 libraries I’m pulling in and my own script file, which contains all of the logic for the game. The JS files are loaded in as follows:

  • js/easeljs.js
  • js/tweenjs.js
  • js/game.js
  • js/Sound.js
  • js/HTMLAudioPlugin.js
  • js/WebAudioPlugin.js
  • js/preloadjs.js

Imagery and Sounds

I didn’t spend a great deal of time on the imagery, but was able to quickly find what I needed on Google Images. I made the buttons and the interface features in Photoshop and exported as PNGs. Then I used imageOptim to compress the files further to make them smaller. Some of the splash screens are pretty big. Fortunately, there’s a lot of sound bites all over the web, so I also made quick work of finding quotes from the Star Wars movie for the game. In the SoundJS example files, I noticed that 2 file formats were being used: MP3 and OGG. The MP3’s were easy to find, but I had to convert to the OGG format. So I used Media.io in order to do the conversions and download them. The audio files are very small.

The JavaScript

The initial setup of the game is in the init() function at the top of the code. Here, a bunch of variables are being set for game parameters, text, bitmaps to import, an array of sounds to import, and the preloader code.

The variables are a comma separated list of constants. I start by declaring the canvas:

                stage <span style="color: #a2ac6f;">= new</span> createjs.<span style="color: #f8cf6d; font-weight: bold;">Stage</span>(canvas)

Next we need the constructors for all of the images to be loaded. EaselJS has a bitmap class for that. Here’s an example:

                logo <span style="color: #a2ac6f;">= new</span> createjs.<span style="color: #f8cf6d; font-weight: bold;">Bitmap</span>("img/logo.png")

For creating text, EaselJS has a Text class. The constructor is very similar to the Bitmap class as seen above:

                inst <span style="color: #a2ac6f;">= new</span> createjs.<span style="color: #f8cf6d; font-weight: bold;">Text</span>()

For those times when we need to center objects on the canvas, we declare a variable for the centerX and centerY positions on the canvas:

                centerX <span style="color: #a2ac6f;">=</span> canvas.width/<span style="color: #4bbeed;">2</span>,<br />
                centerY <span style="color: #a2ac6f;">=</span> canvas.height/<span style="color: #4bbeed;">2</span>

For game progress, there are a few variables that need to be set:

                questionPosition <span style="color: #a2ac6f;">=</span> <span style="color: #4bbeed;">0</span>,<br />
                numCorrect <span style="color: #a2ac6f;">=</span> <span style="color: #4bbeed;">0</span>,<br />
                numWrong <span style="color: #a2ac6f;">=</span> <span style="color: #4bbeed;">0</span>,

questionPosition will help us keep track of which question we’re on. numCorrect and numWrong will keep track of the question answered correctly and incorrectly.

We create an array of sounds called manifest that we’ll be using in the game with paths to the different versions (MP3 and OGG). Each sound is given an id that we can call on later when we want to play that sound.

                assetPath <span style="color: #a2ac6f;">=</span> <span style="color: #f32038;">"snd/"</span>,
                manifest = [{src:assetsPath<span style="color: #a2ac6f;">+</span><span style="color: #f32038;">"Theme - Star Wars.mp3|"</span>+assetsPath<span style="color: #a2ac6f;">+</span><span style="color: #f32038;">"Theme - Star Wars.ogg"</span>, id:<span style="color: #f32038;">"theme"</span>},<br />
                 {src:assetsPath<span style="color: #a2ac6f;">+</span><span style="color: #f32038;">"blaster.mp3|"</span><span style="color: #a2ac6f;">+</span>assetsPath<span style="color: #a2ac6f;">+</span><span style="color: #f32038;">"blaster.ogg"</span>, id:<span style="color: #f32038;">"buttonSnd"</span>},<br />
                 {src:assetsPath<span style="color: #a2ac6f;">+</span><span style="color: #f32038;">"powrweak.mp3|"</span><span style="color: #a2ac6f;">+</span>assetsPath<span style="color: #a2ac6f;">+</span><span style="color: #f32038;">"powrweak.ogg"</span>, id:<span style="color: #f32038;">"powerWeak"</span>},<br />
                 {src:assetsPath<span style="color: #a2ac6f;">+</span><span style="color: #f32038;">"cocky.mp3|"</span><span style="color: #a2ac6f;">+</span>assetsPath<span style="color: #a2ac6f;">+</span><span style="color: #f32038;">"cocky.ogg"</span>, id:<span style="color: #f32038;">"cocky"</span>},<br />
                 {src:assetsPath<span style="color: #a2ac6f;">+</span><span style="color: #f32038;">"haveyou.mp3|"</span><span style="color: #a2ac6f;">+</span>assetsPath<span style="color: #a2ac6f;">+</span><span style="color: #f32038;">"haveyou.ogg"</span>, id:<span style="color: #f32038;">"haveYou"</span>},<br />
                 {src:assetsPath<span style="color: #a2ac6f;">+</span><span style="color: #f32038;">"strong.mp3|"</span><span style="color: #a2ac6f;">+</span>assetsPath<span style="color: #a2ac6f;">+</span><span style="color: #f32038;">"strong.ogg"</span>, id:<span style="color: #f32038;">"strong"</span>}],

Each sound is inserted in brackets and the two types of sounds are separated by a pipe.

For preloading the images, we need to set up a queue and make an array. PreloadJS can do more than preload images, but I was only interested in preloading the image content, since the sound files are very small.

The queue looks like this:

                queue.loadManifest([<span style="color: #f32038;">"img/starfield.png"</span>,<span style="color: #f32038;">"img/logo.png"</span>,<span style="color: #f32038;">"img/START-GAME.png"</span>...]);

Then, we tell the queue to load. You can fire functions with event listeners to watch for complete, progress, Here, I’m only reporting the results to the console:

                queue.load();<br />
                queue.addEventListener(<span style="color: #f32038;">"complete"</span>, showManifest);<br />
                queue.addEventListener(<span style="color: #f32038;">"progress"</span>, showProgress);<br />
                <span style="color: #4bbeed;">function</span> <span style="color: #f8cf6d; font-weight: bold;">showProgress</span>(evt) {<br />
                    <span style="color: #4bbeed;">var</span> perc = evt.loaded / evt.total;<br />
                    <span style="color: #e39247;">console</span>.log(Math.ceil(perc<span style="color: #a2ac6f;">*</span><span style="color: #4bbeed;">100</span>).toString());<br />
                }
                function showManifest() {<br />
                    <span style="color: #e39247;">console</span>.log(<span style="color: #f32038;">"Files are loaded");<br />
                }
                </span>

For all the sounds to play, a listener is added and the sound manifest is then registered. You can create fancy progress bars for the sounds to load and such with a progress handler. I didn’t need that here, so the function fileload() is simply reporting to the console when the files are all loaded:

                createjs.Sound.addEventListener(<span style="color: #f32038;">"fileload"</span>, createjs.proxy(soundLoaded, this));<br />
                createjs.Sound.registerManifest(manifest);<br />
                <br />
                <span style="color: #4bbeed;">function</span> <span style="color: #f8cf6d; font-weight: bold;">soundLoaded</span>(event) {<br />
                    <span style="color: #e39247;">console</span>.log(<span style="color: #f32038;">"sounds loaded"</span>);<br />
                }

At the beginning of the game, the Star Wars theme music plays as the logo fades in and then the instructions appear. To play any sound with SoundJS we use the play() function and feed it the id of the sound as a string:

                createjs.Sound.play(<span style="color: #f32038;">"theme"</span>);

Just as in the original Star Wars movie, the logo is seen on a starfile up close and then fades off into the distance. This effect is achieved using TweenJS and EaselJS. Much like the setInterval class in AS3, the Ticker class in EaselJS allows you to set up simple animations of canvas objects. Here, the starfile and logo are added to the stage:

                stage.addChild(bg,logo);

The Ticker class is started with a frame rate of 30fps and then the logo is animated with the scaleX and scaleY properties – which should be very familiar to AS3 developers.

                createjs.<span style="color: #f8cf6d; font-weight: bold;">Ticker</span>.setFPS(<span style="color: #4bbeed;">30</span>);<br />
                createjs.<span style="color: #f8cf6d; font-weight: bold;">Ticker</span>.addEventListener(<span style="color: #f32038;">"tick"</span>, startAnim);<br />
                <span style="color: #4bbeed;">function</span> <span style="color: #f8cf6d; font-weight: bold;">startAnim</span>(e) {    <br />
                    logo.x <span style="color: #a2ac6f;">=</span> centerX;<br />
                    logo.y <span style="color: #a2ac6f;">=</span> centerY;<br />
                    logo.scaleX <span style="color: #a2ac6f;">-=</span> <span style="color: #4bbeed;">0.005</span>;<br />
                    logo.scaleY <span style="color: #a2ac6f;">-=</span> <span style="color: #4bbeed;">0.005</span>;<br />
                    <br />
                    stage.update();<br />
                }

In addition to scaling down in size, the logo fades out. I decided to try this with TweenJS. First, we set the alpha of the logo to 1, just as in ActionScript the alpha values are on a range from 0 – 1. Then, we perform the tween. This is a long, slow tween over 3 and a half seconds long. TweenJS allows you to chain animations together. In this case, I’m calling an onComplete() function which brings in the instructions and the start button:

                createjs.Tween.get(logo).to({alpha: <span style="color: #4bbeed;">0</span>},<span style="color: #4bbeed;">3600</span>).call(onComplete);

This is very similar to the way we construct tweens with TweenLite in AS3:

                TweenLite.to(mc, 3.5, {alpha:0});

In TweenLite you specify the object to be tweened, the duration and the property or properties to be tweened. In TweenJS you specify the object, the property or properties to be tweened and the duration.

Finally, we come to then end of the game initialization with the onComplete handler. This will bring in the instruction text and the start button. As in ActionScript, event handlers need to be removed for garbage collection. I didn’t come across anything in the online documentation for this, but I know it’s a best practice.

                removeEventListener(<span style="color: #f32038;">"tick"</span>, startAnim);

The start button and the instruction text are both tweened in with TWeenJS. In EaselJS, there are several text properties that can be set. Here, I’m setting some basic settings like font, color, and lineHeight. For the font and color settings, you can specify those as you would with CSS. Once the text properties are set, the text is added to the stage and the alpha property is tweened.

                stage.addChild(startButton);<br />
                createjs.Tween.get(startButton).to({y:<span style="color: #4bbeed;">370</span>}, <span style="color: #4bbeed;">1000</span>);<br />
                startButton.x = <span style="color: #4bbeed;">245</span>;<br />
                startButton.y = <span style="color: #4bbeed;">620</span>;<br />
                <br />
                inst.text = <span style="color: #f32038;">"Welcome to the Star Wars Guessing Game. This game will test if\n you are a true Star Wars fan. In the next few screens, you will be shown some\n images from the Star Wars Universe. Identify the correct image to advance.\n If not, the Empire takes over the Galaxy.\n\n May the force be with you."</span>;<br />
                inst.font = <span style="color: #f32038;">"normal 24px Myriad Pro, 'MyriadPro', sans-serif"</span>;<br />
                inst.color = <span style="color: #f32038;">"#298FC2"</span>;<br />
                inst.linewidth = <span style="color: #4bbeed;">200</span>;<br />
                inst.textAlign = <span style="color: #f32038;">"center"</span>;<br />
                inst.textBaseline = <span style="color: #f32038;">"top"</span>;<br />
                <br />
                inst.lineHeight = <span style="color: #4bbeed;">26</span>;<br />   
                <br />
                inst.x = centerX;<br />
                inst.y = <span style="color: #4bbeed;">180</span>;<br />
                <br />
                stage.addChild(inst);<br />
                inst.alpha = <span style="color: #4bbeed;">0</span>;<br />
                createjs.Tween.get(inst).to({alpha:<span style="color: #4bbeed;">1</span>},<span style="color: #4bbeed;">1000</span>);

Questions

The question functions are very similar. A question area is dynamically drawn on the stage using the drawRoundRect() method. There are 5 parameters, X, Y, Width, Height, and Radius. The question text is added to the stage and 3 images related to the question are shown. The user clicks on the image they think is correct. We increment questionPosition. Either the answerCorrect() or answerWrong() functions will be called when they do that. TweenJS is used again to fade in the images:

                questionPosition<span style="color: #a2ac6f;">++</span>;<br />
                stage.removeChild(inst,startButton);<br />
                <br />
                qArea.graphics.beginStroke(<span style="color: #f32038;">"#298FC2"</span>);<br />
                qArea.graphics.setStrokeStyle(<span style="color: #4bbeed;">10</span>,<span style="color: #4bbeed;">0</span>,<span style="color: #4bbeed;">1</span>);<br />
                qArea.graphics.beginFill(<span style="color: #f32038;">"#ffffff"</span>);<br />
                qArea.graphics.drawRoundRect(<span style="color: #4bbeed;">50</span>, <span style="color: #4bbeed;">87</span>, <span style="color: #4bbeed;">700</span>, <span style="color: #4bbeed;">425</span>, <span style="color: #4bbeed;">10</span>);<br />
                <br /> 
                stage.addChild(qArea);<br />
                <br />
                stage.addChild(ewok);<br />
                ewok.alpha = <span style="color: #4bbeed;">0</span>;<br />
                createjs.Tween.get(ewok).to({alpha: <span style="color: #4bbeed;">1</span>},<span style="color: #4bbeed;">500</span>);<br />
                ewok.x = <span style="color: #4bbeed;">70</span>;<br />
                ewok.y = <span style="color: #4bbeed;">150</span>;<br />
                stage.addChild(wookie);<br />
                wookie.alpha = <span style="color: #4bbeed;">0</span>;<br />
                createjs.Tween.get(wookie).to({alpha: <span style="color: #4bbeed;">1</span>},<span style="color: #4bbeed;">500</span>);<br />
                wookie.x = <span style="color: #4bbeed;">290</span>;<br />
                wookie.y = <span style="color: #4bbeed;">150</span>;<br />
                stage.addChild(gungan);<br />
                gungan.alpha = <span style="color: #4bbeed;">0</span>;<br />
                createjs.Tween.get(gungan).to({alpha: <span style="color: #4bbeed;">1</span>},<span style="color: #4bbeed;">500</span>);<br />
                gungan.x = <span style="color: #4bbeed;">510</span>;<br />
                gungan.y = <span style="color: #4bbeed;">150</span>;<br />
                <br />
                q.text = q1;<br />
                q.font = <span style="color: #f32038;">"normal 24px Myriad Pro, 'MyriadPro', sans-serif"</span>;<br />
                q.color = <span style="color: #f32038;">"#298FC2"</span>;<br />
                q.textAlign = <span style="color: #f32038;">"center"</span>;<br />
                <br />
                stage.addChild(q);<br />
                q.x = <span style="color: #4bbeed;">400</span>;<br />
                q.y = <span style="color: #4bbeed;">450</span>;<br />
                <br />
                ewok.<spanc class="class">onClick = <span style="color: #4bbeed;">function</span>() {<br />
                    answerWrong();<br />
                }<br />
                gungan.<span style="color: #f8cf6d; font-weight: bold;">onClick</span> = <span style="color: #4bbeed;">function</span>() {<br />
                    answerWrong();<br />
                }<br />
                wookie.<span style="color: #f8cf6d; font-weight: bold;">onClick</span> = <span style="color: #4bbeed;">function</span>() {<br />
                    answerCorrect();<br />
                }<br />
                </spanc>

The order in which you add items to the stage is pretty important here. For example, if I added the question area last, it would hide all of the text and graphics. By adding it first, the text and graphics are loaded on top of it.

Again, garbage collection is important. I created a clearScreen() function to remove the some of the basic stuff and additionally removed objects in each subsequent question using removeChild().

Of course, the user starts the game by clicking the start button. Here, there are no rollover effects on the button. Those certainly could’ve been added with EaselJS, but rollovers don’t translate for tablet and mobile use anyway. Clicking the start button calls the question1() function and game play begins with the sound of a blaster!

                startButton.<span style="color: #f8cf6d; font-weight: bold;">onClick</span> = <span style="color: #4bbeed;">function</span>() {<br />
                    question1();<br />
                    createjs.Sound.play(<span style="color: #f32038;">"buttonSnd"</span>);<br />
                }

Checking the Answers

When a question is answered, it will be handled by answerCorrect() or answerWrong() methods, which will: play a sound, show a visual and allow the user to continue to the next question. If all of the questions have been answered, the continueFinal function is called.

                <span style="color: #4bbeed;">function</span> <span style="color: #f8cf6d; font-weight: bold;">answerCorrect</span>() {<br />
                    // console.log(<span style="color: #f32038;">"The force is strong with this one!"</span>);<br />
                    createjs.Sound.play(<span style="color: #f32038;">"strong"</span>);<br />
                    questionCorrect = true;<br />
                    numCorrect++;<br />
                    stage.addChild(rightAnswer);<br />
                    rightAnswer.x = <span style="color: #4bbeed;">50</span>;<br />
                    rightAnswer.y = <span style="color: #4bbeed;">87</span>;<br />
                    <br />
                    correctMsg.text = <span style="color: #f32038;">"The force is strong with this one!"</span>;<br />
                    correctMsg.font = <span style="color: #f32038;">"normal 24px Myriad Pro, 'MyriadPro', sans-serif"</span>;<br />
                    correctMsg.color = <span style="color: #f32038;">"#298FC2"</span>;<br />
                    correctMsg.textAlign = <span style="color: #f32038;">"center"</span>;<br />
                    stage.addChild(correctMsg);<br />
                    correctMsg.x = <span style="color: #4bbeed;">400</span>;<br />
                    correctMsg.y = <span style="color: #4bbeed;">450</span>;<br />
                    <br />
                    if(questionPosition&lt;3) {<br />
                        stage.addChild(nextQbutton);<br />
                        nextQbutton.regX = <span style="color: #4bbeed;">384/2</span>;<br />
                        nextQbutton.regY = <span style="color: #4bbeed;">56/2</span>;<br />
                        nextQbutton.x = centerX;<br />
                        nextQbutton.y = <span style="color: #4bbeed;">520</span>;<br />
                    }<br />
                    <br />
                    if(questionPosition==3) {<br />
                        continueFinal();<br />
                    }<br />
                }

The answerWrong() method is very similar only it plays a different sound, has a different text message, and shows a different image.

Ending the Game

If all of the questions have been answered, continueFinal() is fired, which basically shows a continue button. Once again, TweenJS is used to animate the button into place. When the user clicks on that button, the endGame() method is called.

                <span style="color: #4bbeed;">function</span> <span style="color: #f8cf6d; font-weight: bold;">continueFinal</span>() {<br />
                    stage.addChild(continueButton);<br />
                    continueButton.regX = <span style="color: #4bbeed;">384</span>/<span style="color: #4bbeed;">2</span>;<br />
                    continueButton.regY = <span style="color: #4bbeed;">56</span>/<span style="color: #4bbeed;">2</span>;<br />
                    continueButton.x = centerX;<br />
                    continueButton.y = <span style="color: #4bbeed;">0</span>;<br />
                    continueButton.alpha = <span style="color: #4bbeed;">0</span>;<br />
                    createjs.Tween.get(continueButton).to({y:<span style="color: #4bbeed;">520</span>, alpha: <span style="color: #4bbeed;">1</span>}, <span style="color: #4bbeed;">1000</span>);<br />
                    <br />
                    continueButton.<span style="color: #f8cf6d; font-weight: bold;">onClick</span> = <span style="color: #4bbeed;">function</span>() {<br />
                        endGame();<br />
                    }
                }

At the end of the game if you’ve answered all of the questions correctly, you’ll see an image of Luke, Leia, and Han and hear some audio. If you’ve missed any questions, then you’ll see Darth Vader and Obi-Wan Kenobi dueling with their lightsabers and hear Darth say “Your powers are weak old man”.

                function <span style="color: #f8cf6d; font-weight: bold;">endGame</span>() {<br />
                    clearScreen();<br />
                    stage.removeChild(continueButton);<br />
                    <span style="color: #4bbeed;">var</span> results <span style="color: #a2ac6f;">= new</span> createjs.<span style="color: #f8cf6d; font-weight: bold;">Text</span>();<br />
                    results.text =  <span style="color: #f32038;">""</span>;<br />
                    results.font = <span style="color: #f32038;">"normal 24px Myriad Pro, 'MyriadPro', sans-serif"</span>;<br />
                    results.color = <span style="color: #f32038;">"#298FC2"</span>;<br />
                    results.textAlign = <span style="color: #f32038;">"center"</span>;<br />
                    <br /> 
                     <span style="color: #a2ac6f;">if</span>(numCorrect==<span style="color: #4bbeed;">3</span>) {<br />
                        createjs.Sound.play(<span style="color: #f32038;">"cocky"</span>);<br />
                        stage.addChild(endGood);<br />
                        endGood.x = <span style="color: #4bbeed;">50</span>;<br />
                        endGood.y = <span style="color: #4bbeed;">87</span>;<br />
                        <br />
                        results.text = <span style="color: #f32038;">"Great job kid, don't get too cocky!"</span>;<br />
                        stage.addChild(results);<br />
                        results.x = <span style="color: #4bbeed;">400</span>;<br />
                        results.y = <span style="color: #4bbeed;">450</span>;<br />
                    } <span style="color: #a2ac6f;">else</span> {<br />
                        createjs.Sound.play(<span style="color: #f32038;">"powerWeak"</span>);<br />
                        stage.addChild(endBad);<br />
                        endBad.x = <span style="color: #4bbeed;">50</span>;<br />
                        endBad.y = <span style="color: #4bbeed;">87</span>;<br />
                        <br />
                        results.text = <span style="color: #f32038;">"Your powers are weak old man!"</span>;<br />
                        stage.addChild(results);<br />
                        results.x = <span style="color: #4bbeed;">400</span>;<br />
                        results.y = <span style="color: #4bbeed;">450</span>;<br />
                    }<br />
                }<br />

And that’s the end of the code review. There’s only 3 questions in here, but other questions can easily be added here. I suppose the questions could be randomized too. The point of this whole thing was to get a handle on CreateJS and see what it could do and to compare it with ActionScript.

Summary

I’ll admit, that the first time I looked at CreateJS, it was daunting and I was skeptical. But once I looked at the examples and really dug into the code, I could immediately see the potential and I hope you can too.

Download the source files below:

Download