A Dive Into Plain JavaScript

While I’ve worked over a decade building various websites, it has only been the past 3 years that I’ve started learning more on how to work with plain JavaScript, instead of using jQuery always as the starting point. The fact that I’m learning a dozen new things every day now, has made working on Adtile’s JavaScript SDK feel more like building an open source project than actual work, and I have to say I like that a lot.

Today, I’m going to share some of the basic things I’ve learned during the past years, which will hopefully also help you to dive into the world of plain JavaScript, making it easier to decide whether or not you will need jQuery in your next project.

Progressive Enhancement

While libraries like jQuery help to forget most of the browser inconsistencies, you really become familiar with them once you start using plain JavaScript for everything. To avoid writing JavaScript that’s full of browser hacks and code which only solves browser compatibility issues, I recommend building a progressively enhanced experience using feature detection to only target the more modern browsers. This doesn’t mean that browsers like IE7 don’t see anything at all, it just means that they get a more basic experience without JavaScript enhancements.

Here’s How We’re Doing It

We have a separate JavaScript partial which has all the feature tests. The actual list of tests is often much longer, but let’s get back to this a bit later. To rule out some of the older browsers we use these two tests:

1
2
3
4
var test = {
  addEventListener : !!window.addEventListener,
  querySelectorAll : !!document.querySelectorAll,
};

Then, in the main application partial, we detect if these features are supported by using this simple if statement below. If they aren’t supported, the browser won’t execute any of this code:

1
2
3
if (test.addEventListener && test.querySelectorAll) {
  this.init();
}

These two tests make sure that we have a native way of using CSS selectors in our JavaScript (querySelectorAll), a way to easily add and remove events (addEventListener) and also that the browser’s standards support is better than what IE8 has. Read more about this technique called “Cutting the mustard” from BBC’s blog.

Browser Support

Here’s a rough list of the browsers which support the features we are testing, and will hence keep executing the JavaScript:

  • IE9+
  • Firefox 3.5+
  • Opera 9+
  • Safari 4+
  • Chrome 1+
  • iPhone and iPad iOS1+
  • Android phone and tablets 2.1+
  • Blackberry OS6+
  • Windows 7.5+
  • Mobile Firefox
  • Opera Mobile

The Basics, Plain JavaSript Way

Let’s start looking how the most basic and often needed functionalities work in plain JavaScript, compared to jQuery. For each example, I’m going to provide both the jQuery and plain JavaScript approach.

Document Ready

With jQuery, many are probably used to using document.ready like so:

1
2
3
$(document).ready(function() {
  // Code
});

But did you know that you can just put all of your JavaScript at the bottom of your page and that does basically the same thing? JavaScript has also an event listener for the DOM content loaded event which you can use instead of jQuery’s document.ready:

1
2
3
document.addEventListener("DOMContentLoaded", function() {
  // Code
}, false);

Selectors API

JavaScript’s native selectors API is very good. It works with CSS selectors and is very similar to what jQuery provides. If you are used to writing this in jQuery:

1
var element = $("div");

You can now replace that with:

1
var element = document.querySelector("div");

Or, to select all div’s inside some container:

1
var elements = document.querySelectorAll(".container div");

You can also query against a specific element to find it’s children:

1
2
var navigation = document.querySelector("nav");
var links = navigation.querySelectorAll("a");

Quite straightforward, easy to understand, and doesn’t really require much more writing now does it? To go a little further, we could even build a tiny JavaScript library for ourselves for simple DOM querying. Here’s something that Andrew Lunny has came up with:

1
2
3
4
5
6
// This gives us simple dollar function and event binding
var $ = document.querySelectorAll.bind(document);
Element.prototype.on = Element.prototype.addEventListener;

// This is how you use it
$(".element")[0].on("touchstart", handleTouch, false);

Traversing the DOM

Traversing the DOM with plain JavaScript is a bit harder than it is with jQuery. But not too hard. Here are some simple examples:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Getting the parent node
var parent = document.querySelector("div").parentNode;

// Getting the next node
var next = document.querySelector("div").nextSibling;

// Getting the previous node
var next = document.querySelector("div").previousSibling;

// Getting the first child element
var child = document.querySelector("div").children[0];

// Getting the last child
var last = document.querySelector("div").lastElementChild;

Adding and Removing Classes

With jQuery, adding, removing and checking if an element has certain classes is really simple. It’s a bit more complex with plain JavaScript, but not too much so. Giving element a class called "foo" and replacing all the current classes:

1
2
3
4
5
// Select an element
var element = document.querySelector(".some-class");

// Give class "foo" to the element
element.className = "foo";

Adding a class without replacing the current classes:

1
element.className += " foo";

Removing "no-js" class from html-element and replacing it with "js":

1
2
3
4
5
6
<html class="no-js">
<head>
  <script>
    document.documentElement.className = "js";
  </script>
……

That was quite straightforward, right? Next step, removing only certain classes, is a bit more complex. I’ve been using this small helper function in a separate partial called util.js. It takes 2 parameters: element and the class you want to remove:

1
2
3
4
5
// removeClass, takes two params: element and classname
function removeClass(el, cls) {
  var reg = new RegExp("(\\s|^)" + cls + "(\\s|$)");
  el.className = el.className.replace(reg, " ").replace(/(^\s*)|(\s*$)/g,"");
}

Then, in the main application partial, I’ve been using it like so:

1
removeClass(element, "foo");

If you also want to check an element against some class, kind of like jQuery’s hasClass works, you could add this in your utils:

1
2
3
4
// hasClass, takes two params: element and classname
function hasClass(el, cls) {
  return el.className && new RegExp("(\\s|^)" + cls + "(\\s|$)").test(el.className);
}

…and use it like so:

1
2
3
4
5
6
// Check if an element has class "foo"
if (hasClass(element, "foo")) {

  // Show an alert message if it does
  alert("Element has the class!");
}

Introducing HTML5 classList API

If you only need to support more modern browsers like IE10+, Chrome, Firefox, Opera and Safari, you could also start using HTML5’s classList functionality which makes adding and removing classes even easier.

This is something, that I ended up doing with our latest Developer Docs, as the functionality I was developing, was more like an enhancement to the UI and not really something that would break the experience if it wasn’t present.

You can detect if the browser supports the classList API by using this simple if statement:

1
2
3
if ("classList" in document.documentElement) {
  // classList is supported, now do something with it
}

Adding, removing and toggling classes with classList:

1
2
3
4
5
6
7
8
9
10
11
// Adding a class
element.classList.add("bar");

// Removing a class
element.classList.remove("foo");

// Checking if has a class
element.classList.contains("foo");

// Toggle a class
element.classList.toggle("active");

One other benefit of using classList is that it will perform much better than using the raw className property. If you had an element like this:

1
<div id="test" class="one two three"></div>

Which you’d want to manipulate:

1
2
3
var element = document.querySelector("#test");
addClass(element, "two");
removeClass(element, "four");

For each of these methods the className property would be read from and then written to, triggering a browser repaint. However, this is not the case if we use the relevant classList methods instead:

1
2
3
var element = document.querySelector("#test");
element.classList.add("two");
element.classList.remove("four");

With classList the underlying className is only altered when necessary. Given that we are adding a class that is already present and removing a class that isn’t, the className is never touched, meaning we’ve just avoided two repaints!

Event Listeners

Adding and removing event listeners from elements is almost as simple in plain JavaScript as it’s in jQuery. Things get a bit more complex when you have to add multiple event listeners, but I’ll explain that in a bit. The simplest example, which will just pop out an alert message when an element is clicked, is as follows:

1
2
3
element.addEventListener("click", function() {
  alert("You clicked");
}, false);

To achieve this same functionality on all of the elements on a given page, we have to loop through each element, and give them all eventListeners:

1
2
3
4
5
6
7
8
9
10
11
12
13
// Select all links
var links = document.querySelectorAll("a");

// For each link element
[].forEach.call(links, function(el) {

  // Add event listener
  el.addEventListener("click", function(event) {
    event.preventDefault();
    alert("You clicked");
  }, false);

});

One of JavaScript’s greatest features related to event listeners is the fact that addEventListener can take an object as a second argument that will automatically look for a method called handleEvent and call it. Ryan Seddon has covered this technique thoroughly in his article, so I’m just gonna give a fast example and you can read more about it from his blog:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var object = {
  init: function() {
    button.addEventListener("click", this, false);
    button.addEventListener("touchstart", this, false);
  },
  handleEvent: function(e) {
    switch(e.type) {
      case "click":
        this.action();
        break;
      case "touchstart":
        this.action();
        break;
    }
  },
  action: function() {
    alert("Clicked or touched!");
  }
};

// Init
object.init();

Manipulating the DOM

Manipulating the DOM with plain JavaScript might sound like a horrible idea at first, but it really isn’t much more complex that using jQuery. Below, we have an example that selects an element from the DOM, clones it, manipulates the clone’s styles with JavaScript and then replaces the original element with the manipulated one.

1
2
3
4
5
6
7
8
9
10
11
// Select an element
var element = document.querySelector(".class");

// Clone it
var clone = element.cloneNode(true);

// Do some manipulation off the DOM
clone.style.background = "#000";

// Replaces the original element with the new cloned one
element.parentNode.replaceChild(clone, element);

If you don’t want to replace anything in the DOM, but instead append the newly created div inside the <body>, you could do it like this:

1
document.body.appendChild(clone);

If you feel like you’d want to read even more about different DOM methods, I’d suggest you to head over to Peter-Paul Koch’s DOM Core tables.

Diving Deeper

I’m going to share two bit more advanced techniques here, which I’ve recently discovered. These are both functionalities we have needed while building Adtile, so you might find these useful too.

Determining Max-Width of Responsive Images in JS

This is one of my own favorites, and it’s very useful if you ever need to manipulate fluid images with JavaScript. As browsers return the current resized dimensions of an image by default, we have to come up with some other solution. Luckily, modern browsers now have a way of doing this:

1
var maxWidth = img.naturalWidth;

This will give us image’s max-width: 100% value in pixels and it’s supported in IE9, Chrome, Firefox, Safari and Opera. We can also take this further and add support for older browsers by loading the image into an in-memory object:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Get image's max-width:100%; in pixels
function getMaxWidth(img) {
  var maxWidth;

  // Check if naturalWidth is supported
  if (img.naturalWidth !== undefined) {
    maxWidth = img.naturalWidth;

  // Not supported, use in-memory solution as fallback
  } else {
    var image = new Image();
    image.src = img.src;
    maxWidth = image.width;
  }

  // Return the max-width
  return maxWidth;
}

You should note that the images must be fully loaded before checking for the width. This is what we’ve been using to make sure they have dimensions:

1
2
3
function hasDimensions(img) {
  return !!((img.complete && typeof img.naturalWidth !== "undefined") || img.width);
}

Determining if an Element is in the Viewport

You can get the position of any element on the page using getBoundingClientRect method. Below is a simple function showing how simple and powerful it can be. This function takes one parameter, which is the element you want to check. It will return true when the element is visible:

1
2
3
4
5
6
7
8
9
10
11
// Determine if an element is in the visible viewport
function isInViewport(element) {
  var rect = element.getBoundingClientRect();
  var html = document.documentElement;
  return (
    rect.top >= 0 &&
    rect.left >= 0 &&
    rect.bottom <= (window.innerHeight || html.clientHeight) &&
    rect.right <= (window.innerWidth || html.clientWidth)
  );
}

The above function could be used by adding a “scroll” event listener to the window and then calling isInViewport().

Conclusion

Whether or not you should use jQuery in your next project depends a lot on what you are building. If it’s something that requires large amounts of front-end code, you should probably use it. However, if you’re building a JavaScript plugin or a library, you might want to consider sticking with just plain JavaScript. Using plain JavaScript means fewer requests and less data to load. It also means that you aren’t forcing developers to add jQuery to their project just because of that dependency. ❦

This article was originally published on Adtile’s blog.

A New Path

Today, after over two years, I’ll be leaving my position at Kisko Labs. I’ve started working on a new responsive advertising solution for smartphones and tablets called Adtile. Another big news is, that we have just received a $2.7 million funding to bring this product to the market. There’s also a story about us on TechCrunch, so check that out.

Banner ads might still function well in print, but it’s clear that they just don’t work on screen and especially on mobile devices anymore. Instead of trying to make the current model work somehow, we decided to start with an entirely new idea and ditch the old model—and the annoying banners. As we are focusing on mobile and building a customizable SDK for both web and native app developers, we will be also building another device lab soon only for this purpose.

The company where I’ll be working at, TenFarms, is based in Los Angeles, so I will be most likely spending time in the US a lot more too. Besides Adtile, I’ll be soon revamping the whole web presence of our second product, Photopoll iOS application too.

Helsinki Device Lab, which I established about 10 months ago, will still stay at the Kisko Labs offices and I will be still maintaining it together with the Kisko guys, so that’s one thing which won’t change because of all this. The Helsinki Device Lab will also soon be at the Webshaped conference, so come say hello if you are coming there.

Kudos to everyone at Kisko Labs and thank you for the past years! I don’t think that I’ve ever been so productive or learned so much new in such a little time. That’s all because of y’all. I will miss you a lot, but will also be visiting the office occasionally to check the devices, do some testing, and to have a chat & tea with you. ❦

A Hot Air Balloon

Plugin For Responsive Navigation

Responsive Nav is a tiny JavaScript plugin which weighs only 1.6KB minified and Gzip’ed, and helps you to create a toggled navigation for small screens. It uses touch events and CSS3 transitions for the best possible performance. It also contains a “clever” workaround that makes it possible to transition to height: auto, which isn’t normally possible with CSS3 transitions. The plugin, along the site, was released today on Smashing Magazine.

Read the article

Prototyping Responsive Typography

The history of typography dates back about 5,000 years. It starts from a series of pictograms, which then evolved to hieroglyphs in Egypt and later around 1,200BC to Phoenician alphabets. Almost 2,500 years later the Chinese invented first movable type which later revolutionized everything in the west when Gutenberg invented latin movable type. Many of the basic concepts of typesetting are still the same as 500 years ago.

Web typography, and digital typography in general, is a huge step forward in this history. It has made setting type fast and easy compared with hand-setting metal type. Responsiveness, when added on top of this, makes this period of change we are living very fascinating. Not only is centuries old design theory being rewritten, but the process of how design happens is now changing too (as Mark Boulton states it).

Universality, as a design principle, should guide us when choosing fonts and when testing how our type works on various devices and platforms.

When talking about “responsive typography,” I don’t just mean flexible body text, but also that all our decisions should be based on universality. Universality, as a design principle, should guide us when choosing web fonts and when testing how our type works on various devices and platforms. It should be the core principle behind all the work we do.

Movable Type

New Process

About a year ago I wrote Responsive Workflow article describing my responsive design process. It was an article that gathered a lot of buzz, but I think it just scratched the surface a bit and never really tried to fully describe what’s happening behind the curtains. In this article I’m going to open the curtain and explain a new phase which I would today add to my year old workflow drawing. The new design phase is somewhere between prototyping and visual design phases, and I call it the “Typography Prototyping Phase.”

As I earlier in that article wrote, typography for the Web is really hard to design anywhere else than inside the browser. This is today even more true than it was a year ago. Typography prototype tries to solve this by doing the hard choices before jumping to other tools like Photoshop.

Basically, a typography prototype is a single web page that consists of the project’s actual content. It’s designed in the browser using real web fonts and tools like Typecast. A typography prototype includes font choices, styles for the basic text content and a typographic scale, but nothing else.

Content precedes design. Design in the absence of content is not design, it’s decoration.”

– Jeffrey Zeldman

Planting the seed

All our decisions should start from the content out, not canvas in. This means we shouldn’t start doing any design work before having the project’s actual content on hand (or something that is very near the actual content). That’s because the content and the language used has a big impact on how our typography will work. This is especially true with display type and headers, but also with paragraphs and line-lengths. Having the real content also helps to judge if the font choices fit the mood correctly.

Below is an example of what the typography prototype looks like before any styles have been applied. This basic HTML page is already responsive on its own—by default, like Andy Hume states it, so you can immediately start testing how it works on various devices:

Typography prototype, example 1

Choosing typefaces

Choosing type combinations, which are legible and readable across multiple devices and operating systems isn’t easy. Windows XP, which still has relatively high usage percent globally (24.29% at the moment of writing), is notorious for its poor font rendering. By default it doesn’t have ClearType antialiasing on at all, except in IE8. Fonts which haven’t been properly hinted for use on screen, tend to look like this when viewed there:

Windows XP rendering

When choosing typefaces for the Web you should look out for the following qualities: Style and form, How easy it is to read, typeface’s intended usage—is it meant for longform reading or is it a display type, it’s character set, file size, OpenType font features, how it renders on different screens and if it is hinted for screen or not. Some good tools which can help with the process are Web Font Specimen, Typecast app and Typekit’s font browser.

It’s important that we choose the typefaces before making any other decisions about the layout. This way we can later on determine what the optimal font sizes are for the project, based on how the selected typefaces render at different sizes. Below is an example of what the typography prototype looks like on various platforms after the typefaces have been picked and we start testing how they actually render:

Typography prototype, example 2

Useful Resources:

Choosing a scale

A scale, or more precisely, a modular scale, is a sequence of numbers that relate to one another in a meaningful way. A modular scale helps us to choose font sizes, line heights, margins, and more. Modular scales also make it easier to achieve a visual harmony in the whole design.

I recommend calculating typographic scales using the ideal text size of the chosen body typeface + a ratio, which could for example be the Golden Ratio 1:1.618. I tend to use either Tim Brown’s Modular Scale Calculator to build a custom scale, or, if the sizes match, the scale described in my previous typography article:

Typographic scale

Tim, who also made the calculator I just mentioned, has written an in-depth guide about modular scales and how to use them on the Web. Tim’s methods are very similar to the ones I use myself too, and this is a short excerpt from his article:

Sizing type on the web is tricky because of the limited resolution involved. One pixel of font-size up or down can completely change how a typeface—and thus a whole text—looks. But once I found the size I liked, 18px, I had a number upon which to base my modular scale.”

Sizing type

There are no absolute sizes when it comes to measuring web type. Everything is relative. That’s why you should avoid using absolute values like pixels and instead embrace the fluid nature of the Web using units like percents and EMs. The size of the type you should use depends on the reading distance, device’s resolution and the typeface used. Reading distance also varies depending on the device used—is it a device held in hand, is it a tablet or is it a desktop device? Or maybe it’s something in between these?

A good starting point is to set the body font-size initially to 100%, which zeroes our scales to the “normal” of a given environment and then design and build for larger screens from that point upwards by using the modular scale we calculated earlier.

I do this by using a function in Sass which automatically converts pixels to EMs so that I don’t have to manually calculate them. The function below works by taking two arguments, pixels and context. You can either use the default context and specify only the pixels you want to convert—or you can specify pixels and a context for the conversion:

1
2
3
4
5
$browser-context: 16; // Default

@function em($pixels, $context: $browser-context) {
  @return #{$pixels/$context}em
}

…and then later in the CSS we can just pick numbers from the scale, 16/24/72, and they get automatically converted to EMs:

1
2
3
4
5
6
7
8
9
10
11
body {
  font-size: em(16);
}

p.intro {
  font-size: em(24);
}

h1 {
  font-size: em(72);
}

Below is an example of what the typography prototype looks like now, when we have our scale and have applied some base font sizes from that, but haven’t really tweaked the leading or margins at all:

Typography prototype, example 3

Leading and white space

Leading (line-height in CSS) is the vertical distance between baselines of two lines of text. Leading has a big impact on the readability of a paragraph, so we should be careful when adjusting it. We should use tighter leading in a narrower paragraph, and looser in a wider one. This is to aid the readability and can be achieved by changing the line-height inside our media queries, or by using Mat Marquis’s plugin called Molten Leading.

High DPI screens add some extra complexity as they tend to require different line-heights than the lower DPI screens. Joni Korpi thinks this is because the text looks visually thinner with the extra pixels in use. Less weight = less line height needed.

In the example below, I’ve adjusted the leading of the header, para­graphs, margins, and also the line lengths to be more comfortable to the eye. Everything is based on the numbers found from the scale I created earlier. The example you see here is now basically a ready typography prototype which can be used as the base for the rest of our work:

Typography prototype, example 4

Additional Tips

  • Screens with different pixel densities require different grades of the same font, just like different papers in print do. In theory, this is a great idea, but in reality, there aren’t that many fonts which would have grades (and hardly any have been designed for screen use). Newspapers have been using graded fonts for different papers for a long time, but it’s a quite new concept on the Web.

  • Sometimes using different body fonts for different screen types is better than using the same font all the way. A List Apart’s new redesign is experimenting with this idea. They are using Georgia Pro Condensed in the smallest breakpoint, to see if layouts are enhanced by fitting in more characters per line.

  • If needed, use non-breaking spaces between last two words to avoid orphans in fluid paragraphs (&nbsp;).

  • Always use non-breaking spaces in expressions in which figures and abbreviations are separated by a space (e.g. 20 kg, 4:00 pm) and where text breaking across two lines might be disruptive to the reader.

  • Try to keep the line length between 45-75 characters per line.

Conclusion

The finished typography prototype will be used as the foundation for the rest of our work. We have the recipe, and now we need to start thinking how the colours and the layout will be cooked. This way, when we start our work from the most crucial parts—the content and the typography—and build everything else up from that point, there’s much less chance that we will get lost along the way. ❦