Vous êtes sur la page 1sur 128

appliness

TUTORIALS JAVASCRIPT

BOOKMARK / SHARE / TOC

Secrets of Awesome JavaScript API Design


by Brandon Satrom

TUTORIALS AWESOME JAVASCRIPT API DESIGN

by Brandon Satrom
GETTING STARTED

Article published by:

Design is a universal concept. As the act of form[ing] a plan or scheme of [some thing] for later execution, (Oxford English Dictionary) design is the common thread that weaves together art, architecture, hardware and more. Software design, specifically the subcategory of API design, is no different. Yet API design is often given little attention in the world of software development, because the exercise of writing code for other developers often seems far less important than the design of application UI and end-user experiences. But API designthe public interfaces we provide in the libraries we create, with the express intent of exposing features and functionality to developers who call our code is just as important as UI design. In fact, both are the primary mode of creating user experiences for a segment of an applications audience. Where application UI is a large part of end-user UX, an applications API is developer UX. As such, it should be designed with the same level of care and attention to detail that we provide to user interfaces. Just as we pay attention to the utility, simplicity and elegance of a UI, we should similarly evaluate the utility, simplicity and elegance of an API. API design, and in the context of this article JavaScript API design, presents a unique challenge for all developers, whether youre building a public library or an internal one. The dynamic nature of JavaScript, the anonymity of library consumers and ambiguity in requirements presents a daunting set of challenges for the API designer. While there are no quick shortcuts to good API design, it is possible to distill a handful of design principles that hold up when applied to some of the popular JavaScript libraries of today. API DESIGN: A STRUGGLE OF GOOD VS. EVIL Poor design in JavaScript APIs is costly, both to the developers consuming your API and to you. In both cases, a poor design generates waste: wasted time for developers as they struggle to make sense of an interface, and wasted time for the API author as she deals with the increased load of support and rework brought about by developer confusion. Considering that nearly all APIs are created with the goal of abstracting common functionality for easy consumption and thus, saving time, a poor API leaves both you and your users wondering if this little library of yours was such a good idea
2 of 12

TUTORIALS AWESOME JAVASCRIPT API DESIGN

after all. Good API design, on the other hand, accomplishes the goal of abstraction, while being self-describing. When an API is well-designed, users can leverage your work quickly and intuitively, without the constant reference of a manual, documentation or frequent visits to support and Q&A sites. Youve also saved another developer time by packaging up some feature that would have taken much longer to create on their own. And not only does good design save developers time, it makes them look smart and responsible. Helping your users look smart and capable makes them feel awesome, which makes you look pretty awesome, too. IN JAVASCRIPT, API DESIGN IS ESPECIALLY IMPORTANT While API design is important regardless of programming language or framework, the stakes of API design are much higher for JavaScript than for many other languages. To begin with, as a dynamic, late-bound programing language, JavaScript has no compiler to serve as a safety net or first unit test to point out mistakes in your code. Linting or verification frameworks like JSLint and JSHint help somewhat. These utilities are useful in pointing out common mistakes in JavaScript code, but they do nothing to catch the errors a developer might make when using your API. Its up to you, then, to build an API with a design that helps users of your library fall into the proverbial pit of success. This means that your library feels comfortable and familiar to the developer, while also providing positive reinforcement and building the developers confidence as she interacts with your code. One of the best examples of falling into the pit of success is jQuerys use of CSS selector syntax for fetching DOM elements. For example, if I want to select all article elements with the class blogPost, I can do the following in jQuery:
$(article.blogPost).fadeIn();

Its no coincidence that the selector article.blogPost uses the exact same syntax as the following:
article.blogPost { border-radius: 10px; background-color: salmon; box-shadow: 0px 0px 10px 2px #ccc;
3 of 12

TUTORIALS AWESOME JAVASCRIPT API DESIGN

jQuerys selector engine was designed to enable me, the developer, to map my existing understanding of CSS selectors onto basic interactions with its engine. As a result, Im instantly and measurably more productive than if jQuery required me to use a new, purpose-built syntax. Its possible to take inspiration from libraries like jQuery and others, and to apply these our own designs. However, inspiration by itself is a degree removed from copying, and anyone whos ever designed an API based solely on the inspiration of another knows that he will inherit both good and bad. Instead, if we map examples of good JavaScript API design to proven principles found in other fields, we can build a framework of good API design that can be applied in any context.

SECRETS OF AWESOME JAVASCRIPT APIS While its true that software doesnt have the same visual qualities as a painting or a building, we tend to use the same adjectives to describe software as we do for physical media. Its not uncommon to hear someone refer to an API as elegant or beautiful. If its valid to describe APIs in terms we use for visual media, its equally valid to use the principles of those media to inform our software designs. In this section, Im going to introduce four popular design principles from the art world and apply these to API design: Unity and Harmony Balance Proportionality Emphasis For each of these, Ill point to one or more examples of the principle as leveraged in the API of a popular JavaScript library. PRINCIPLE 1: UNITY & HARMONY In art, unity is the concept behind a work, or how the composer brings everything together into a coherent whole. Harmony, on the other hand, is the placement of
4 of 12

TUTORIALS AWESOME JAVASCRIPT API DESIGN

similar elements throughout a work, which yields an uncomplicated and simple feel when considered in its entirety. For the API designer, these principles can be applied through the use of similar and/or unifying elements in a library. Take, for instance, Kendo UI, a JavaScript framework for building rich web applications. One of Kendo UIs offerings is a set of UI controls and widgets, all of which can be initialized using a similar syntax. For example, if I wanted to create a TreeView control from an unordered list, I need only call the following:
$(ul.tree).kendoTreeView({ /* Configuration goes here */ });

If, on the other hand, I wanted to create a PanelBar from a list, Ill make a slightly different call.
$(ul.panel).kendoPanelBar({ /* Configuration goes here */ });

5 of 12

TUTORIALS AWESOME JAVASCRIPT API DESIGN

Kendo UI promotes unity and harmony by using this consistent kendoX syntax for all of its widgets. Whats more, its dependency on jQuery objects for obtaining DOM elements adds an additional layer of harmony that any developer already familiar with jQuery will benefit from. By using a local dialect of JavaScript that millions of developers are familiar with, Kendo UI promotes harmony across libraries. Another example of harmony in action is Backbones [object].extend syntax to create objects that inherit and extend the functionality of Backbone Models, Views, Collections and Routers. To create a new Backbone model, I can do something like the following, and Ill get a model object thats fully-supported by Backbone, while being customized to my applications needs:
var Book = Backbone.Model.extend({ initialize: function() { ... }, author: function() { ... }, pubDate: function() { ... }, });

The goals of unity and harmony are to convey familiarity and comfort to developers new to your API. By leveraging identical or similar idioms for related but different actions, an API can convey familiarity and comfort which can greatly ease a developers adoption of a new tool.
6 of 12

TUTORIALS AWESOME JAVASCRIPT API DESIGN

PRINCIPLE 2: BALANCE The next principle is balance, an arrangement of elements to ensure that no one part of the work overpowers other parts or causes the work to feel unstable. In art, balance is about visual weight. Even when asymmetrical, a work can feel balanced because its asymmetry follows a pattern. In the context of API design, I interpret balance to mean both the visual weight of the code and its predictability. A balanced API is one whose component parts feel as though they belong together, because they behave the same or aid the consumer in accomplishing a complementary goal. By extension, these APIs also feel balanced because they allow the consumer to extrapolate usage from a small sample. Consider Modernizrs property tests. These achieve balance by a) using property names that match HTML5 and CSS concepts and APIs; and b) by consistently returning a truthy or falsy value for every single test:
// All of these properties will be true or false for a given browser Modernizr.geolocation Modernizr.localstorage Modernizr.webworkers Modernizr.canvas Modernizr.borderradius Modernizr.boxshadow Modernizr.flexbox

Accessing a single property tells the developer everything he or she needs to know in order to access every other property, a quality thats powerful in its simplicity. It also ensures that the code I write to interact with Modernizr has the same visual weight each time I write or read it. How I use and access the API looks and feels the same, regardless of my usage. If, on the other hand, Modernizr were to add an API to polyfill Canvas, imbalance would take hold. Not only is the visual weight of the library affected by this new API, but the scope and purpose of Modernizr has grown greatly, and my ability to predict how to interact with the API is hampered. Another way to achieve balance through predictability is to rely on concepts already familiar to developers. A notable example is jQuerys selector syntax, which maps CSS13 selectors into its own DOM selector engine:
$(#grid) // Selects by ID $(ul.nav > li) // All LIs for the UL with class nav $(ul li:nth-child(2)) // Second item in each list
7 of 12

TUTORIALS AWESOME JAVASCRIPT API DESIGN

By using a familiar concept and mapping it to its own library, jQuery is able to avoid creating a new selector syntax, while also creating a mechanism that makes new users of the library instantly productive with a predictable API. PRINCIPLE 3: PROPORTION The next principle is proportion, which is a measurement of the size and quantity of elements within a work. Rather than stating that a good API is a small API, proportion is about size relative to purpose. A proportional API is one whose API surface matches its scope of capability. For instance, Moment.js, a popular date parsing and formatting library, can be considered proportional because its API surface is compact, which matches the straightforward purpose of the library. Moment.js is for working with dates and, as such, its API is filled with convenience functions designed to make the JavaScript Date object tolerable to work with:
moment().format(dddd); moment().startOf(hour).fromNow();

For libraries with a targeted purpose, like Moment.js, keeping the API focused and small is important. For larger, more expansive libraries, the size of the API should reflect the capabilities of the library itself. Take Underscore. As a general-purpose utility library, Underscore provides a large number of convenience functions designed to help developers work with JavaScript collections, arrays, functions and objects. It has a larger API surface than a library like Moment.js, and yet Underscore is proportional because each function aids in the purpose of the library. Consider the following examples, the first two of which illustrate using Underscore to work with Arrays, and the last of which illustrates working with strings:
_.each([Todd, Burke, Derick], function(name){ alert(name); }); _.map([1, 2, 3], function(num){ return num * 3;

8 of 12

TUTORIALS AWESOME JAVASCRIPT API DESIGN

_.isNumber(ten); // False

}); As a library grows, the challenge of maintaining proportion becomes even more critical. Care must be taken to ensure that every feature and function added to a library reinforces the librarys purpose. For a large offering like Kendo UI, an expansive purpose doesnt mean we need to add every feature under the sun. For a library as large as Kendo, even utility objects and features should prove their worth to be included. Take for example, Kendo UIs JavaScript based DataSource, which can be used to query and work with remote data:
var dataSource = new kendo.data.DataSource({ transport: { read: { url: http://search.twitter.com/search.json, dataType: jsonp, data: { q: API Design } } }, schema: { data: results } });

At first glance, it might seem like a custom DataSource falls outside of the primary purpose of the library. However, many of todays web widgets assume the existence of dynamic data, and the inclusion of a DataSource allows Kendo UI to use a consistentand thus, comfortableparadigm for working with remote data across the entire library. Allowing an API to turn into a veritable JavaScript junk drawer is a danger of library growth, but it is not the only danger. Of equal risk is falling in the trap not allowing your API to grow along with a library; constraining the surface area of your library for artificial reasons. A good example of how not to handle API growth, is jQuerys jQuery or $ function. As much as I and millions of others love jQuery, the librarys gateway method is a bit of a mess, providing no less than eleven separate overloads for everything from DOM selection to the ability to wrap DOM elements in a jQuery object. For the most part, these are loosely related features that have been stuffed into one API. Taken on the whole, jQuery is a large library and can be considered reasonably
9 of 12

TUTORIALS AWESOME JAVASCRIPT API DESIGN

proportional. The jQuery method, on the other hand, represents what can happen when we attempt to force functionality into a single interface, without care for proportion. If you find yourself stuffing tangential features into existing methods, or rationalizing the addition of function overloads that dont feel natural to the API, chances are you need to loosen the belt and let that library breathe. Your users will have an easier time adapting to a new function with a self-describing name than they will yet another overload on an existing method.

PRINCIPLE 4: EMPHASIS In art, emphasis is the use of contrast to cause an aspect of the work to stand out and serve as a focal point. In many APIs, the focal point might be a gateway or main method that anchors the library. Another example of emphasis could be a chained or fluent API, which adds emphasis to a central object used by the library. jQuerys tendency to return a jQuery object from many of its functions demonstrates this type of emphasis:
$(ul.first).find(.overdue) .css(background-color,red) .end() .find(.due-soon) .css(background-color, yellow);

For many modern libraries, another excellent example of emphasis is extensibility: that part of the library where the creators embrace whats missing from the library by giving you a vehicle to add functionality yourself. A classic example is jQuerys fn (pronounced effin) namespace, the general extensibility point from which countless plugins and complementary libraries have been launched:
(function($) { $.fn.kittehfy = function() { return this.each(function(idx, el) { var width = el.width, height = el.height; var src= http://placekitten.com/;

10 of 12

TUTORIALS AWESOME JAVASCRIPT API DESIGN

el.src= src + width + / + height; }); }; })(jQuery);

Another example of extensibility is Backbones extend function, which weve looked at already in this article:
var DocumentRow = Backbone.View.extend({ tagName: li, className: row, events: { click .icon: open, click .button.edit: openEditDialog }, render: function() { ... } });

Adding extensibility exhibits emphasis because it calls attention to the fact that a given library wasnt meant to be the endallbeall, while at the same time encouraging you to add to the capabilities of the library as you see fit. When libraries encourage extensibility, they unlock not only new specialized uses, but additional general uses that might benefit countless other developers. One great example is the Backbone.Marionette framework, a extension library for Backbone that aims to simplify the construction of large scale JavaScript applications. Were it not for the extensibility of a library like Backbone, libraries like Marionette would be much more difficult, if not impossible, to deliver. API DESIGN: NOT JUST FOR LIBRARY AUTHORS If youre not a JavaScript library author, but consider yourself a JavaScript app developer and library implementer, you might be tempted to think that the principles in this article dont apply to you. After all, most of us often think of thirdparty libraries, like those Ive used for the samples in this article, when we hear the term API. The truth is that an API, by definition, is nothing more than a segregated piece of functionality that provides an interface for others to leverage. Im using general terms here to underscore an important point: modular JavaScript code is written to be consumed; the number of consumers is irrelevant.
11 of 12

TUTORIALS AWESOME JAVASCRIPT API DESIGN

Your own JavaScript code exposes interfaces for others, just as the libraries referenced in this article do. Even if the consumers of your code are a small, internal teamor even if youre building a library for private useyou dont have to be a public library author to think about API design and apply the principles covered in this article. The benefits of leveraging intentional API design pay off for an audience of one, just as they do for an audience of one million. Because API design represents UX for developers, it is just as important as UI design for end-users. Just as we can learn to develop a sense for UI design by studying principles and examples of good and bad interfaces, we can learn much about good API design by doing the same. Applying the four principles from this article, as well as others you discover on your own, can result in awesome APIs that delight your users and help them build amazing experiences for others.

Brandon Satrom
Developer extraordinaire

HIS BLOG

SHARE

TWITTER

GITHUB

appliness

TUTORIALS JAVASCRIPT

BOOKMARK / SHARE / TOC

asm.js: closing the gap between JavaScript and native.


by Dr. Axel Rauschmayer

TUTORIALS ASM.JS: CLOSING THE GAP BETWEEN JAVASCRIPT AND NATIVE

by Dr. Axel Rauschmayer


GETTING STARTED

[asm.js] effectively describes a safe virtual machine for memory-unsafe languages like C or C++.

asm.js defines a subset of JavaScript that can be compiled to fast executables. It has been created at Mozilla by David Herman, Luke Wagner and Alon Zakai. According to the specification, [asm.js] effectively describes a safe virtual machine for memoryunsafe languages like C or C++. This blog post describes how asm.js works, it is based on the specification. 1. THINGS THAT SLOW DOWN JAVASCRIPT Current JavaScript is already quite fast, but a few mechanisms in engines limit its speed: Boxing: Floating point numbers (including integers stored as floating point numbers) are boxed, they have wrappers that allow them to co-exist with other values such as objects. Just-in-time (JIT) compilation and runtime type checks: Most JavaScript engines compile code in two stages. Initially, a format is used that can be compiled to quickly, but that runs slowly (e.g. interpreted bytecode). The execution of that format is observed. If it runs more often, assumptions can be made about the types of its parameters etc. and it can be compiled to a format that runs faster. If one of the assumptions turns out to be wrong, the faster format cant be used any more and the engine has to go back to the slower format. The faster format is always slowed down by checking whether the assumptions still hold. Automated garbage collection: which can be slow. Flexible memory layout: JavaScripts data structures are very flexible, but they also make memory management slower. asm.js code can produce executables that exhibit none of these drawbacks. They can be compiled ahead of time (before execution) and are faster than JIT-compiled ones: asm.js can be implemented massively faster than anything existing JavaScript engines can do, and its closing the gap to native more than ever. David Herman
2 of 9

TUTORIALS ASM.JS: CLOSING THE GAP BETWEEN JAVASCRIPT AND NATIVE

The asm.js specification only describes what JavaScript code has to look like to be asm.js-compliant, the semantics follow from the ECMAScript language specification. That is, asm.js is a true subset of JavaScript. 2. HOW ASM.JS WORKS asm.js code is packaged in specially marked functions (asm.js modules) that have the following structure:
function MyAsmModule(stdlib, foreign, heap) { use asm; // marks this function as an asm.js module // module body: function f1(...) { ... } function f2(...) { ... } ... return { export1: f1, export2: f2, ... };

Two steps are performed before asm.js code can be used: Ahead of time (AOT) compilation: a complete fast executable can be produced when the code is loaded (compare: JITs only produce a slow version at load time). Linking: The asm.js module function is invoked and linked to its external dependencies stdlib and foreign (see below). All three parameters are optional (if any of them are missing, appropriate default values are created): stdlib: a standard library object, providing access to (a subset of) the standard library. foreign: a foreign function interface (FFI) providing access to arbitrary external JavaScript functions. heap: a heap buffer, an instance of ArrayBuffer that acts as the asm.js heap.
3 of 9

TUTORIALS ASM.JS: CLOSING THE GAP BETWEEN JAVASCRIPT AND NATIVE

The functions in the returned object can be invoked from non-asm.js code like all other JavaScript functions. Example. Lets look at a concrete example:
function DiagModule(stdlib) { use asm; var sqrt = stdlib.Math.sqrt; function square(x) { x = +x; return +(x*x); } function diag(x, y) { x = +x; y = +y; return +sqrt(square(x) + square(y)); } } return { diag: diag };

The following code links and uses this asm.js module.


// Browsers: this === window var fast = DiagModule(this); console.log(fast.diag(3, 4)); // link the module // 5

2.1 STANDARD LIBRARY asm.js has very limited access to JavaScripts standard library. Only the following values can be accessed: Global double values: Infinity, NaN Double functions (arity 1): Math.acos, Math.asin, Math.atan, Math. cos, Math.sin, Math.tan, Math.ceil, Math.floor, Math.exp, Math.log, Math.sqrt Double functions (arity 2): Math.atan2, Math.pow Integer or double function (arity 1): Math.abs Integer function (arity 2, proposed for ECMAScript 6): Math.imul (integer multiplication) Double values: Math.E, Math.LN10, Math.LN2, Math.LOG2E, Math. LOG10E, Math.PI, Math.SQRT1_2, Math.SQRT2
4 of 9

TUTORIALS ASM.JS: CLOSING THE GAP BETWEEN JAVASCRIPT AND NATIVE

2.2 STATIC TYPING asm.js code is statically typed. You statically specify the type of a variable declaration via its initializer. For example:
var a = 0; var b = 0.0; // a has type int // b has type double

You statically specify the types of parameters and return values via type annotations. For example:
function foo(x, y) { var x = x|0; // x has type int var y = +y; // y has type double return +(x * y); // function returns a double }

The annotations tell the compiler what type to expect and also coerce arguments to the correct type. 2.3 SUPPORTED TYPES Value types. Roughly, asm.js supports 64 bit double-precision floating point numbers and 32 bit integers (ignoring several types that are needed so that all asm.js-supported JavaScript operations can be typed correctly). asm.jss doubles are the same as JavaScripts. You cant work with integers directly in JavaScript, but 32 bit integers (similar to asm.jss integers) are used internally [1]. References types. Reference types are only allowed for variable declarations at the top level of a module. All other variables and parameters must have value types. The following reference types are available: ArrayBufferView types: Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array. These types are used for accessing the asm.js heap. Functions Function tables: an array of functions that all have the same type References to foreign functions

5 of 9

TUTORIALS ASM.JS: CLOSING THE GAP BETWEEN JAVASCRIPT AND NATIVE

2.4 CHECKING FOR ASM.JS CONFORMANCE Static checks (at compile time). The code of an asm.js is statically checked (when the JavaScript code is loaded): It must only use the declarations, statements and expressions that are part of asm.js (e.g. almost none of the OOP features of JavaScript are). And it must be well-typed, according to the static type system. If the checks fail, then asm.js code cant be AOT-compiled and is executed as normal JavaScript code. Dynamic checks (at link time). When you invoke an asm.js module, the following dynamic checks are performed. If one of them fails, the AOT-compiled code cant be linked and the engine must fall back to normal JavaScript. No exception must be thrown until the return statement is reached. The heap object (if provided) must be an instance of ArrayBuffer. Its byteLength must be a multiple of 8. All view objects must be true instances of their respective typed array types. All properties of the stdlib object must implement the semantics as specified by the ECMAScript standard. In practice, that means that they must have the same values as the properties of the global object that have the same names. 3. ADVANTAGES OF ASM.JS The approach taken by asm.js has the following benefits: Relatively easy to implement on top of existing JavaScript engines. Quoting David Herman: [...] its significantly easier to implement in an existing JavaScript engine than from-scratch technologies like NaCl/PNaCl. Luke Wagner has implemented our optimizing asm.js engine entirely by himself in the matter of a few months. Interacts well with JavaScript. It is a subset of JavaScript, after all. Backward compatible with all existing JavaScript engines: if an engine isnt aware of asm.js then the code simply runs as normal JavaScript.

6 of 9

TUTORIALS ASM.JS: CLOSING THE GAP BETWEEN JAVASCRIPT AND NATIVE

3.1 EMSCRIPTEN To see what is possible with asm.js, you only have to look at Emscripten which is described as follows on its web site: Emscripten is an LLVM-to-JavaScript compiler. It takes LLVM bitcode (which can be generated from C/C++, using llvm-gcc or clang, or any other language that can be converted into LLVM) and compiles that into JavaScript, which can be run on the web or anywhere else JavaScript can run. The list of projects that have been compiled via Emscripten is impressive: SQLite, Graphviz, LaTeX, Python, etc. Emscripten already produces surprisingly fast code. In fact, its way of code generation has been the inspiration for asm.js and its creator Alon Zakai is part of the asm.js team. A modified version of Emscripten now targets asm.js, which will result in considerable performance increases on engines with the necessary support. First performance numbers are already in: OdinMonkey skinning zlib bullet 2.46 1.61 1.79 SpiderMonkey 12.90 5.15 12.31 V8 59.35 5.95 9.30

OdinMonkey is Firefoxs SpiderMonkey with asm.js support, V8 is Googles JavaScript engine. Numbers denote how much slower the code is compared to code compiled via gcc -O2 (1.0 would mean same speed). 3.3 THE FUTURE Several features are on the horizon for JavaScript that will also benefit asm.js: Modules: ECMAScript 6 will have modules, then asm.js code can be packaged more conveniently. Type guards: Versions after ECMAScript 6 [2] might have type guards, obviating the need for the current, slightly hacky, type annotations.
7 of 9

TUTORIALS ASM.JS: CLOSING THE GAP BETWEEN JAVASCRIPT AND NATIVE

Better parallel programming: better support for data parallelism could come via either River Trail [3] or SIMD [2]. More value objects are also planned for ECMAScript, with 64 bit integers having priority. Once JavaScript has them, they are also available to asm.js. Furthermore, asm.js might be expanded to be a more full-fledged virtual machine in the future, similar to the Java Virtual Machine or Microsofts Common Language Runtime. Quoting the asm.js FAQ: Right now, asm.js has no direct access to garbage-collected data; an asm.js program can only interact indirectly with external data via numeric handles. In future versions we intend to introduce garbage collection and structured data based on the ES6 structured binary data API, which will make asm.js an even better target for managed languages. 3.3 AVAILABILITY Quoting Herman: As the site says, the spec is a work in progress but its nearly done. Our prototype implementation in Firefox is almost done and will hopefully land in the coming few months. 4. CONCLUSION asm.js is impressive technology. There will probably always be people who would prefer a single standardized bytecode for the web, but asm.js proves that different approaches are possible and beneficial. It gives you the best of both worlds: Low-level code: use asm.js for computationally intensive tasks and/or code that can be compiled to LLVM bitcode. High-level code: use all of JavaScript for maximum flexibility. JavaScript source code becomes a format for delivering programs that abstracts over the different compilation strategies of JavaScript engines [4] and over the difference between asm.js and JavaScript. Delivering source code is not an approach that opposes a particular compilation strategy (bytecode etc.), you simply postpone deciding on one, giving engines the freedom to make their own choice. Additionally, this approach allows you to compile asm.js code in the browser: simply assemble a text string with the code and use eval() or Function() to compile it.

8 of 9

TUTORIALS ASM.JS: CLOSING THE GAP BETWEEN JAVASCRIPT AND NATIVE

JavaScript engines are optimized for higher-level code in a manner that cant be replicated by less specialized engines. Thus, there will always be a schism between low-level and high-level engines; asm.js manages to make that schism as small as possible. 5. MORE MATERIAL Website asmjs.org: Specification FAQ Talk: Big Web App? Compile It! by Alon Zakai [video and slides] 6. REFERENCES 1. Integers and shift operators in JavaScript 2. A first look at what might be in ECMAScript 7 and 8 3. JavaScript: parallel programming via River Trail coming to Firefox 4. JavaScript myth: JavaScript needs a standard bytecode

Dr. Axel Rauschmayer


JavaScript Consultant

HIS BLOG

SHARE

TWITTER

GITHUB

appliness

TUTORIALS JAVASCRIPT

BOOKMARK / SHARE / TOC

Functions Explained.
by Mark Daggett

TUTORIALS FUNCTIONS EXPLAINED

by Mark Daggett

Functions are the most rudimentary components of JavaScript.

PHOTO BY: DERREN RASER Mark Daggett is an pioneering New Media artist, professional developer and CEO of Humansized Inc., a social innovations lab in Kansas City. He is a co-creator of Pledgie. com, the popular crowd-funding platform, and an adjunct professor at the Kansas City Art Institute. He has worked for over a decade within the fields of experience and user interaction design, concept development and strategy, through a variety of start-up ventures, consulting and advisory roles. He is a Rockefeller New Media Grant nominee, and has been profiled in The New York Times, Le Monde, WIRED Magazine and Surface Magazine, among others. A DEEP DIVE INTO JAVASCRIPT FUNCTIONS Based on my readership I have to assume most of you are familiar with JavaScript already. Therefore, it may seem odd to include a post on functions. After all, they are one of the most rudimentary components of JavaScript. My assertion is this, just as a person can speak a language without the ability to read or write it, so too can developers use functions in JavaScript and yet be blissfully unaware of their complexities. Typically developers only become aware of the specifics of functions when something they wrote explodes in their face. My goal in this section is to expose the intricacies of JavaScript functions to you, which will hopefully save you from having to pull syntactic shrapnel from your codebase. A word of caution before we begin; JavaScript is only as good as its interpreter. While the concepts well consider are well-covered in the language spec, it does not mean that all runtime environments will work the same way. In other words your milage may vary. This section will discuss common misconceptions of JavaScript functions, and the silent bugs they introduce. However, debugging functions in detail is not covered. Fortunately, debugging has been documented by others in the JavaScript community especially in Juriy Zaytsevs excellent article Named Function Expressions Demystified [1].

2 of 10

TUTORIALS FUNCTIONS EXPLAINED

BLOCKS IN JAVASCRIPT Before we can understand functions in JavaScript we have to understand blocks. JavaScript blocks are nothing more than statements grouped together. Blocks start with a left curly bracket { and end with a right one }. Simply put, blocks allow statements inside the brackets to be executed together. Blocks form the most basic control structure in JavaScript. The following are a few examples of how blocks in JavaScript:
// Block as an anonymous self-executing function ;!function () { var triumph = false, cake = false, satisfaction = 0, isLie, note; // Block used as part of function expression var isLie = function (val) { return val === false; } // Block used as part of a conditional statement if (isLie(cake)) { triumph = true; makeNote(huge success); satisfaction += 10; } // Block used as part of a function declaration function makeNote(message) { note = message; } }();

As we saw above, functions are essentially named blocks, which the developer can invoke on demand. This is easy to demonstrate:
// The inline conditional block statement is executed only once per cycle. if (isLie(cake)) { ... } function makeNote(message) { ... }
3 of 10

TUTORIALS FUNCTIONS EXPLAINED

// The function declaration is executed as many times as it is called. makeNote(Moderate Success); makeNote(Huge Success);

FUNCTION ARGUMENTS Functions like control flow statements (if, for, while etc.) can be initialized by passing arguments into the function body. In JavaScript variables are either a complex type (e.g. Object, Array) or a primitive type (e.g. String, Integer). When a complex object is supplied as an argument it is passed by reference to the function body. Instead of sending a copy of the variable, JavaScript sends a pointer to its location in memory. Conversely, when passing a primitive type to a function JavaScript passes by value. This difference can lead to subtle bugs because conceptually we often treat functions as a black box, and assume they can only effect the enclosing scope by returning a variable. With pass by reference, the argument object is modified even though it may not returned by the function. Pass by reference and pass by value are demonstrated below:
var object = { foo: bar }, num = 1; // Passed by reference ;!function(obj) { obj.foo = baz; }(object); // => Object {foo: baz} console.log(object); // Passed by value; ;!function(num) { num = 2; }(num); // => 1 console.log(num);

4 of 10

TUTORIALS FUNCTIONS EXPLAINED

FUNCTION TYPES Now that we have a better understanding of blocks, and arguments lets dive deeper into Function Declaration and Function Expression, the two types of functions used in JavaScript. To the casual reader the two appear very similar:
// Function Declaration function isLie(cake){ return cake === true; } // Function Expression var isLie = function(cake){ return cake === true; }

The only real difference between the two, is when they are evaluated. A function declaration can be accessed by the interpreter as it is being parsed. The function expression on the other hand is part of an assignment expression, which prevents JavaScript from evaluating it until the program has completed the assignment. This difference may seem minor, but implications are huge; consider the following example:
// => Hi, Im a function declaration! declaration(); function declaration() { console.log(Hi, Im a function declaration!); } // => Uncaught TypeError: undefined is not a function expression(); var expression = function () { console.log(Hi, Im a function expression!); }

As you can see in the previous example the expression function threw an exception when it was invoked, but the declaration function executed just fine. This exception gets to the heart of the difference between declaration and expression functions. JavaScript knows about declaration function and can parse it before the program executes. Therefore, it doesnt matter if the program invokes the function before it is defined. This is because behind the scenes JavaScript has hoisted the function to the top of the current scope. The function expression is not evaluated until it
5 of 10

TUTORIALS FUNCTIONS EXPLAINED

is assigned to a variable; therefore it is still undefined when invoked. This is why good code style is to define all variables at the top of the current scope. Had we done this then our script would visually match what JavaScript is doing during parsetime. The concept to take away is that during parsetime JavaScript moves all function declarations to the top of the current scope. This is why it doesnt matter where declarative functions appear in the script body. To further explore the distinctions between declarations and expressions, consider the following:
function sayHi() { console.log(hi); } var hi = function sayHi() { console.log(hello); } // => hello hi(); // => hi sayHi();

Casually reading this code, one might assume that the declaration function would get clobbered because it function expression has an identical name. However, since the second function is part of an assignment expression it is given its own scope, and JavaScript treats them as seperate entities. To make things even more confusing look at this example:
var sayHo // => function console.log(typeof (sayHey)) // => undefined console.log(typeof (sayHo)) if (true) { function sayHey() { console.log(hey); }

6 of 10

TUTORIALS FUNCTIONS EXPLAINED

sayHo = function sayHo() { console.log(ho); } } else { function sayHey() { console.log(no); } sayHo = function sayHo() { console.log(no); } } // => no sayHey(); // => ho sayHo();

In the previous example we saw that functions of the same name were considered different if one was an expression and the other was a declaration. In this example we are attempting to conditionally define the function based on how the program executes. Reading the scripts control flow youd expect sayHey to return hey since the conditional statement evaluates true. Instead it returns no, meaning the second version of the sayHey function clobbered the first. Even more confusing is that the sayHo function behaves the opposite way! Again, the difference comes down to parsetime versus runtime. We already learned that when JavaScript parses the script it collects all of the function declarations and hoists them to the top of the current scope. When this happens it clobbers the first version of sayHey with the second because they exist in the same scope. This explains why it returns no. We also know that function expressions are ignored by the parser until the assignment process completes. Assignment happens during runtime, which is also when the conditional statement is evaluated. That explains why the sayHo function was able to be conditionally defined. The key to remember here is that function declarations can not be conditionally defined. If you need conditional definition use a function expression. Furthermore, function declarations should NEVER be made inside a control flow statement, due to the different ways interpreters handle it.

7 of 10

TUTORIALS FUNCTIONS EXPLAINED

FUNCTION SCOPES Unlike many other languages which are scoped to the block, JavaScript is scoped to the function. In Ruby (version 1.9.+) you can write this:
x = 20 10.times do |x| # => 0..9 puts x end # => 20 puts x

What this demonstrates is that each block gets its own scope. Conversely, if we wrote similar code in JavaScript:
var x = 20; // Functions have their own scope ;!function() { var x = foo; // => foo console.log(x); }(); // => 20 console.log(x); for (x = 0; x < 10; x++) { // => 0..9 console.log(x);

// => 10 console.log(x);

In JavaScript x is available inside the for loop, because as a control statement it belongs to the enclosing scope. This is not intuitive to many developers used to block level scope. JavaScript handles the need of block level scope at least partially through the use of closures which well discuss later.

8 of 10

TUTORIALS FUNCTIONS EXPLAINED

DEBUGGING FUNCTIONS Before we wrap this topic up, lets briefly touch on debugging functions. In JavaScript naming a function expression is completely optional; so why do it? The answer is to aid the debugging process. Named function expressions have access to their name within the newly defined scope, but not in the enclosing scope. Without a name their anonymous nature can make them feel a bit like ghosts in the machine when it comes to debugging.
var namedFunction = function named() { // => function console.log(typeof(named));

} namedFunction();

// => undefined console.log(typeof(named));

9 of 10

TUTORIALS FUNCTIONS EXPLAINED

Nameless function expressions will be displayed in the stack trace as (anonymous function) or something similar. Naming your function expression gives you clarity when trying to unwind an exception whose call stack may feel miles long.
/* * It is much harder to debug anonymous function expressions * Uncaught boom * - (anonymous function) * - window.onload */ ;!function(){ throw(boom); }(); /* * Naming your function expressions give you a place to start looking when debuggin. * Uncaught boom * - goBoom * - window.onload */ ;!function goBoom() { throw(boom) }();

Mark Daggett
Data Viz Tool Maker

HIS BLOG

SHARE

TWITTER

GITHUB

appliness

TUTORIALS JAVASCRIPT

BOOKMARK / SHARE / TOC

Fun with AngularJS!


by Holly Schinsky

TUTORIALS FUN WITH ANGULARJS!

by Holly Schinsky
GETTING STARTED

I may have been hooked initially because of my Adobe Flex background.

Recently AngularJS, an MVC style JavaScript framework from Google, has been gaining more momentum. Ive been curious about it for awhile and when I read this article recently, I decided it was finally time to give it a whirl. I was pleasantly surprised with what I found. I first watched these two videos by John Lindquist which I highly recommend as a starting point to get your feet wet. They are short and totally worth the time: 1. Simple ToDos App 2. Simple Twitter Search App Part of the reason I personally may have been hooked initially could be due to my Adobe Flex background. Theres a reminiscent feel with AngularJS to Flex in the twoway binding, HTML extension etc so I could see how a lot of Flex developers might feel at home with this framework. The framework is built on the idea that declarative programming should be used for building the UI and imperative programming for your business logic. With AngularJS you can do quite a bit with a small amount of code due to the built-in features that will be explained further in this post. It also relies on dependency injection throughout as well as the separation of the model/view/ controller. Heres a nice illustration from the AngularJS site I found that helps explain more:

2 of 11

TUTORIALS FUN WITH ANGULARJS!

Disclaimer: My intention is not to incite a frameworks war here. I know there are a myriad of JavaScript frameworks available that people are passionate about. Im simply sharing my thoughts and observations. After watching the videos above, I moved on to the tutorial, which was very easy to follow and I thought it was especially cool how they introduced testing your AngularJS app while building it using Jasmine and Testacular. I had previously only heard of those but got a much better idea of how to use them from the tutorial. Its obvious they kept testing in mind while creating this framework. I then decided to build myself a web application with what I had learned. Im a big music fan, always downloading from iTunes for my running playlists etc, so I thought Id build a simple web app that interfaced with the iTunes Search API. The resulting application is here. You can grab the project from my github account here. This was my first newbie attempt so Im open to critique and feedback on how I could make it better. I noticed there are often multiple ways to do the same thing using AngularJS, so Im still in the learning process of when to use what. Overall though I was impressed by how fast I was able to make it all work and how much the framework provides for you. From my Media Explorer application you can enter a search term for anything media related (artist, song name or part, video etc). Once you get the results back, try out the sort and filter to see the returned results sort and filter accordingly. The filter field will filter results as you type into it. This is all built into the array filtering mechanism in AngularJS. Currently the max number of results returned defaults to 50.

3 of 11

TUTORIALS FUN WITH ANGULARJS!

Hitting the play button on the far left of any row will bring up an overlay to play the sample media as shown below:

I used Twitter Bootstrap in my MediaExplorer, but subsequently found AngularUI and Angular Bootstrap which you should also check out for help with your UI specific to Angular. In the next sections Ill cover some of the main AngularJS concepts that seem important to understand.

4 of 11

TUTORIALS FUN WITH ANGULARJS!

DATA BINDING One of the first things I was most excited to see with AngularJS is that it has builtin support for two-way data binding similar to Flex (yay)! This is a big deal for datadriven applications in particular and can save you a TON of time coding. Below are two images from the AngularJS site that I think illustrate this point so well:

5 of 11

TUTORIALS FUN WITH ANGULARJS!

If you want to try a very basic example of the two-way data binding in action, I found this live sample here. If you look at the source code youll see how simple it is:

<div> Binding the value in the text field to the model name. <br/><br/> <input type=text ng-model=name placeholder=Enter a name here/> <span ng-show=name><h4>Hello {{name}}></h4></span> </div>

As you type into the input field it will show up next to the Hello string since the name field is referenced there and is also the bound model object on the HTML input (with ng-model=name). MODEL The model is simply a plain old JavaScript object, does not use getter/setter methods or have any special framework-specific needs. Any changes are immediately reflected in the view via the two-way binding feature. Theres a concept of scope in the AngularJS framework, where all model objects stem from. I recommend seeing the AngularJS Scope documentation for more information on this topic. Typically your model objects are initialized in your controller code with syntax like:
$scope.searchTerm = Alicia Keys;

But in the HTML template, that model variable would be referenced in curly braces such as: {{searchTerm}} without the $scope prefix.

6 of 11

TUTORIALS FUN WITH ANGULARJS!

VIEW The view is the rendered HTML that contains the transformed DOM resulting from a combination of the HTML template along with the AngularJS model and controller. The AngularJS View is aware of the controller and model, and accesses it through annotated HTML directives specific to AngularJS. For example, an ngclick AngularJS directive can be applied to a button element to call a specific method in the controller when clicked. More on directives below CONTROLLER The controller is used to provide the business logic behind the view and construct and value the model. The goal is to not manipulate the DOM at all in the controller, which is something to get used to if youve been using other frameworks. FILTERS AngularJS filters are used to modify data in some way, similar to formatters in Flex. For instance, a built-in filter called uppercase would look like this when applied to the name string from the model in order to uppercase it upon display.
<td>{{name|uppercase}}</td>

Youre welcome to write your own filters as well. I included a custom one for fun in my application called capitalize that will simply capitalize the first letter of a string.
mediaApp.filter(capitalize, function() { return function(input, scope) { if (input!=null) return input.substring(0,1).toUpperCase()+input.substring(1); } });

7 of 11

TUTORIALS FUN WITH ANGULARJS!

You can see it applied here:

Theres also an array filtering feature which is really cool, and you can see an example of it in the Media Explorer app. When you specify a filter string on an array in the Angular ng-repeat directive it will automatically filter the matching results into a new array. For instance, heres the code from the Media Explorer that specifies the filterTerm (the model object bound to the filter input HTML element) to your results list as you type (automatically applied do to the two-way data binding on the model data):
<label>Filter by <input type=text ng-model=filterTerm class=input-small/> </label> ... <tr ng-repeat=item in mediaResults | filter:filterTerm | orderBy:sortProp> <td><button id=playBtn class=btn ng-click=playVideo(item)><i class=icon-play></i></button></td> <td><a href={{item.previewUrl}}><img ng-src={{item.artworkUrl60}}></ a></td> <td>{{(item.trackName != null) item.trackName || item.collectionName}}</ td> <td>{{item.kind | capitalize}}</td> <td>{{item.artistName}}</td> <td>{{item.collectionName}}</td> <td>{{item.trackPrice}}</td> <td>{{item.collectionPrice}}</td> ...
8 of 11

TUTORIALS FUN WITH ANGULARJS!

DIRECTIVES Directives are ways to transform the DOM through extended HTML. The add additional behavior. If you happen to have done Flex, its similar to adding a property like itemRenderer to an MXML component, or specifying click to call a function. In AngularJS there are a bunch of built-in ones you can use, most with a prefix of ng (ng-click, ng-show, ng-change, ng-app etc). Theyre actually defined with camelCase in the JavaScript, but applied with a dash to the HTML. You can also define your own directives and apply them in a similar fashion. In my Media Explorer application I wrote a couple of directives you could see for more examples. I used them to manipulate DOM elements since its not good practice to do so in the controller code. One called videoLoader is used to play and stop the video in the modal when the play button is clicked:
mediaApp.directive(videoLoader, function(){ return function (scope, element, attrs){ console.log(scope.url); scope.$watch(url, function(newValue, oldValue){ //watching the scope url value element[0].children[0].attributes[3].value=newValue; //set the URL on the src attribute element[0].load(); element[0].play(); }, true); scope.$watch(showFlag, function(newValue, oldValue){ if (!newValue) // if the showFlag is false, stop playing the video (modal was closed) element[0].pause(); }, true); } });

Then to apply this videoLoader directive to my video control, I add it as an attribute with a dash, such as:
<video id=vid width=320 height=240 video-loader=item.previewUrl autoplay controls> {{url}} <source id=vidsrc ng-src=url type=video/mp4>

9 of 11

TUTORIALS FUN WITH ANGULARJS!

</video>

SERVICES Services are provided in AngularJS to help you do common task. For instance, theres a built-in $http service that gives you access to make http or JSON requests etc, theres also a $location service that gives you access to the browser location URL and helps you parse it etc. There are a bunch of others built-in and once again you can also write your own. You may write your own in the case where theres something you know youre going to use more than once in your application. In my application I did write a service just to try it out and use it to call the iTunes API with the $resource service, which allows you to interact with RESTful services and provides higher level behavior over the $http service (but is dependent on the $http service). My service looks like this:
mediaApp.factory(MediaService, function($resource){ return $resource(https://itunes.apple.com/:action, {action: search, callback: JSON_CALLBACK}, {get: {method: JSONP} }); });

ROUTES You typically configure routes in your main or app.js file for an AngularJS app. For instance, mine is very basic since Im not using multiple views and looks like this:
mediaApp.config([$routeProvider, function($routeProvider) { $routeProvider.when(/, {templateUrl: views/media-list.html, controller: MediaListCtrl}); }]);

You can specify multiple paths for different URLs as well as a fallback. More on route configuration can be found here. QUICK START` You can use the AngularJS seed project, or if youre familiar with Yeoman, theres a whole option to generate an AngularJS-based project as well as additional commands that can be run to add new routes, views, controllers etc. Its actually really cool and easy to use, check out this article for an awesome walkthrough of it. It will even generate your stubbed out tests for testing with Jasmine / Testacular. They
10 of 11

TUTORIALS FUN WITH ANGULARJS!

cant make it much easier for us than that ! I didnt discover this until after I created my application so my project structure doesnt follow the Yeoman structure, but instead mirrors the AngularJS seed project structure. There are also seed projects available for using AngularJS on the front-end and Express+Node on the backend here, as well as AngularJS on the front-end, and Socket.io+Express+Node here if that fits your needs. Ive only scratched the surface of what this framework is about. Below is a list of resources that can be used to follow-up with more in-depth information for those interested. The AngularJS documentation is good and the community support as well from my experience. Next I plan to turn my Media Explorer web application into a mobile application using PhoneGap and will post it here so check back soon! USEFUL RESOURCES 5 Awesome AngularJS Features @briantford on Building huuuuuuge Angular apps AngularJS Batarang Chrome Extension for Debugging AngularJS Forum AngularJS on Google+ AngularJS Cheat Sheet AngularJS Docs AngularJS Blog @briantford on Brian Ford on AngularJS with PhoneGap @simpulton on The AngularJS Scope LifeCycle AngularJS for jQuery Developers @simpulton blog lots of useful articles on AngularJS Dean Sofer AngularJS Tips and Tricks

Holly Schinsky
Developer Evangelist

HER BLOG

SHARE

TWITTER

GITHUB

appliness

TUTORIALS JAVASCRIPT

BOOKMARK / SHARE / TOC

Building a Unit Test in Jasmine, Part 3.


by David Posin

TUTORIALS BUILDING A UNIT TEST IN JASMINE, PART 3

by David Posin

This time we will expand the object to be more robust.

We created a Jasmine unit test example in the first two parts of this series that started with a statement and then abstracted out to an object. This time we will expand the object to be more robust. Most importantly, we are not changing the tests currently in place. The JasmineTester is going to be updated to accept a random number of values. The first step is to create a unit test to describe this. The number of properties being added is upped to 4. The new test will check to make sure the new object constructor still returns an object by using the toBeDefined matcher.
//Check for expanded options object it(Increase number of values to 4, function() { var testObject = new JasmineTester({ a: 2, b: 2, c: 2, d: 2 }); expect(testObject).toBeDefined(); });

The test passes. testObject should now have 4 properties so lets add a new expect to check the number of properties.
expect(Object.keys(testObject).length).toEqual(4);

This test fails:


Expected 2 to equal 4.

Its time to update the constructor to use a random number of properties.


for (o in opts) { if (opts[o]) { this[o] = opts[o]; } }
2 of 6

TUTORIALS BUILDING A UNIT TEST IN JASMINE, PART 3

The constructor is changed to copy all properties from the passed object to itself. This is fairly simple and allows the JasmineTester to accept more than numbers. We run the tests and our new test pass. However, our old tests fail. The old tests should not be changed. Its time to take a look at the total function. The total function is looking for number1 and number2. We can no longer guarantee that those properties will exist. The total function needs to be updated to use all number properties on the object regardless of name. The total is changed to a loop that adds all properties to a running total.
for (num in this) { total += this[num]; }

Unfortunately, our tests still fail because properties from the prototype are also getting added in. We need to make sure the loop only uses this objects own propertes, so the code is changed to:
for (num in this) { if (this.hasOwnProperty(num)) { total += this[num]; } }

Now everything passes, so we can move on. Our new sets of tests are checking for existence and property length, but they are not using the total function yet. We add one more expect function to our new set of tests:
expect(testObject.total()).toEqual(8);

The test passes, and everything is looking good.

3 of 6

TUTORIALS BUILDING A UNIT TEST IN JASMINE, PART 3

A quick look at the code shows a new possibility we did not need to check for before. The JasmineTester can take any property type now, so what happens if any of the properties are not numbers? A new test is added to check if the same result is returned when a string is passed in as a property.
//Make sure object doesnt include strings in total it(Successful total with a string value, function() { var testObject = new JasmineTester({ a: 2, b: 2 }); }); expect(testObject.total()).toEqual(2);

This test fails.


Expected 22 to equal 4.

The total function needs a little more work. The string 2 is being concatenated to the running total instead of being added to it. Adding a typeof check will ensure that the property is a valid number that can be used in a computation. Now the validation test passes. Even though the validation passes, it would be good to expand the check. Lets ensure that the total function wont break if other types are also sent in. The string unit test can be changed to be a generic validation check. The code can be modified to reuse one of the properties of the testObject multiple times and then send the object back for testing.
//Make sure the total function doesnt include/break with non-numbers it(Successful total with non-number values, function() { var testObject = new JasmineTester({ a: 2, b: 2 }); expect(testObject.total()).toEqual(2); testObject.b = function (){}; expect(testObject.total()).toEqual(2); testObject.b = {b:2}; expect(testObject.total()).toEqual(2);

});

4 of 6

TUTORIALS BUILDING A UNIT TEST IN JASMINE, PART 3

We run all of our tests in the suite and they all pass. Our new changes are complete.

The JasmineTester has now been expanded to be more robust and our total function is smarter than before. There are two critical points here: The old tests still pass. Any code that would have been written previously is still working with our new changes. Our process has also changed. Changes to our object started by being described in the unit test. The object was expanded after the test was written. Our development was being guided towards a demonstrable end point that showed success.
5 of 6

TUTORIALS BUILDING A UNIT TEST IN JASMINE, PART 3

The next post will finish this series by adding a second object to the mix. Other parts in the series: Building a unit test in jasmine, Part 1 Building a unit test in jasmine, Part 2

David Posin
Scrollmotion, Inc.

HIS BLOG

SHARE

JavaScript Architect at
TWITTER
GITHUB

appliness

TUTORIALS HTML / CSS

BOOKMARK / SHARE / TOC

Using White Space for Readability in HTML and CSS.


by Louis Lazaris

TUTORIALS USING WHITE SPACE FOR READABILITY IN HTML AND CSS

by Louis Lazaris

Well-written, readable code doesnt create mind games and labyrinths when other developers read it.

This article was originally published in Smashing Magazine on February 19, 2013. You can read it here.

Right up front, Ill offer some simple advice: In production, your code should be as performance-friendly as possible. This means, Gziping, concatenating and minifying as many assets as possible, thus serving the smallest possible files and the least number of files. I dont think anyone would argue that these suggestions arent best practices (even if we dont implement them in every project).

Well-written, readable code doesnt create mind games and labyrinths when other developers read it. (Image: Toca Boca)
2 of 11

TUTORIALS USING WHITE SPACE FOR READABILITY IN HTML AND CSS

Now that weve got that out of the way, how can we use white space in development code to ensure that our files are as readable and maintainable as possible? Well, we could consider a number of options, starting with some basics. (Smashings note: Subscribe to the Smashing eBook Library and get immediate unlimited access to all Smashing eBooks, released in the past and in the future, including digital versions of our printed books. At least 24 quality eBooks a year, 60 eBooks during the first year. Subscribe today!) BASIC HTML INDENTATION I think most if not all of us add basic indentation in our HTML:
<header> <hgroup> <h1>Section title</h1> <h2>Tagline</h2> </hgroup> <nav> <ul> <li><a <li><a <li><a <li><a </ul> </nav> </header> <div class=main> <p>Content goes here.</p> </div>

href=/>Home</a></li> href=/about/>About</a></li> href=/services/>Services</a></li> href=/contact/>Contact</a></li>

The principle here is that whenever something is nested, you indent, so that its clear where everything is in the markups hierarchy. With simple HTML nesting, the content in the <head> section is often neglected, but keeping the nesting consistent here, too, is good practice.

3 of 11

TUTORIALS USING WHITE SPACE FOR READABILITY IN HTML AND CSS

For example, the following sample code is fairly readable, even with no nesting:
<!DOCTYPE html> <html> <head> <title>Foo</title> </head> <body> <!-- content --> </body> </html>

However, with much more content in the <head> section, nesting could make it easier to scan the contents:
<!doctype html> <html class=no-js lang=en> <head> <meta charset=utf-8> <meta content=IE=edge,chrome=1 http-equiv=X-UA-Compatible> <title>HTML5 Please - Use the new and shiny responsibly</title> <meta name=description content=Look up HTML5, CSS3, etc features, know if they are ready for use, and if so find out how you should use them - with polyfills, fallbacks or as they are.> <meta content=width=device-width, initial-scale=1.0 name=viewport> <link rel=shortcut icon href=favicon.ico /> <link rel=apple-touch-icon-precomposed sizes=114x114 href=apple-touchicon-114x114-precomposed.png> <link rel=apple-touch-icon-precomposed sizes=72x72 href=apple-touchicon-72x72-precomposed.png> <link rel=apple-touch-icon-precomposed href=apple-touch-iconprecomposed.png> <link href=http://fonts.googleapis.com/ css?family=Francois+One|Open+Sans:400italic,400,800 rel=stylesheet> <link href=css/style.css rel=stylesheet> <script src=js/libs/modernizr-2.0.min.js></script> <script>if (location.host == h5bp.github.com) location.href = // html5please.us/</script> </head> <body id=gfs> <!-- content --> </body> </html>
4 of 11

TUTORIALS USING WHITE SPACE FOR READABILITY IN HTML AND CSS

This last chunk of code is taken from the HTML5 Please website. As you can see, when the content in the <head> section starts to get larger, indenting makes things a bit easier to digest at a glance. Notice that the <head> and <body> elements are indented, because they are both immediate children of the <html> element. Of course, some developers might have a slightly different method of indenting in certain areas, but the idea is basically the same; the intention is to make the code easier to read in a development environment. BASIC CSS INDENTATION In addition to indenting HTML, many developers (me included) will do matching indentation in any corresponding CSS. The following code would match the HTML shown in the first example above:
header { color: blue; } hgroup { color: green; } hgroup h1 { line-height: 1.5; } hgroup h2 { font-size: 15px; } nav { background: purple; } nav ul { float: left; } nav ul li { font-size: 20px; } nav ul li a, nav ul li a:visited {
5 of 11

TUTORIALS USING WHITE SPACE FOR READABILITY IN HTML AND CSS

text-decoration: none;

.main { border: solid 1px #ccc; }

To some, this seems a bit obsessive. But I prefer it because it helps me to scan the CSS and find matching hierarchies without having to read each selector. Of course, this type of hierarchy in your CSS should be used sparingly if youre implementing modular CSS principles that encourage class-based modules and limited use of the descendant selector (for example, ul li). Certainly, some of the code above is kind of awful; I wouldnt recommend tying your heading and list styles to a specific context like that. But for the purpose of understanding this concept of indenting CSS, look at it as a theoretical example. The point is that you have the option to indent CSS to match the HTMLs structure, thus making it easier to scan and easier to make sense of relative to the markup. Of course, as is the case with a few things mentioned in this post, some of this doesnt apply when youre using a CSS preprocessor. For example, the nested selectors option for Sass would make this last tip quite different in such an environment. READABLE CSS3 Lets take our abuse of white space even further. Many new CSS3 features allow for either comma-separated or space-separated value sets. Two simple examples are multiple backgrounds and transforms. Lets see how we can make these easier to read:
.example { background: url(images/example.png) center center no-repeat, url(images/example-2.png) top left repeat, url(images/example-3.png) top right no-repeat; } .example-2 { transform: scale(.8) skew(20deg, 30deg) translateZ(0); }

Notice what weve done here? Instead of keeping the entire value on a single
6 of 11

TUTORIALS USING WHITE SPACE FOR READABILITY IN HTML AND CSS

line (which can get lengthy in some cases especially when gradients and vendor prefixes are involved), weve put each value set on a new line, aligned with the one above it. Thus, each of the three backgrounds is on its own line, and each transform function is on its own line, left-aligned with the first of each example. Generally, this might go against the idea of having a single property per line (assuming, of course, that youre not doing single-line rule sets). But when compared to the alternative of potentially really long lines, this is a good option, and it makes these rule sets very easy to read. DEALING WITH VENDOR PREFIXES As mentioned, if youre preprocessing your CSS or using -prefix-free, then this advice doesnt apply. But you could manipulate white space to make your vendor prefixes easier to read at a glance:
.example { -webkit-transform: -moz-transform: -o-transform: transform: } scale(.8); scale(.8); scale(.8); scale(.8);

Here weve lined up the colons so that the values align, making it easy to scan all values to ensure theyre the same. I cant tell you how many times Ive adjusted only the WebKit value in a rule set like this and forgotten to do the rest. Of course, this illustrates the importance of preprocessing, but if youre not doing that yet, then this use of white space is a good option to consider. Additionally, many text editors offer a feature called block edit or multiline editing. This is available in Sublime Text, Vim, Coda and probably most others. Using this feature is that much easier when the values youre changing are aligned vertically.

7 of 11

TUTORIALS USING WHITE SPACE FOR READABILITY IN HTML AND CSS

READABLE FILE REFERENCES The gist of this next suggestion comes from a tweet by Twitter Bootstrap cofounder Jacob Thornton. The idea here is that if a list of file references is contained in your document, you can make them easier to read by doing something like the following:
<link rel=apple-touch-icon-precomposed sizes=144x144 href=assets/ico/ apple-touch-icon-144-precomposed.png> <link rel=apple-touch-icon-precomposed sizes=114x114 href=assets/ico/ apple-touch-icon-114-precomposed.png> <link rel=apple-touch-icon-precomposed sizes=72x72 href=assets/ico/appletouch-icon-72-precomposed.png> <link rel=apple-touch-icon-precomposed href=assets/ico/apple-touch-icon-57precomposed.png> <link rel=shortcut icon href=assets/ico/favicon.png>

The example above is taken directly from Bootstrap. Here, all href attributes of the <link> elements are aligned. This makes it easier to refer to or adjust a <link> tag because the update will usually be to the value of the href attribute. Of course, this somewhat violates the rules of indenting HTML. So, alternatively, you could opt for this:
<link rel=apple-touch-icon-precomposed sizes=144x144 href=assets/ico/ apple-touch-icon-144-precomposed.png> <link rel=apple-touch-icon-precomposed sizes=114x114 href=assets/ico/ apple-touch-icon-114-precomposed.png> <link rel=apple-touch-icon-precomposed sizes=72x72 href=assets/ico/ apple-touch-icon-72-precomposed.png> <link rel=apple-touch-icon-precomposed href=assets/ico/ apple-touch-icon-57-precomposed.png> <link rel=shortcut icon href=assets/ico/ favicon.png>

This latter example seems cleaner and has the bonus of aligning the other attributes, although thats not as necessary in my opinion.

8 of 11

TUTORIALS USING WHITE SPACE FOR READABILITY IN HTML AND CSS

But wait. What if you dont care that the href attribute is listed last (which seems to be the custom and is unnecessary for validation)? Then you could do this instead:
<link href=assets/ico/apple-touch-icon-144-precomposed.png rel=apple-touchicon-precomposed sizes=144x144> <link href=assets/ico/apple-touch-icon-114-precomposed.png rel=apple-touchicon-precomposed sizes=114x114> <link href=assets/ico/apple-touch-icon-72-precomposed.png rel=apple-touchicon-precomposed sizes=72x72> <link href=assets/ico/apple-touch-icon-57-precomposed.png rel=apple-touchicon-precomposed> <link href=assets/ico/favicon.png rel=shortcut icon>

No white space tricks needed here, because the href attributes align just fine. But if youre bothered by the lack of alignment of the other attributes, or if you just cant stand the thought of the href attribute being listed first, then youll have to opt for one of the preceding solutions. READABLE CONDITIONAL CLASSES The concept behind the alignment of attributes is nothing new. HTML5 Boilerplate has been doing this sort of thing for some time now with its IE conditional classes. Heres what that chunk of code looks like in the latest version:
<!--[if <!--[if <!--[if <!--[if lt IE IE gt IE 7]> 7]> 8]> IE 8]><!--> <html <html <html <html class=no-js lt-ie9 lt-ie8 lt-ie7> <![endif]--> class=no-js lt-ie9 lt-ie8> <![endif]--> class=no-js lt-ie9> <![endif]--> class=no-js> <!--<![endif]-->

In this case, the class attribute on the opening <html> tag in each conditional (and, incidentally, the tag itself) is being aligned, because this is the part of the code thats most relevant to readability and maintenance, and the part of the code that would suffer most in readability if this alignment were not present.

9 of 11

TUTORIALS USING WHITE SPACE FOR READABILITY IN HTML AND CSS

READABLE COMMA-SEPARATED SELECTORS Sticking with Boilerplate, lets go back to CSS. Heres something used in that projects main style sheet:
html, button, input, select, textarea { color: #222; }

Here, instead of keeping all of the comma-separated selectors on a single line which would be more difficult to scan each selector is put on a new line. This can be helpful when the selectors are somewhat lengthy, as in this next example, also taken from Boilerplate:
.visuallyhidden.focusable:active, .visuallyhidden.focusable:focus { clip: auto; height: auto; margin: 0; overflow: visible; position: static; width: auto; }

Similar to the idea behind aligning HTML attributes discussed above, this vertical alignment makes the code a breeze to scan through when compared to scanning a single seemingly never-ending line of comma-separated selectors. CAN YOUR TEXT EDITOR HELP WITH ANY OF THIS? As a long-time developer who has grown accustomed to coding by hand, my knowledge of the features of different text editors is fairly limited. Some text editors or IDEs might do some of this automatically. Also, plugin developers can use some of these patterns to create plugins or extensions that do this sort of thing automatically or at the click of a button. If you have any suggestions of built-in tools or extensions to text editors that can assist with this, Im sure Smashing Magazines readers would be glad to hear about them.
10 of 11

TUTORIALS USING WHITE SPACE FOR READABILITY IN HTML AND CSS

CONCLUSION Were all encouraged to do whatever we can to make code in a development environment as easy to read and maintain as possible. I hope these suggestions will improve your code in this way. And knowing that this use of white space wont bloat our files is comforting after all, this is not for production code. So, do whatever you feel is necessary to make your HTML and CSS easier to deal with, and be sure to minify those assets when deploying to production. Finally, if you have any suggestions on using white space in HTML or CSS, wed be glad to hear them.

Louis Lazaris
Web Developer

HIS BLOG

SHARE

TWITTER

GITHUB

appliness

INTERVIEW CHRIS COYIER

BOOKMARK / SHARE / TOC

appliness

INTERVIEW CHRIS COYIER

BOOKMARK / SHARE / TOC

INTERVIEW
THE WEB CRAFTSMAN
by Maile Valentine

CHRIS COYIER

INTERVIEW CHRIS COYIER

ABOUT YOU

APPLINESS: Hi Chris, thank you for your time, were excited to have you in this issue of Appliness! Can you tell us a bit about yourself? Chris Coyier: Thanks for having me! Im a web worker. I write about the web at CSS-Tricks, talk about the web on ShopTalk, and design for the social coding site CodePen. How did you manage the transition into making css-tricks a full-time job? Can you tell us about some other projects you are actively working on or contributing to? It was a very slow process. I worked hard and continuously on CSS-Tricks while working full time for five years. Right about at the five year mark I was able to go off on my own, and even that was a bit risky. Luckily I was able to do a Kickstarter and ask people to help me and they did. My biggest project right now is CodePen, which I co-founded with Tim Sabat and Alex Vasquez. Im excited every second I work on it. The things people build on CodePen are incredible. It is a place for inspiration, finding code to use on your own projects, learning new things, teaching, getting feedback, troubleshooting,

and more. CodePen is really what you make of it. Were soon to be going through that same transition - going full time on it and building it into a strong business that can support us. Your design process sounds unique, can you describe it to our readers? How do you transition your design into development? Im not sure my process is that unique. When designing from scratch I often use Photoshop a bit to get my bearings and stay as open minded as I can. But I get out of Photoshop as quickly as I can and into the browser. Thats where the things we build are used. Thats what matters. Fortunately, everywhere Ive ever worked building websites, the teams were small enough that being crossdiscipline was a big advantage. I can work however I want to - Im not waiting for designers to send me comps or designing things just to be passed off like more silo-oriented teams.

3 of 7

INTERVIEW CHRIS COYIER

CHRIS COYIER
& WEB DESIGN
What is the white canvas funk? How do you get out of this funk? When starting a project from scratch, any designer faces a empty white browser window or a blank white Photoshop document. This is the same kind of issue writers face when they start a new writing project, only they have more established tricks for fighting against that moment of terror. For example, as a writer, you can just write out your grocery list. Its not what you need to write, but it gets the blood flowing in your fingers and might get you started. As a designer, the equivalent might be just putting shapes and textures down on the page
4 of 7

INTERVIEW CHRIS COYIER

to get the creative juices flowing. What are your favorite tools to use for web design? Testing design / browser variances? I write code in Sublime Text and largely use Google Chrome as a browser to develop in. BrowserStack is pretty sweet for testing on a huge variety of other browsers without needing to have other computers or devices. Like many of us, IE testing is still a big thing, and I like to use a real Window 7 install running on my Mac through Parallels. Its just nice and fast. I also own more than my fair share of devices. My most recent being a Nexus 7 so I have a real Android device for testing. How do you plan for performance as you develop? I mostly just think about the easy front end wins. Like using as few resources as I can. Compressing and concatenating all scripts and styles. Using a CDN. Making sure expires headers are set nice and long. My biggest project right now, CodePen, is on Ruby on Rails and we use the Rails Asset Pipeline. Its not all wonderful (our deployment is a bit slow at the moment) but I like what it does for us. It gives us Sass and Compass which concatenates and compresses our CSS (which we write in small modular bits). It also combines and concatenates JavaScript. Then when we do deploy,

the final .css and .js files are created with cache busting random numbers in them so our changes are seen right away by users. Are you a fan of preprocessors? If so, whats to like? Sass with Compass is fantastic. There is very little not to like. There is too many features to go into here, but getting into them isnt something youll regret. Its also very easy. See my screencast! Youve had some big names on the very popular podcast ShopTalk, any guests (past or future) you are most excited about? Im excited about every guest. For real. Everybody in this industry is so dang smart and has unique things to share. I think we give them a great venue on ShopTalk with our Q & A format. We dont tell the questions ahead of time, so what you hear on the show is them reacting to unknown questions totally naturally. ShopTalk day is usually my favorite day of the week!

WEB DESIGN

5 of 7

INTERVIEW CHRIS COYIER

CHRIS COYIER
& FUN
Can you tell us what motivated you to write Digging into Wordpress and Wordpress 3: Creating and Editing Custom Themes? The book was a result of Jeff Starr and me essentially wanting to write a book together and choosing a topic we both had things to say about. Ive used WordPress a ton in my web career. Its my go-to CMS for sure. Since I had to learn a lot about it to create all the sites with it that I have, writing about it was very easy and natural. We had both been writing about tech for a number of years. The Lynda.com course came a bit later
6 of 7

INTERVIEW CHRIS COYIER

and was a natural next step after the book. The book isnt so much step-bystep theme building, and this course was. Im dont have any book plans right now but I wouldnt doubt I do another at some point in my life. Im staying plenty busy between ShopTalk, CSSTricks, and CodePen.

Gosh I sure hope so. Thanks for having me!

FUN

You play a mean ukulele and banjo any other instruments? I suck equally at the guitar and mandolin as well! Can you tell us about your history with music? Your roots in bluegrass? Do you play professionally? I was in an acoustic band for a bunch of years. Mid-college to a few years after college. It was bluegrass-ish but we didnt have a scruggs-style banjo player which is kinda of a requirement for real bluegrass. I was in an acoustic Irish punk band called The Groggers after that for a few years. Funnily enough, Im a much better musician now. Ive kept up practicing and various lessons over the years, but I dont do anything with it. Someday Ill get back into it with a force Im sure. I dont really regret leaving it behind a while. The web thing has been great. Will your left brain and right brain continue to coexist peacefully to create technically creative things for the future?
7 of 7

appliness

TUTORIALS RESPONSIVE DESIGN

BOOKMARK / SHARE / TOC

Building a Better Responsive Website.


by Jeremy Girard

TUTORIALS BUILDING A BETTER RESPONSIVE WEBSITE

by Jeremy Girard

The project before us was the ideal opportunity to experiment and push ourselves to improve our responsive workflow.

This article was originally published on the Smashing Magazine website on March 5, 2013. You can read it here.

Earlier this year, I was in the beginning stages of a redesign for our companys website. We had already been planning to use a straightforward responsive approach to Web design, which is our preferred solution for multi-device support. After hearing some frank discussions at An Event Apart conference in Boston about the limitations and challenges of responsive Web design, I realized that our solution needed a bit of adjustment. Thankfully, the project before us was the ideal opportunity to experiment and push ourselves to improve our responsive workflow. In this article, I will detail the process we took, including some of the changes we made along the way, as we worked to build a better responsive website.

The variety of devices being used to access our websites is more diverse than ever. (Image: Blake Patterson)

2 of 21

TUTORIALS BUILDING A BETTER RESPONSIVE WEBSITE

DEFINING OUR GOALS The first step in our project was to make a list of the benefits and drawbacks to the responsive approach we had been using. Our list looked like this: BENEFITS 1. A single website to build, maintain and promote. 2. Support for a variety of screen sizes, not just the extreme cases of large desktop monitors and small handheld devices. 3. Future-friendly, because the layout will reflow based on screen size and not just the size of todays popular devices. DRAWBACKS 1. Content meant only for large-screen devices is often delivered to small screens and simply turned off with CSS media queries, creating unnecessary downloads. 2. Because the markup is a one-size-fits-all solution, we are unable to change the source order of that markup (or eliminate unnecessary elements from the markup completely) based on the device or screen size. What you will likely notice here is that the drawbacks we identified with a responsive approach are areas where a mobile-only solution excels. We wanted the best of both worlds for our new website the advantages that a responsive approach and a mobile-specific solution have to offer. STARTING WITH CONTENT One of the common differences between a responsive design and a dedicated or mobile-only design is in the content or features that are delivered to the browser. A mobile-specific website often features only a subset of content found on the normal version of the website. This is one of the ongoing debates about the two approaches, and proponents of mobile-only websites often argue that mobile users want access only to content that is important to them. The problem with this line of thinking is that what is important to a user any user changes according to their situation. Eliminating access to content based solely on the device someone is using is sure to alienate and frustrate anyone who doesnt fit into the ideal scenario that you envisioned when you decided what to include in and what to eliminate from your mobile website.

3 of 21

TUTORIALS BUILDING A BETTER RESPONSIVE WEBSITE

Our belief has always been that all users should have access to all of the content that the website has to offer, but we wanted to make sure this was indeed the right answer for our website and our users. To help us determine the right approach, we turned to our analytics and found no discernible difference between the type of content requested by our mobile visitors and by our visitors on non-mobile devices. Content that was popular for desktop users was similarly popular for mobile visitors. Additionally, we sat down and spoke with some of our current clients, who represent a large part of our websites audience, and asked them some questions, including What content are you coming to our website for when on a desktop computer? and How about on a tablet or a phone? The interviews were obviously more in depth than this, but you can see what we were asking. Once again, we found that the content they were seeking was the same, regardless of the device they were using. DATA DICTATES DIRECTION The findings from our research reinforced our belief that a responsive approach, which provides access to the same content across all devices, was the right choice for our website. This research also enabled us to determine what content on our website was not being accessed at all. When we discovered pages that were not being used by our audience, we cut them from our site map. Similarly, content that was most popular was treated appropriately in our content hierarchy and our layout plans for the redesign. By starting the project by looking at our content and gathering data on what was important to our audience and what was not, we were able to move into the design phase with an informed plan for what content our websites design needed to support.

4 of 21

TUTORIALS BUILDING A BETTER RESPONSIVE WEBSITE

DESIGNING TO THE EXTREMES I have heard the arguments for designing in the browser, and I appreciate many of the benefits this approach brings. That being said, having tried designing in the browser on a number of occasions, I have found that my own design workflow is simply better suited to starting in Photoshop. In no way do I think this is the right decision for everyone, but it is the right decision for me, and it is how I began this design. For responsive designs, I use a method that I refer to as designing to the extremes. I start by designing the desktop version of the website. In this version, I work out the designs typography, tone and overall visual direction as well as the layout for the large screen view of the website. Once I am happy with this version of the design, I work on the small screen or mobile version of the website, using the same visual direction, but adjusting the layout as appropriate for the smaller screen. At the end of this process, I have visual examples of the two layouts of the website that will vary the greatest the biggest and the smallest screen versions of the design. These two examples will guide me as I begin the websites front-end development.

The extreme versions of the new website design


5 of 21

TUTORIALS BUILDING A BETTER RESPONSIVE WEBSITE

MOBILE FIRST The mobile-first approach to responsive design is not a new idea. This method, whereby you build the mobile experience and layout of a website first and then use media queries to adjust and add to that layout as the screen size grows, has been considered a best practice in responsive Web design for some time now. While not a new approach, it is still an important one, and coupled with our plan to start with the content, it helped us to address one of the shortcomings that we identified in our responsive projects the problem of delivering unnecessary content. By starting with content, we ensured that all of our websites content was relevant and appropriate to all users, mobile or otherwise. This meant that we didnt have to worry about delivering large amounts of content in the markup only to have to hide it visually with CSS. The mobile-first approach meant that images would be delivered only to devices they are intended for. For instance, our new design called for a background graphic of a watercolor texture. The image, which is quite large, is intended to be a part of the design only on larger screens (660 pixels and up). Because our CSS starts with the mobile design first, this large graphic is never sent to small-screen devices because the media query that loads the image is activated only by larger screens. That media query, which applies the background to our html element, looks like this:
@media only screen and (min-width: 660px) { html { background: url(/images/bg-watercolor.jpg) no-repeat fixed center top; } }

In addition to adding that background image, this media query that is triggered at 660 pixels also introduces a number of other layout changes to the website, transitioning from what we consider the small-screen layout to what will become the various larger-screen versions.

6 of 21

TUTORIALS TBUILDING A BETTER RESPONSIVE WEBSITE

BUILDING TO THE DESIGN, NOT TO DEVICES When we began using responsive design in our Web projects, we focused on known devices and screen sizes, and our media queries often reflected those known devices (iPhones, iPads in both portrait and landscape orientation, laptops, widescreen desktops, etc.). Over time, we found that this was not the best approach because it only addressed the devices and screen sizes that were popular today and not those that may come in future. One of the strengths of responsive Web design is its future-friendly aspect. So, to fully realize that strength, we moved away from building to devices, instead allowing the design to dictate our media query breakpoints. The mobile-first method established the baseline for our websites CSS. With that in place, we launched the website in a browser and scaled it to the smallest size of our layout (we set a minimum width of 320 pixels in the CSS). Slowly, we increased the size of our browser window to see how the layout responded. As the browser window widened, we noticed that the layout began to feel strained. It was at these points that we would need to establish a new media query to adjust the layout. To help us with this approach, we created a graphic and set it as the background of our desktop. With vertical lines showing us a width of 320 pixels (our smallest size) and then a break at every hundred pixels starting with 400, we used this as a guide as we scaled the browser window to determine This desktop background can be used to help deterwhere the design started mine the breakpoints needed for a responsive design. to break down, and then used those approximate pixel values in the resulting media queries that we added to the CSS.

7 of 21

TUTORIALS BUILDING A BETTER RESPONSIVE WEBSITE

This approach of adding media queries based on the needs of the design, rather than on known device sizes, enables a website to better respond to a wider range of screen sizes. It does, however, end up filling the CSS file with more media queries than if you were using device-specific breakpoints. Still, while the number of media queries is higher, the queries themselves tend to be very small because you are making few changes with each one, rather than making the sweeping changes normally needed for device-specific media queries. One area of our website where this increase in media queries is evident is the navigation. RESPONSIVE NAVIGATION Handling navigation is one of the most challenging aspects of responsive design. For our website, we essentially have four main areas of navigation. 1. Primary navigation; 2. What we call the help navigation, which links to various portals and services that our clients use; 3. Footer navigation; 4. Section-specific navigation, which is presented on subpages of the website (for the larger-screen layouts) in the left-hand column. Because our CSS is mobile-first, one of the first things we did was to establish the navigation for our small-screen layout. This meant turning off the display of all of the navigation sections except for the primary navigation.
#helpNav, .subNav, footer nav { display: none; }

Now, I said earlier that our goal was not to deliver content to devices only then to turn it off. That was indeed the goal, but with our navigation, we had to accept that this was how we needed to do it. We werent able to find another, simple yet maintainable, solution. Luckily, the content we are delivering and not displaying turns out to be only a few lists, so the impact on downloading for visitors is minimal. The help navigation is the one area of the website that has been considered to be not relevant to most users, because these links and portals are intended only for desktop users. Now thats a big assumption and a bold statement. The rationale
8 of 21

TUTORIALS BUILDING A BETTER RESPONSIVE WEBSITE

behind this was that the portals themselves, which are all third-party applications over which we have no control, are not optimized for very small-screen mobile devices, and the services they offer are geared to supporting corporate clients with large screens on desktops. This situation informed our decision to remove that section from the small-screen version and in the months that the site has been live we received no comments or complaints from our user base regarding that decision. For the other two navigation areas, our subpage section navigation and our footer navigation, this content is presented as part of the primary navigation for small-screen devices. This is why we turn off these three areas by default. Later, as the screen size increases and we get past the 660-pixel point where the larger-screen design begins to show, we will style these navigation areas as needed. Here is the CSS for our help navigation:
#helpNav { display: block; position: absolute; top: 1px; right: 0px; width: 100%; text-align: right; } #helpNav ul { padding-left: 10px; } #helpNav li { display: inline; padding-right: 6px; padding-left: 6px; background-color: #2f6a98; } #helpNav a { font-size: 12px; padding: 0 6px; color: #FFF; border-radius: 20px; } #helpNav a:hover {
9 of 21

TUTORIALS BUILDING A BETTER RESPONSIVE WEBSITE

background-color: #f66606;

And our subpage navigation areas:


.subNav { display: block; width: 25%; float: left; } .subNav h4 { padding-bottom: 8px } .subNav ul { list-style: disc; color: #c65204; padding: 0 0 20px 20px; } .subNav li { padding-bottom: 14px; } .subNav a { color: #186483; font-size: 21px; font-family: RokkittRegular, Times, Times New Roman, serif; line-height: 1; }

Finally, our footer navigation:


footer nav { display: block; margin-top: 40px; } footer nav ul { list-style: none; } footer nav li { padding-bottom: 24px; width: 19%; padding: 0 5% 20px 0;
10 of 21

TUTORIALS BUILDING A BETTER RESPONSIVE WEBSITE

float: left;

.innerNav li { width: 100%; float: none; padding-bottom: 4px; } footer nav a { color: #575454; font-size: 12px; } .innerNav a { font-weight: normal; }

PIXELS VS. EMS You will notice that we have used pixel values in our media queries. Using pixel-based media queries is how we, like many front-end developers, began implementing responsive design, and we have maintained the practice as part of our responsive workflow. In the spirit of building a better responsive website, though, Ill point out an article on proportional media queries using ems that was brought to our attention during the editing of this piece. Essentially, to improve the appearance of the site when zoomed in, its highly recommended to convert px-media queries into em-media queries by dividing all pixel values by the body font-size. This wonderful article has caused us to rethink our pixel-based approach to media queries, and it is another example of how we continue to refine our responsive approach. While we did not use ems in our media queries in this particular project, we are experimenting with them now, and the approach is worth mentioning here.

11 of 21

TUTORIALS BUILDING A BETTER RESPONSIVE WEBSITE

PRIMARY NAVIGATION Our primary navigation is presented on wide screens as a horizontal row across the top of the layout. On small screens, this primary navigation structure changes so that there is a large Menu button at the top of each page that links to the navigation at the bottom of the page. To accomplish this, we added a link with an ID of menuLink and a class of tabButton in the header, which is near the start of the markup. We then placed a division with an ID of mainNav at the very end of the markup. Inside that division is our main navigation, which is simply an unordered list with a number of other unordered lists inside it for the subpage section menus. We also have another anchor with an ID of toTop, which acts as a link back to the top of the page.

The small-screen layout presents a Menu button at the very top of the layout.

12 of 21

TUTORIALS BUILDING A BETTER RESPONSIVE WEBSITE

Continuing our mobile-first approach, we styled the menu link at the top of the small-screen layout to look like a button.
#menuLink a { float: right; margin: -56px 8px 0 0; } .tabButton a { color: #FFF; font-family: RokkittRegular, Times, Times New Roman, serif; font-size: 20px; background-color: #45829b; padding: 10px 12px; border-radius: 10px; } .tabButton a:hover { background-color: #f66606; }

Our main navigation menu is set to its small-screen display:


#mainNav { margin-top: 30px; width: 100%; } #mainNav #toTop a { float: right; margin: 0 8px 0 0; font-size: 20px; } #mainNav nav { padding-top: 80px; } #mainNav ul { list-style: none; } #mainNav li { background: #45829b; border-bottom: 1px solid #abc7d2; padding: 4px 10px 4px 15px; }
13 of 21

TUTORIALS BUILDING A BETTER RESPONSIVE WEBSITE

#mainNav li:hover { background-color: #f66606; } #mainNav a { font-size: 24px; color: #FFF; font-family: RokkittRegular, Times, Times New Roman, serif; }

Our websites primary navigation as presented for small-screen layouts

14 of 21

TUTORIALS BUILDING A BETTER RESPONSIVE WEBSITE

Our submenus, which are set not to display initially, we can now display as the page requires. Each of these submenus has a unique ID, such as servicesTab, and each section of the website has a class applied to the body tag. The class for the Company section is companyPage. We use this class to set styles for that entire section of the website. We use the class of the submenu sections to turn on the submenus as needed when a section is active.
.companyPage #companyTab ul, .newsPage #newsTab ul, .contactPage #contactTab ul, .servicesPage #servicesTab ul { display: block; }

The subpage navigation displayed for the small-screen layout


15 of 21

TUTORIALS BUILDING A BETTER RESPONSIVE WEBSITE

GETTING LARGER As the larger-screen layouts kick in once again with the media query for 660 pixels and above we dramatically change the primary navigations layout. First, we turn off the display of the menuLink and toTop buttons because they are no longer needed:
#menuLink a, #toTop a { display: none; }

Next, we style the mainNav horizontally across the top of the page to achieve the larger-screen design:
#mainNav { position: absolute; top: 92px; margin: 18px 2% 0 2%; width: 96%; text-align: center; } #mainNav nav { padding: 5px 0; border-top: 1px solid #bacfd7; border-bottom: 1px solid #bacfd7; } #mainNav li { background: none; display: inline; border-bottom: 0; border-right: 1px solid #bebebe; padding: 0 6px 0 8px; margin: 4px 0; } #mainNav a { font-size: 16px; color: #45829b; } #mainNav a:hover { color: #f66606; }
16 of 21

TUTORIALS BUILDING A BETTER RESPONSIVE WEBSITE

These styles set the look of our primary navigation. But to build to the design, instead of to the device, we will need to make small adjustments as the screen size grows. Our primary navigations font has eight different sizes in total for the largerscreen layouts, changing as the screen grows and as we have more room to work with. Figuring out how best to display this navigation so that it is both easy to use and visually attractive was one of the challenges we faced while working with this responsive design. Initially, our font size is set to 16 pixels. Once we hit 767 pixels in width, we bump that to 18 pixels.
@media only screen and (min-width : 767px) { #mainNav a { font-size: 18px; } }

We continue this pattern a number of times, increasing the font size finally to 27 pixels as the website reaches its largest size. In this way, the websites navigation truly responds best to the design and to the screen being used to view that design. GETTING HELP FROM THE CMS Our preferred CMS is ExpressionEngine, and the specifics of this next portion of the article refer to that platform, but the general idea of what we accomplished with ExpressionEngine could undoubtedly be applied to other popular CMS platforms as well. One of the biggest drawbacks to the responsive approach is that you cannot deliver different markup or a different source order to different devices. This drawback is what we wanted to overcome with our CMS. During our experimentation and research, we stumbled upon an article titled Going Truly Adaptive With ExpressionEngine. Using the approach detailed in this article, we were able to use a device-detection script to set a variable in the system of either mobile or full. We could then conditionally load markup into our website based on which of these variables was met. By going further and using the device detection, we were able to make other very small changes to further improve the mobile experience. To us, this was kind of like
17 of 21

TUTORIALS BUILDING A BETTER RESPONSIVE WEBSITE

progressive enhancement, where we created a quality solution and then tried to take it further to deliver a slightly more optimized experience. Make sure to read Chris Coyiers similar view on combining RWD and mobile templates in which he argues about mixing and matching a variety of techniques for your mobile strategy. STARTING SMALL You could certainly use these variables to deliver completely different markup and source orders to different devices, but our initial approach was a little less extreme. Because we had already decided that all versions of our website would have access to all content, we initially used this variable method to make slight adjustments to how much of that content would be delivered. For instance, on our websites home page, we show teasers for a variety of content found within the website. For the Culture and Project Spotlight sections, an image accompanies each post. The images are a nice-to-have addition but certainly not critical, so we do not deliver these images to mobile users at all. Now, I do not mean that we use CSS to turn off their display, which would cause the data to get delivered to the browser anyway; instead, we use the variables we have established to omit the images from the markup unless they need to be shown.

The teaser images are nice to have, but not critical to the content or layout.

18 of 21

TUTORIALS BUILDING A BETTER RESPONSIVE WEBSITE

The syntax is quite easy. Once you have established your variables which the aforementioned article explains how to do easily by adding a little script to the systems config.php file you can use those variables like an if statement.
{if global:site_version==full}<img src={teaser-image} alt={title} />{/if} {if global:site_version==mobile} {title}{/if}

This is ExpressionEngine syntax, but you should be able to read this and easily see what is happening. If the full variable is met, then we deliver the teaser-image from that articles entry in the database. If the mobile variable is met instead, then we deliver the title of the article. We use this same approach for the home pages News and Blog sections, delivering three short teasers if the full variable is met and only one if the mobile one is. That syntax looks like this:
{exp:channel:entries channel=news {if global:site_version==full}limit=3{/ if}{if global:site_version==mobile}limit=1{/if}}

Here you see that we are accessing the ExpressionEngine channel named news. We use our variable to determine how many recent entries will be displayed from that channel, using the limit parameter. TAKING IT A STEP FURTHER In the websites Culture section, we publish articles that are often accompanied by a number of images. Unlike the teaser images on the websites home page, the images in the articles themselves are critical to that content, because they help to carry or reinforce the articles point. Now, while the images are important, they are also quite large each one is 650 pixels wide, and most articles include at least three images and as many as ten. Because mobile devices will show the images at about half their original size, the downloads for the full-sized images would be quite substantial. To address this, we once again turned to our device detection and variables. For each article, we produce two sets of images: one full sized at 650 pixels wide and a second set at almost half that size. We then use the variables in our article (but first we need to allow ExpressionEngine code in our pages template), and we include the markup for both sets of images but only one set is ever delivered to the browser. Mobile devices get the smaller images, while everything else gets
19 of 21

TUTORIALS BUILDING A BETTER RESPONSIVE WEBSITE

the normal set. We take a similar approach with the home pages large billboard area. These rotating banner messages and images are used to promote important items, such as upcoming events, new services and announcements, in a bigger way than we do in the other areas of the home page. The billboard is another nice-to-have element that is intended for large displays only. Once again, we use the variables to deliver the main billboard division, as well as the JavaScript that runs it, to appropriate devices effectively enabling us to send different markup to different devices and eliminating yet another of the drawbacks that we identified at the start of this project. Through a mobile-first approach and with our CMS help, we are able to deliver our home page to desktop users at 738.3 KB and dramatically reduce that to only 174.4 KB for mobile users. FALLBACK PLANS One of the questions that has always bothered me about a mobile-only approach and device detection is, What happens if that detection fails? Is the normal version of the website delivered to the mobile device, thereby rendering your carefully designed mobile experience null and void? This possibility is one of the main reasons why I have avoided a mobile-only solution that uses device detection in the past. For our new responsive workflow, we are using device detection, but our process has equipped us with excellent fallbacks in case that detection fails for some reason. Because we are using a responsive approach, even if the full version get delivered to a mobile browser, the layout will be suited to that device because our CSS will adjust the websites layout accordingly. Additionally, because we went with a mobile-first build, items not intended for small screens, such as the giant background graphic mentioned above, do not get delivered either. The only thing that will fail is what we have done with our device detection-generated variables. If the worst-case scenario happens and our detection fails, then the mobile version would simply get a few extra images or a little markup or JavaScript that it does not need. The experience would still be suited to mobile. Not bad at all for a worst-case scenario.

20 of 21

TUTORIALS BUILDING A BETTER RESPONSIVE WEBSITE

PROGRESS, NOT PERFECTION A few years ago, a client said something to me that has stuck with me to this day. Talking about his website, he said:

ont worry about making my website perfect. Just work on making it better. If were constantly making it better, were going in

the right direction.

This idea has guided me over the years and reminded me never to dismiss a better solution simply because it is not perfect. I know this is not a perfect solution, and I am OK with that because it is an improvement to our previous responsive workflow. It has helped us overcome some obstacles that we identified, and we can now bring those improvements to other projects we are working on. Yes, there are still many issues that we have yet to effectively address, such as the delivery of higher-quality images to HD displays as well as the use of em-based media queries referred to earlier in this piece, but we are moving in the right direction for this project and for others. Who knows? Maybe someday someone will build a perfect website. In the meantime, we will focus on progress, not perfection, as we continue to make small improvements along the way, working to build a better responsive website.

Jeremy Girard
Director of Web Development

HIS BLOG

SHARE

TWITTER

GITHUB

appliness

TUTORIALS LIBRARY

BOOKMARK / SHARE / TOC

A responsive boilerplate
by Fernando Monteiro

TUTORIALS A RESPONSIVE BOILERPLATE

by Fernando Monteiro
SKELETON FRAMEWORK

This is my micro framework to build responsive websites

Hello everyone, my name is Fernando Monteiro and im front-end developer in Brazil. Today I will write a few lines about the micro framework, ResponsiveBoilerplate, which can be downloaded for free through the url: http://www.responsiveboilerplate.com, and github repository at: https://github.com/newaeonweb/responsiveboilerplate. It began in mid-2010 when I was hired to work in a big project of web software. Our aim was to create a big news portal using some techniques of fluid grids, at that time still unheard effectively responsive design here on our land, everything was very new and unknown even to our team of experienced developers. Then I read the book by Etham Marcote called Responsive Design, it changed my way of thinking and seeing the new reality of web development at the time. In that same season I began researching similar solutions and also trying to develop something solution in this regard. A few minutes of google search brought me a lot of the same options that I had in mind. It was there that I had my first actual contact with a responsive framework: Skeleton Framework, too be more exactly. Since that time already used and researched a lot of frameworks, among them, bootstrap, 1140, 960gs, baseline, Ink among others, I also had the opportunity to develop small websites using these tools so i decide to write myself a micro framework . The ResponsiveBoilerplate is a micro framework, based on columns, to be exact, there are 12 columns and a container. The biggest difference is the simplicity in writing and ease of use. In a more detailed analysis, most frameworks have 50-60% of code (css) is not used in structuring simple pages. I say this without counting the stylesheets that bring additional formatting, colors, prefixes, forms and jquery plugins to do simple tasks like accordion, or slideshow.

2 of 3

TUTORIALS A RESPONSIVE BOILERPLATE

In ResponsiveBoilerplate, everything has been designed to be as simple and intuitive as possible, so the developer gains more flexibility in use and not waste time reading a big documentation. The learning curve is very small compared to other framework. Also, included in download package some snippets for sublime text editor, a template for photoshop and a basic javascript for navigation. Of course he is not the best framework and does not intend to be. But the intention is to provide just the basics needed to build responsive layouts. Some features: - Very Lightweight - Contains only 12 columns and 1 container as the main base. - Low learning curve to use. - Optimized for mobile devices. - Includes four breakpoints for the most common resolutions (320, 480, 768, 1024). - No minimum limit of width. Fits any screen size, even in screens of 32 inches or more. Use respond.js and head.js for better performance. - Its free ... and contributions are most welcome ... A demo: http://riagora.com/appliness/samples/responsive/demo.html Source code of the demo: http://riagora.com/appliness/samples/responsive/source.zip

Fernando Monteiro
Web Developer

HIS BLOG

SHARE

TWITTER

GITHUB

appliness

TUTORIALS HTML

BOOKMARK / SHARE / TOC

The Progress Element.


by Ian Devlin

TUTORIALS THE PROGRESS ELEMENT

by Ian Devlin

HTML5 makes life easier for us by defining the right element.

This article was originally published on the html5 Doctor website on February 12, 2013. You can read it here.

When building web sites and web applications, we often need to provide essential feedback to a user informing them of the progress of their request or task, be it uploading a file, playing a video, or importing data. HTML5 makes life easier for us by defining an element whose sole purpose is just that: the <progress> element.

The progress element represents the completion progress of a task .

The HTML5 specification describes it best: The progress element represents the completion progress of a task. The task itself is irrelevant, but displaying its progress is not.

2 of 8

TUTORIALS THE PROGRESS ELEMENT

ATTRIBUTES There are four attributes that are specified for the <progress> element: max, value, position, and labels. Before taking a look at each of theses attributes in turn, here are a few important notes on them: If the value attribute exists, then the progress bar is considered to be determinate (i.e., it has exact limits). Otherwise it is considered to be indeterminate. If the max attribute is not included, the default acceptable range for the progress bar is between 0.0 and 1.0 inclusive. Authors are encouraged always to include the current value and the maximum value (if used) as inline text to the <progress> element so that the information is still visible to users of legacy browsers. And now lets take a closer look at the attributes themselves: Max The max attribute is a floating point number that indicates how much work the relevant task requires in total before it can be considered complete. The default value is 1.0. Value This is a floating point number that represents the current progress of the relevant task. Its value must be greater than or equal to 0.0 and less than or equal to 1.0 or the value of the max attribute if present. Position This is a read-only attribute that returns the current position of the <progress> element. This value is equal to value / max for a determinate progress bar and -1 for an indeterminate progress bar (as the position cant accurately be determined). Labels This is also a read-only attribute that returns a list of the <progress> elements labels (if there are any).

3 of 8

TUTORIALS THE PROGRESS ELEMENT

EXAMPLES Lets now take a look at some examples of how the <progress> element might be used, including how it might be updated via JavaScript. SIMPLE INDETERMINATE PROGRESS BAR
<progress id=p></progress>

Since we have no idea how long the task in hand will take, the browser will simply display the progress bar until the task is complete and we either hide it or replace it with a task complete message. SIMPLE DETERMINATE PROGRESS BAR
<progress id=p max=70><span>0</span>%</progress>

And the JavaScript for updating it:


var pBar = document.getElementById(p); var updateProgress = function(value) { pBar.value = value; pBar.getElementsByTagName(span)[0].innerHTML = Math.floor((100 / 70) * value); }

Note that here the progress bar can have a maximum value of 70, so calls to updateProgress will have values between 0 and 70 and that the value is also displayed within the <progress> element so that it is visible as a simple percentage string for users of legacy browsers. USING <PROGRESS> WITH HTML5 VIDEO A good example of using the <progress> element is with an HTML5 video, informing the user how much of the video has been played. This wont be a full example but will just show the necessary HTML and JavaScript.

4 of 8

TUTORIALS THE PROGRESS ELEMENT

Given a <video> element with an id of v:


<progress id=p max=100 value=0><span>0</span>% played</progress>

Use this JavaScript:


var video = document.getElementById(v); var pBar = document.getElementById(p); video.addEventListener(timeupdate, function() { var percent = Math.floor((100 / video.duration) * video.currentTime); pBar.value = percent; pBar.getElementsByTagName(span)[0].innerHTML = percent; }, false);

The JavaScript uses the timeupdate event, which is constantly triggered as the video is being played. The value is converted into a percentage value using the videos duration (full length) and currentTime (where in the video it currently is). USING <PROGRESS> WITH THE FILE API Another useful example is how the <progress> element might be used with the File API. Again, this is not a complete example, assuming the existence of a file input and upload button and <progress> element, and code for reading the file. The specification itself has some good code examples of this.
var p = document.getElementById(p); // reader is of type FileReader reader.addEventListener(loadstart, function(evt) { if (evt.lengthComputable) p.max = evt.total; }, false); reader.addEventListener(progress, function(evt) { if (evt.lengthComputable) p.value = evt.loaded; }, false);

Here the loadstart event is used to set the max attribute of the <progress> element, and then the progress event is used to update the <progress> elements value attribute.

5 of 8

TUTORIALS THE PROGRESS ELEMENT

BROWSER SUPPORT The <progress> element is fairly well-supported in todays major browsers, although only in version 6+ of Safari (so not on Windows, as the last version there was 5.1) and only in version 10+ of Internet Explorer. STYLING As is usual with such elements, browsers have their own unique styling for the <progress> element. You can, however, override this to a certain extent using simple CSS. The default styling tends to consist of an element with rounded corners, a grey background colour, and a green gradient for the actual progress marker.

The default styling for the progress element in Firefox 18.0.2. Lets say we want to style our progress bar for the HTML5 Doctor website, so that it fits in with the design. Well remove the bevel and the gradients using only solid colours. The code below will almost do that:
progress { color: #0063a6; font-size: .6em; line-height: 1.5em; text-indent: .5em; width: 15em; height: 1.8em; border: 1px solid #0063a6; background: #fff; }

This, however, wont change the colour of the progress bar itself, which will remain a green colour. We can change this in Firefox, Internet Explorer 10, Chrome, and Safari using a variety of methods which are outlined below.

6 of 8

TUTORIALS THE PROGRESS ELEMENT

FIREFOX All we need to use here is:


progress::-moz-progress-bar { background: #0063a6; }

and Firefox will display the colour correctly.

The progress bar as it appears in Firefox 18.0.2 after being styled. CHROME AND SAFARI UPDATE 13TH FEBRUARY 2013 Opera have just announced their move to using WebKit as their rendering engine, so eventually the WebKit specifc styling rules will also work in Opera. For Chrome and Safari, we need to use progress::-webkit-progress-value to specify the progress bar colour and progress::-webkit-progress-bar to specify the background colour of the <progress> element itself:
progress::-webkit-progress-bar { background: #fff; } progress::-webkit-progress-value { background: #0063a6; }

INTERNET EXPLORER 10 Actually the CSS above will be fine to style the <progress> element in IE10, but its worth noting that this browser interprets the <progress> elements color value as the colour of the progress bar. Ive uploaded some working examples of determinate and indeterminate progress bars for you to see.

7 of 8

TUTORIALS THE PROGRESS ELEMENT

SUMMARY The <progress> element may seem very similar to the <meter> element which was also introduced in HTML5 but it can be seen as a more specific kind of <meter> element thats only used to measure progress of a task. Its worth bearing this in mind when deciding which one to use. Since browser support is pretty good, its definitely worth using the <progress> element where appropriate, but you should also ensure that you provide textual fallback for legacy browsers as has been outlined above.

Ian Devlin
Web Developer

HIS BLOG

SHARE

TWITTER

GITHUB

appliness

TUTORIALS CSS

BOOKMARK / SHARE / TOC

Dig Deep into CSS Linear Gradients.


by Ana Tudor

TUTORIALS DIG DEEP INTO CSS LINEAR GRADIENTS

by Ana Tudor
INTRODUCTION

I had no idea how powerful CSS gradients could be until late 2011.

Ana Tudor is passionate about experimenting and learning new things. Also she loves maths and enjoys playing with code. I had no idea how powerful CSS gradients could be until late 2011, when I found the CSS3 Patterns Gallery made by Lea Verou. The idea that you can obtain many shapes using just gradients was a starting point for many CSS experiments I would later do. Recently, while browsing through the demos on CodePen, I came across a CSS3 Color Wheel and thought hey, I could do it with just one element and gradients. So I did and the result can be seen here. And now Im going to explain the reasoning behind it. BREAKING IT DOWN The wheel - or you can think of it as a pie - is first split horizontally into two halves and then each half is split into five slices, so there are ten slices in total. Which means that the central angle for each slice is 360/10 = 36. The pen shows graphically how to layer the multiple backgrounds. It also has a pause button so that the infinite animation doesnt turn into a performance problem.
2 of 10

TUTORIALS DIG DEEP INTO CSS LINEAR GRADIENTS

For both the original pen and this helper demo, the interesting part is this one:
background: linear-gradient(36deg, #272b66 42.34%, transparent 42.34%), linear-gradient(72deg, #2d559f 75.48%, transparent 75.48%), linear-gradient(-36deg, #9ac147 42.34%, transparent 42.34%) 100% 0, linear-gradient(-72deg, #639b47 75.48%, transparent 75.48%) 100% 0, linear-gradient(36deg, transparent 57.66%, #e1e23b 57.66%) 100% 100%, linear-gradient(72deg, transparent 24.52%, #f7941e 24.52%) 100% 100%, linear-gradient(-36deg, transparent 57.66%, #662a6c 57.66%) 0 100%, linear-gradient(-72deg, transparent 24.52%, #9a1d34 24.52%) 0 100%, #43a1cd linear-gradient(#ba3e2e, #ba3e2e) 50% 100%; background-repeat: no-repeat; background-size: 50% 50%;

We first specify the nine gradient backgrounds, their positioning and the background-color using the shorthand background syntax. THE BACKGROUND SHORTHAND For anyone who doesnt remember, the background layers are listed from the top one to the bottom one and the background-color is specified together with the bottom layer. A background layer includes the following: <background-image> <background-position> / <background-size> <background-repeat> <background-attachment> <background-origin> <background-clip> If the background-position is not specified, then the background-size isnt specified either. Also, since background-origin and background-clip both need the same kind of value (that is, a box value like border-box or contentbox), then, if there is only one such value, that value is given to both backgroundorigin and background-clip. Other than that, any value except the one for background-image can be missing and then it is assumed to be the default. Since we have nine background layers and we want to have the same non-default
3 of 10

TUTORIALS DIG DEEP INTO CSS LINEAR GRADIENTS

values for background-repeat and background-size for all of them, we specify these outside the shorthand so that we dont have to write the same thing nine times. In the case of background-size, there is also another reason to do that: Safari doesnt support background-size inside the shorthand and, until recently (up to and including version 17), Firefox didnt support that either. Also, two values should be always given when the background-image is a gradient, because giving it just one value is going to produce different results in different browsers (unless that one value is 100%, in which case it might as well be missing as that is the default). The background-color is set to be a light blue (#43a1cd) and then, on top of it, there are layered nine non-repeating (background-repeat: no-repeat for all) background images created using CSS gradients. All nine of them are half the width and the height of the element (background-size: 50% 50%). The bottom one - horizontally centred (50%) and at the bottom (100%) - is really simple. Its just a gradient from a firebrick red to the same color (lineargradient(#ba3e2e, #ba3e2e)), so the result is simply a solid color square. The other eight are gradients from transparent to a solid color or from a solid color to transparent. Four of them look like double slices, having a central angle of 2*36 = 72, but half of each such double slice gets covered by another single slice (having a central angle of 36).

Safari doesnt support background-size inside the shorthand

4 of 10

TUTORIALS DIG DEEP INTO CSS LINEAR GRADIENTS

A FEW THINGS ABOUT LINEAR GRADIENTS In order to better understand gradient angles and how the % values for color stops are computed, lets see how a linear gradient is defined. Hopefully, this demo that lets you change the gradient angle helps with that - just click the dots.

The gradient angle is the angle - measured clockwise - between the vertical axis and the gradient line (the blue line in the demo). This is for the new syntax, which is not yet supported by WebKit browsers (however, this is going to change). The old syntax measured angles just like on the trigonometric unit circle (counter-clockwise and starting from the horizontal axis). Note: coming from a mathematical background, I have to say the old way feels more natural to me. However, the new way feels consistent with other CSS features, like rotate transforms, for which the angle values are also clockwise. What this means is that we (almost always) have different angle values in the standard syntax and in the current WebKit syntax. So, if we are not using something like -prefix-free (which I do almost all the time), then we should to be able to compute one when knowing the other. That is actually pretty simple. They are going in opposite directions, so the formula for one includes the other with a minus sign.

5 of 10

TUTORIALS DIG DEEP INTO CSS LINEAR GRADIENTS

Also, there is a 90 difference between them so this is how we get them:


newSyntax = 90 - oldSyntax; oldSyntax = 90 - newSyntax;

Note: if no gradient angle or destination side is specified (for example, linear-gradient(lime, yellow)), then the resulting gradient is going to have a gradient angle of 180, not 0. All the points on a line that is perpendicular on the gradient line have the same color. The perpendicular from the corner in the quadrant thats opposite to the quadrant of the angle is the 0% line (the crimson line in the demo) and its intersection with the gradient line is the starting point of the gradient (lets call it S). The perpendicular from the opposite corner (the one in the same quadrant as the gradient angle) is the 100% line (the black line in the demo) and its intersection with the gradient line is the ending point of the gradient (lets call it E).

In order to compute the % value of any point P, we first draw a perpendicular on the gradient line starting from that point. The intersection between the gradient line and this perpendicular is going to be a point well name I. We now compute the ratio between the lengths of SI and SE and the % value for that point is going to be 100% times that ratio.

6 of 10

TUTORIALS DIG DEEP INTO CSS LINEAR GRADIENTS

PUTTING IT ALL TO WORK Now lets see how we apply this for the particular case of the rainbow wheel. Lets first consider a gradient that creates a single slice (one with a central angle of 36). This is a square image (see below), with a blue slice having an angle of 36 in the lower part. We draw the horizontal and vertical axes through the point O at which the diagonals intersect. We draw a perpendicular from that point to the line that separates the dark blue part from the transparent part. This is going to be the gradient line. As it can be seen, there is a 36 angle between the vertical axis and the gradient line, so the angle of the gradient is 36. We now draw a perpendicular from the corner of the square in the quadrant that is opposite to the one in which the gradient angle is found. This is the 0% line. Then

we draw a perpendicular from the corner of the square in the same quadrant (Q I) as the gradient angle - this is the 100% line. The intersection of the diagonals of a square splits each one of them into two, so
7 of 10

TUTORIALS DIG DEEP INTO CSS LINEAR GRADIENTS

AO and BO are equal. The BOE and AOS angles are equal, as they are vertical angles. Moreover, the BOE and AOS triangles are right triangles. All these three mean that the two triangles are also congruent. Which in turn means that SO and EO are equal, so the length of SE is going to be twice the length of EO or twice the length of SO. Note: before moving further, lets go through a couple of trigonometry concepts first. The longest side of a right-angled triangle is the one opposing that right angle and its called the hypotenuse. The other two sides (the ones forming the right angle) are called the catheti of the right triangle. The sine of an acute angle in a right triangle is the ratio between the cathetus opposing that angle and the hypotenuse. The cosine of the same angle is the ratio between the adjacent cathetus and the hypothenuse. Computing the length of EO in the right triangle BOE is really simple. If we take the length of the side of the square to be a, then the length of the half diagonal BO is going to be a*sqrt(2)/2. The BOE angle is equal to the difference between the BOM angle, which is 45, and the EOM angle, which is 36. This makes BOE have 9. Since BO is also the hypotenuse in the right triangle BOE, the length of EO is going to be (a*sqrt(2)/2)*cos9. Which makes the length of SE be a*sqrt(2)*cos9. We now draw a perpendicular from A to the PI line. ASID is a rectangle, which means that the length of SI equals the length of AD. We now consider the rectangular triangle APD. In this triangle, AP is the hypotenuse and has a length of a. This means that AD is going to have a length of a*sin36. But SI is equal to AD, so it also has a length of a*sin36. Since we now know both SI and SE, we can compute their ratio. It is sin36/ (sqrt(2)*cos9) = 0.4234. So the % value for the color stop is 42.34%.

8 of 10

TUTORIALS DIG DEEP INTO CSS LINEAR GRADIENTS

In this way, weve arrived at: linear-gradient(36deg, #272b66 42.34%, transparent 42.34%) Computing the % values for the other background layers is done in the exact same manner. AUTOMATING ALL THIS By now, youre probably thinking it sucks to do so many computations. And it must be even worse when there are more gradients with different angles... Even though for creating the rainbow wheel experiment I did compute everything on paper... I can only agree with that! This is why I made a really basic little tool that computes the % for any point inside the gradient box. You just need to click inside it and the % value appears in a box at the bottom center.

You can change the dimensions of the gradient box and you can also change the gradient itself. It accepts the newest syntax for linear gradients, with angle values in degrees, to <side> values or no value at all for describing the direction of the gradient.
9 of 10

TUTORIALS DIG DEEP INTO CSS LINEAR GRADIENTS

FINAL WORDS CSS gradients are really powerful and understanding how they work can be really useful for creating all sorts of imageless textures or shapes that would be difficult to obtain otherwise.

Ana Tudor
CSS & Math Expert

HER BLOG

SHARE

TWITTER

GITHUB

appliness

TUTORIALS CSS

BOOKMARK / SHARE / TOC

The Problem of CSS Form Elements.


by Gabriele Romanato

TUTORIALS THE PROBLEM OF CSS FORM ELEMENTS

by Gabriele Romanato

Back in 2004 and later in 2007, Roger Johansson created a complete test suite for form elements and CSS.

This article was originally published on the Smashing Magazine website on March 31, 2013. You can read it here.

Before 1998, the birth year of CSS Level 2, form elements were already widely implemented in all major browsers. The CSS 2 specification did not address the problem of how form elements should be presented to users. Because these elements are part of the UI of every Web document, the specifications authors preferred to leave the visual layout of such elements to the default style sheet of Web browsers. Through the years, this lack of detail in the CSS specification has forced Web developers to produce a significant number of tests and examples whose primary goal is to reduce form elements to a common visual denominator in order to get a cross-browser rendering of elements such as input, select, fieldset, legend and textarea. In this article, we will cover some of the CSS patterns used by Web developers to tame the visual layout of form elements. ROGER JOHANSSONS TESTS Back in 2004 and later in 2007, Roger Johansson created a complete test suite for form elements and CSS. These seminal tests, which can be found in his article Styling Form Controls With CSS, Revisited, lead to the frustrating conclusion that Johansson summarizes with the following words:

o what does this experiment show? Like I already stated, it shows that using CSS to style form controls to look exactly the same across browsers and platforms is impossible. It also shows that most browsers ignore many CSS properties when they are applied to form controls.
2 of 9

TUTORIALS THE PROBLEM OF CSS FORM ELEMENTS

Despite the underlying truth of these conclusions, Web developers continued to extensively test CSS styles on form elements to find the Holy Grail of or at least a reasonable compromise between the browsers default rendering and the authors styles.

THE DEFAULT MODEL The CSS 2.1 specification states in its proposed default style sheet for HTML4 that form elements such as textarea, input and select are inline-block elements:
textarea, input, select { display: inline-block; }

Conversely, the form and fieldset elements are block-level elements:


fieldset, form { display: block; }

The default model proposed by the CSS specification stops here. All other visual aspects of form elements rely on the browsers default style sheet. However, the above rules indicate the following: Inline-block elements can be styled using an inline formatting context. This implies the use of CSS properties such as line-height and vertical-align to control the height of the box and its vertical alignment. Padding and margins can also be applied to define the outer and inner spacing of the affected box. As well, inline-block elements accept widths and heights because they share the block formatting model. Block-level elements can be styled using the well-known block formatting context. However, problems arise with the fieldset and legend elements because legend relies entirely on the default styles provided by Web browsers. How do Web developers manage these problems?

3 of 9

TUTORIALS THE PROBLEM OF CSS FORM ELEMENTS

DEFINING DIMENSIONS Web developers soon noticed that Web browsers handle inline-block elements oddly when it comes to defining dimensions. Defining an height often leads to unexpected results:
input, select { width: 120px; height: 32px; }

Developers tried to fix this problem by turning these elements into block-level elements:
input, select { width: 120px; height: 32px; display: block; }

Results are still poor, except for the textarea element. A common pattern to solve this problem is to avoid the height property and instead to use the fontsize and padding properties. Browsers do not use the same font family and size on these elements, so the first thing to do is normalize them:
input, select { width: 120px; font: 1em Arial, sans-serif; }

For an example, see the page CSS: Defining Form Element Dimensions on jsFiddle. Once the font in use is normalized, you can add padding to give some inner spacing to the elements box:
input, select { width: 120px; font: 1em Arial, sans-serif; padding: 3px 6px; }

4 of 9

TUTORIALS THE PROBLEM OF CSS FORM ELEMENTS

The input elements and textarea also show a border that affects their box model:
input[type=text], input[type=password], textarea { border: 1px solid #ccc; }

The input elements of the types button and submit have additional padding set by Web browsers. So, a common practice is to normalize them:
input[type=button], input[type=submit] { padding: 2px; }

The problem with this approach is that Web browsers also apply vendor-specific properties to these elements, so our padding is not always able to normalize this property. For example, in a Webkit-based browser, you might have this:
input[type=button], input[type=submit], input[type=reset], input[type=file]::-webkit-file-upload-button, button { -webkit-box-align: center; text-align: center; cursor: default; color: buttontext; padding: 2px 6px 3px; border: 2px outset buttonface; border-image: initial; background-color: buttonface; box-sizing: border-box; } input[type=button], input[type=submit], input[type=reset] { -webkit-appearance: push-button; white-space: pre; }

5 of 9

TUTORIALS THE PROBLEM OF CSS FORM ELEMENTS

Padding is also used on the fieldset and legend elements but with different results: Setting the padding on fieldset to 0 will reset the default indentation of the legend elements in some browsers (though not in IE). Setting the padding on legend to 0 has the effect of making this element shrink. Select boxes, checkboxes and radio buttons can be normalized with good results with only a few properties, namely: font-family, font-size, width (on select boxes), padding. Applying other properties to this group of elements often leads to inconsistent results across browsers.

ALIGNMENT Form elements can be vertically or horizontally aligned. They can be laid out on the same line or as a group of boxes on multiple rows. To align them on the same line, you can follow one of two approaches: 1. Use floating, 2. Use the default inline-block context on some of these elements. When you use floating, elements are automatically turned into block-level elements. This means that form elements are now subject to the nine rules that govern floated elements.
Form elements can be vertically or horizontally aligned.

6 of 9

TUTORIALS THE PROBLEM OF CSS FORM ELEMENTS

With floats, the main challenge is to achieve good vertical alignment on the current line. In this case, using vertical margins or padding is a common practice:
input, select { width: 120px; float: left; margin-top: 0.4em; }

This approach works when you do not have to align boxes with text, such as with the contents of a label element. In this case, you could use relative positioning, padding or margins on the element that contains only text:
label { float: left; padding-top: 0.4em; width: 5em; margin-right: 1em; }

Another problem arises with buttons. In this case, when you have a button whose dimensions are greater than those of other elements, you can force its vertical alignment with relative positioning:
input[type=submit] { float: left; width: 90px; position: relative; top: 0.4em; }

This approach with relative positioning also works with checkboxes and radio buttons. Relative positioning can even be applied to normalize the left indentation of the legend element within a fieldset element, the only difference being that you would use the left property instead of top. When using inline formatting, you can rely on the vertical-align property to vertically align elements:
label, input[type=text] { vertical-align: middle; margin-right: 1em; }

7 of 9

TUTORIALS THE PROBLEM OF CSS FORM ELEMENTS

Good results can be achieved by combining this property with the line-height property. However, this property must be set on the parent element. If you set this property directly on the forms elements, their computed height would be affected:
.form-row { line-height: 1.4; }

Using a declared height on the parent element is also effective when paired with the same value for the line height:
.form-row { line-height: 1.8; height: 1.8em; }

With inline formatting, you can also use the text-align property on the parent element to align elements to the right, left or center. THE STRANGE CASE OF FILE INPUTS The file input element that is, <input type=file/> is a special case. This kind of element must always be visible and recognizable in the browsers UI for security reasons. This implies that browsers deliberately ignore some style rules (such as those related to visibility) and tend to apply the algorithms defined in their default style sheet. Furthermore, the default rendering varies from browser to browser: some browsers display only a single button, while others add a text field to display the path of the uploaded file. Web developers, however, soon found a way to circumvent these limitations. First, they wrapped the input element in a container:
<form action= method=post enctype=multipart/form-data> <div class=upload> <input type=file name=upload/> </div> </form>

8 of 9

TUTORIALS THE PROBLEM OF CSS FORM ELEMENTS

Then, they hid the input element using the opacity property and applied certain styles to the inputs container:
.upload { width: 157px; height: 57px; background: url(upload.png) no-repeat; overflow: hidden; } .upload input { display: block !important; width: 157px !important; height: 57px !important; opacity: 0 !important; overflow: hidden !important; }

Notice the !important statement. This is the preferred way to override the browsers default rules. For an example, see the page CSS: Styling Inputs of Type file on jsFiddle. CONCLUSION Totally taming form elements is impossible due to the lack of detail in the CSS specification and because of the default styles applied by Web browsers. However, by following some common practices, reducing (though not eliminating) the differences and achieving good visual results are possible.

Gabriele Romanato
Web Developer

HIS BLOG

SHARE

TWITTER

GITHUB

appliness

TUTORIALS MOBILE

BOOKMARK / SHARE / TOC

PhoneGap Q&A
by Christophe Coenraets

TUTORIALS PHONEGAP Q&A

by Christophe Coenraets

Ive answered live questions about PhoneGap. Here is the summary.

Thanks to all of you who attended my Architecting a PhoneGap Application TechLive session, and thanks also for the great feedback. The recording is available here. A lot of my content was based on my PhoneGap Tutorial available here. Here are some questions I wanted to answer about PhoneGap:

I built an app using PhoneGap, jQuery, and LESS. There is a delay before the app responds to a button click.

After you tap a button, mobile browsers wait for about 300ms before they fire the click event. This is to make sure you are actually not performing a double tap. One simple solution is to use the touchend event instead of click. But there are two issues with that approach: - You have to change your code (replacing click with touchend), and touchend will not work when testing your app in the browser on your development machine. - Adding logic to the touchend event could interfere with other touch interactions (like scrolling). These two problems can be overcome by adding contextual logic to your event handlers. But before you reinvent the wheel, take a look at existing libraries that already address this problem. Fastclick.js is a good place to start. This Google Developers document is also a great resource to better understand the problem and the solution.

Will phonegap support upcoming mobile OSs Tizen & Mozilla mobile?
2 of 8

TUTORIALS PHONEGAP Q&A

Yes. Click the links below for more info: Tizen Firefox OS

How does one solve the problem of getting client approval for iOS devices without the issues of gathering their UDID for provisioning profiles?

Thats the Apple process and there is really nothing we can do here. PhoneGap Build can make it easier to distribute your app to beta testers during development, but you still need to get the UDID of their devices.

What kind of tips would you recommend for creating a responsive layout? I already know about media queries and I used a fittext.js for scaling the text within a div .

Take a look at Adobe Edge Reflow, a new Responsive Web Design tool (currently in preview).

How do you stop the tap-and-hold on a link which makes a flyout menu to open to browser/copy in iOS.

3 of 8

TUTORIALS PHONEGAP Q&A

Try: -webkit-touch-callout:none;

Now that I have a PhoneGap app build for iOS, how can I send it to my client for testing? In Android, I just have to send him the APK file, how about in iOS ?

You need to sign up for the Apple Developer Program. Then you have to create an Apple developer certificate, and an application provisioning profile that includes the UDID of your client devices.

How can I get a link to the recording of this session when its over?

Its available here.

I was told that the Facebook iPhone app was built using PhoneGap can anyone confirm that?

The current Facebook app on iOS is native.

4 of 8

TUTORIALS PHONEGAP Q&A

What is a good library for page transitions and page handling in general if not jQuery Mobile?

Page transitions are really easy to implement with a few lines of CSS. Take a look at Part 13 in the PhoneGap Tutorial. For architectural frameworks, take a look at Backbone.js, Angular.js, Ember.js, and others.

Which is preferable, draw buttons with gradients or just load a PNG file?

This may vary depending on the platform. There doesnt seem to be much of a difference on iOS, but Android (particularly older devices) sometimes struggles with rendering gradients.

How does the App Store review process work? For native iOS apps there is a code review of any changes.

PhoneGap apps are native apps. They have a native shell that happens to render a lot of its content using HTML/JS/CSS. The review process is the same as for other iOS apps. The guidelines are available here. Apps are evaluated based on a range of criteria, including user interface design, functionality, content, and the use of specific technologies. As far as I know and based on my own experience submitting apps, a code review is not part of the process. Also based on my experience, the use of specific technologies means that if your app doesnt make use of any device feature (like GPS, accelerometer, camera, contacts, local storage, device events, etc), Apple may consider that it would be better suited as a traditional web app delivered in
5 of 8

TUTORIALS PHONEGAP Q&A

the browser. PhoneGap obviously gives you access to all the device features, so you have all you need to build an app that complies with the guidelines.

Christophe, can you please create or point us to a good tutorial, that uses the facebook plugin and do some typical things like connecting with facebook, posting something to the timeline? etc

Thats my next blog post :) Click here

What is the proper sequence for loading .js files when using cordova.js and jquery/jquery-mobile?

Here is what Im typically doing:

<body> <!-- HTML markup here --> <script src=phonegap.js></script> <!-- JavaScript libraries here --> <!-- App specific Javascript files here --> </body>

Do I have to create different folders & config.xml for different devices with www/ or can I use the same code for all devices?
6 of 8

TUTORIALS PHONEGAP Q&A

The easiest way to build is to use PhoneGap Build. In that case, you have a single directory structure with a single config.xml, and you dont even have to download the PhoneGap SDK: The right cordova.js for each platform will be injected by PhoneGap build. If you dont want to build in the cloud using PhoneGap Build, I recommend you take a look a the Command Line Tools Interface to create your project structure.

Can I use PhoneGap build if using Cordova?

Yes, since the PhoneGap and Cordova libraries are the same. Just add: <script src=phonegap.js></script> to your index.html page, and the right version of Cordova for each platform will be injected by PhoneGap build.

If I have cordova.js before I send it into PhoneGap will it replace it in PhoneGap or am I running two .js files on PhoneGap build?

In the app you submit to PhoneGap build, you should just have this: <script src=phonegap.js></script>

7 of 8

TUTORIALS PHONEGAP Q&A

and phonegap.js should actually not be present in the root folder. PhoneGap build will inject the right cordova.js for each platform. Let me know if you have other questions.

Christophe Coenraets
Adobe Evangelist

HIS BLOG

SHARE

TWITTER

GITHUB

appliness

NEWS BY BRIAN RINALDI

BOOKMARK / SHARE / TOC

Building Windows Store Applications With jQuery 2.0 by Jonathan Sampson

Easy High DPI Images by Boris Smus

Slide In (as you scroll down) Boxes by Chris Coyier

CSS3 transitions and z-index by Zoe


Gillenwater

Make a 3D iPhone with CSS by Donovan Hutchinson

shapeoutside is in CSS exclusions by Bem Jones-Bey

Brackets Quick Open: Thats No Regex! by Kevin Dangoor Deploying JavaScript Applications by Alex Sexton Getting started with AngularJS by
Kris Schultz

Google Analytics and PhoneGap by Raymond Camden

appliness

MORE NEWS ON HTTP://REMOTESYNTHESIS.COM/

appliness

EOF FOLLOW US

BOOKMARK / SHARE / TOC

Now what?
N
SUBSCRIBE TO OUR MONTHLY NEWSLETTER

FOLLOW US ON TWITTER

JOIN US ON FACEBOOK

visit appliness.com

Vous aimerez peut-être aussi