rowid,title,contents,year,author,author_slug,published,url,topic
110,Shiny Happy Buttons,"Since Mac OS X burst onto our screens, glossy, glassy, shiny buttons have been almost de rigeur, and have essentially, along with reflections and rounded corners, become a cliché of Web 2.0 “design”. But if you can’t beat ‘em you’d better join ‘em. So, in this little contribution to our advent calendar, we’re going to take a plain old boring HTML button, and 2.0 it up the wazoo.
But, here’s the catch. We’ll use no images, either in our HTML or our CSS. No sliding doors, no image replacement techniques. Just straight up, CSS, CSS3 and a bit of experimental CSS. And, it will be compatible with pretty much any browser (though with some progressive enhancement for those who keep up with the latest browsers).
The HTML
We’ll start with our HTML.
This is a shiny button
OK, so it’s not shiny yet – but boy will it ever be.
Before styling, that’s going to look like this.
Ironically, depending on the operating system and browser you are using, it may well be a shiny button already, but that’s not the point. We want to make it shiny 2.0. Our mission is to make it look something like this
If you want to follow along at home keep in mind that depending on which browser you are using you may see fewer of the CSS effects we’ve added to create the button. As of writing, only in Safari are all the effects we’ll apply supported.
Taking a look at our finished product, here’s what we’ve done to it:
We’ve given the button some padding and a width.
We’ve changed the text color, and given the text a drop shadow.
We’ve given the button a border.
We’ve given the button some rounded corners.
We’ve given the button a drop shadow.
We’ve given the button a gradient background.
and remember, all without using any images.
Styling the button
So, let’s get to work.
First, we’ll add given the element some padding and a width:
button {
padding: .5em;
width: 15em;
}
Next, we’ll add the text color, and the drop shadow:
color: #ffffff;
text-shadow: 1px 1px 1px #000;
A note on text-shadow
If you’ve not seen text-shadows before well, here’s the quick back-story. Text shadow was introduced in CSS2, but only supported in Safari (version 1!) some years later. It was removed from CSS2.1, but returned in CSS3 (in the text module). It’s now supported in Safari, Opera and Firefox (3.1). Internet Explorer has a shadow filter, but the syntax is completely different.
So, how do text-shadows work? The three length values specify respectively a horizontal offset, a vertical offset and a blur (the greater the number the more blurred the shadow will be), and finally a color value for the shadow.
Rounding the corners
Now we’ll add a border, and round the corners of the element:
border: solid thin #882d13;
-webkit-border-radius: .7em;
-moz-border-radius: .7em;
border-radius: .7em;
Here, we’ve used the same property in three slightly different forms. We add the browser specific prefix for Webkit and Mozilla browsers, because right now, both of these browsers only support border radius as an experimental property. We also add the standard property name, for browsers that do support the property fully in the future.
The benefit of the browser specific prefix is that if a browser only partly supports a given property, we can easily avoid using the property with that browser simply by not adding the browser specific prefix. At present, as you might guess, border-radius is supported in Safari and Firefox, but in each the relevant prefix is required.
border-radius takes a length value, such as pixels. (It can also take two length values, but that’s for another Christmas.) In this case, as with padding, I’ve used ems, which means that as the user scales the size of text up and down, the radius will scale as well. You can test the difference by making the radius have a value of say 5px, and then zooming up and down the text size.
We’re well and truly on the way now. All we need to do is add a shadow to the button, and then a gradient background.
In CSS3 there’s the box-shadow property, currently only supported in Safari 3. It’s very similar to text-shadow – you specify a horizontal and vertical offset, a blur value and a color.
-webkit-box-shadow: 2px 2px 3px #999;
box-shadow: 2px 2px 2px #bbb;
Once more, we require the “experimental” -webkit- prefix, as Safari’s support for this property is still considered by its developers to be less than perfect.
Gradient Background
So, all we have left now is to add our shiny gradient effect. Now of course, people have been doing this kind of thing with images for a long time. But if we can avoid them all the better. Smaller pages, faster downloads, and more scalable designs that adapt better to the user’s font size preference. But how can we add a gradient background without an image?
Here we’ll look at the only property that is not as yet part of the CSS standard – Apple’s gradient function for use anywhere you can use images with CSS (in this case backgrounds). In essence, this takes SVG gradients, and makes them available via CSS syntax.
Here’s what the property and its value looks like:
background-image: -webkit-gradient(linear, left top, left bottom, from(#e9ede8), to(#ce401c),color-stop(0.4, #8c1b0b));
Zooming in on the gradient function, it has this basic form:
-webkit-gradient(type, point, point, from(color), to(color),color-stop(where, color));
Which might look complicated, but is less so than at first glance.
The name of the function is gradient (and in this case, because it is an experimental property, we use the -webkit- prefix).
You might not have seen CSS functions before, but there are others, including the attr() function, used with generated content. A function returns a value that can be used as a property value – here we are using it as a background image.
Next we specify the type of the gradient. Here we have a linear gradient, and there are also radial gradients.
After that, we specify the start and end points of the gradient – in our case the top and bottom of the element, in a vertical line.
We then specify the start and end colors – and finally one stop color, located at 40% of the way down the element. Together, this creates a gradient that smoothly transitions from the start color in the top, vertically to the stop color, then smoothly transitions to the end color.
There’s one last thing. What color will the background of our button be if the browser doesn’t support gradients? It will be white (or possibly some default color for buttons). Which may make the text difficult or impossible to read. So, we’ll add a background color as well (see why the validator is always warning you when a color but not a background color is specified for an element?).
If we put it all together, here’s what we have:
button {
width: 15em;
padding: .5em;
color: #ffffff;
text-shadow: 1px 1px 1px #000;
border: solid thin #882d13;
-webkit-border-radius: .7em;
-moz-border-radius: .7em;
border-radius: .7em;
-webkit-box-shadow: 2px 2px 3px #999;
box-shadow: 2px 2px 2px #bbb;
background-color: #ce401c;
background-image: -webkit-gradient(linear, left top, left bottom, from(#e9ede8), to(#ce401c),color-stop(0.4, #8c1b0b));
}
Which looks like this in various browsers:
In Safari (3)
In Firefox 3.1 (3.0 supports border-radius but not text-shadow)
In Opera 10
and of course in Internet Explorer (version 8 shown here)
But it looks different in different browsers
Yes, it does look different in different browsers, but we all know the answer to the question “do web sites need to look the same in every browser?“.
Even if you really think sites should look the same in every browser, hopefully this little tutorial has whet your appetite for what CSS3 and experimental CSS that’s already supported in widely used browsers (and we haven’t even touched on animations and similar effects!).
I hope you’ve enjoyed out little CSSMas present, and look forward to seeing your shiny buttons everywhere on the web.
Oh, and there’s just a bit of homework – your job is to use the :hover selector, and make a gradient in the hover state.",2008,John Allsopp,johnallsopp,2008-12-18T00:00:00+00:00,https://24ways.org/2008/shiny-happy-buttons/,code
177,"HTML5: Tool of Satan, or Yule of Santa?","It would lead to unseasonal arguments to discuss the title of this piece here, and the arguments are as indigestible as the fourth turkey curry of the season, so we’ll restrict our article to the practical rather than the philosophical: what HTML5 can you reasonably expect to be able to use reliably cross-browser in the early months of 2010?
The answer is that you can use more than you might think, due to the seasonal tinsel of feature-detection and using the sparkly pixie-dust of IE-only VML (but used in a way that won’t damage your Elf).
Canvas
canvas is a 2D drawing API that defines a blank area of the screen of arbitrary size, and allows you to draw on it using JavaScript. The pictures can be animated, such as in this canvas mashup of Wolfenstein 3D and Flickr. (The difference between canvas and SVG is that SVG uses vector graphics, so is infinitely scalable. It also keeps a DOM, whereas canvas is just pixels so you have to do all your own book-keeping yourself in JavaScript if you want to know where aliens are on screen, or do collision detection.)
Previously, you needed to do this using Adobe Flash or Java applets, requiring plugins and potentially compromising keyboard accessibility. Canvas drawing is supported now in Opera, Safari, Chrome and Firefox. The reindeer in the corner is, of course, Internet Explorer, which currently has zero support for canvas (or SVG, come to that).
Now, don’t pull a face like all you’ve found in your Yuletide stocking is a mouldy satsuma and a couple of nuts—that’s not the end of the story. Canvas was originally an Apple proprietary technology, and Internet Explorer had a similar one called Vector Markup Language which was submitted to the W3C for standardisation in 1998 but which, unlike canvas, was not blessed with retrospective standardisation.
What you need, then, is some way for Internet Explorer to translate canvas to VML on-the-fly, while leaving the other, more standards-compliant browsers to use the HTML5. And such a way exists—it’s a JavaScript library called excanvas. It’s downloadable from http://code.google.com/p/explorercanvas/ and it’s simple to include it via a conditional comment in the head for IE:
Simply include this, and your canvas will be natively supported in the modern browsers (and the library won’t even be downloaded) whereas IE will suddenly render your canvas using its own VML engine. Be sure, however, to check it carefully, as the IE JavaScript engine isn’t so fast and you’ll need to be sure that performance isn’t too degraded to use.
Forms
Since the beginning of the Web, developers have been coding forms, and then writing JavaScript to check whether an input is a correctly formed email address, URL, credit card number or conforms to some other pattern. The cumulative labour of the world’s developers over the last 15 years makes whizzing round in a sleigh and delivering presents seem like popping to the corner shop in comparison.
With HTML5, that’s all about to change. As Yaili began to explore on Day 3, a host of new attributes to the input element provide built-in validation for email address formats (input type=email), URLs (input type=url), any pattern that can be expressed with a JavaScript-syntax regex (pattern=""[0-9][A-Z]{3}"") and the like. New attributes such as required, autofocus, input type=number min=3 max=50 remove much of the tedious JavaScript from form validation.
Other, really exciting input types are available (see all input types). The datalist is reminiscent of a select box, but allows the user to enter their own text if they don’t want to choose one of the pre-defined options. input type=range is rendered as a slider, while input type=date pops up a date picker, all natively in the browser with no JavaScript required at all.
Currently, support is most complete in an experimental implementation in Opera and a number of the new attributes in Webkit-based browsers. But don’t let that stop you! The clever thing about the specification of the new Web Forms is that all the new input types are attributes (rather than elements). input defaults to input type=text, so if a browser doesn’t understand a new HTML5 type, it gracefully degrades to a plain text input.
So where does that leave validation in those browsers that don’t support Web Forms? The answer is that you don’t retire your pre-existing JavaScript validation just yet, but you leave it as a fallback after doing some feature detection. To detect whether (say) input type=email is supported, you make a new input type=email with JavaScript but don’t add it to the page. Then, you interrogate your new element to find out what its type attribute is. If it’s reported back as “email”, then the browser supports the new feature, so let it do its work and don’t bring in any JavaScript validation. If it’s reported back as “text”, it’s fallen back to the default, indicating that it’s not supported, so your code should branch to your old validation routines. Alternatively, use the small (7K) Modernizr library which will do this work for you and give you JavaScript booleans like Modernizr.inputtypes[email] set to true or false.
So what does this buy you? Well, first and foremost, you’re future-proofing your code for that time when all browsers support these hugely useful additions to forms. Secondly, you buy a usability and accessibility win. Although it’s tempting to style the stuffing out of your form fields (which can, incidentally, lead to madness), whatever your branding people say, it’s better to leave forms as close to the browser defaults as possible. A browser’s slider and date pickers will be the same across different sites, making it much more comprehensible to users. And, by using native controls rather than faking sliders and date pickers with JavaScript, your forms are much more likely to be accessible to users of assistive technology.
HTML5 DOCTYPE
You can use the new DOCTYPE !doctype html now and – hey presto – you’re writing HTML5, as it’s pretty much a superset of HTML4. There are some useful advantages to doing this. The first is that the HTML5 validator (I use http://html5.validator.nu) also validates ARIA information, whereas the HTML4 validator doesn’t, as ARIA is a new spec developed after HTML4. (Actually, it’s more accurate to say that it doesn’t validate your ARIA attributes, but it doesn’t automatically report them as an error.)
Another advantage is that HTML5 allows tabindex as a global attribute (that is, on any element). Although originally designed as an accessibility bolt-on, I ordinarily advise you don’t use it; a well-structured page should provide a logical tab order through links and form fields already.
However, tabindex=""-1"" is a legal value in HTML5 as it allows for the element to be programmatically focussable by JavaScript. It’s also very useful for correcting a bug in Internet Explorer when used with a keyboard; in-page links go nowhere if the destination doesn’t have a proprietary property called hasLayout set or a tabindex of -1.
So, whether it is the tool of Satan or yule of Santa, HTML5 is just around the corner. Some you can use now, and by the end of 2010 I predict you’ll be able to use a whole lot more as new browser versions are released.",2009,Bruce Lawson,brucelawson,2009-12-05T00:00:00+00:00,https://24ways.org/2009/html5-tool-of-satan-or-yule-of-santa/,code
235,"Real Animation Using JavaScript, CSS3, and HTML5 Video","When I was in school to be a 3-D animator, I read a book called Timing for Animation. Though only 152 pages long, it’s essentially the bible for anyone looking to be a great animator. In fact, Pixar chief creative officer John Lasseter used the first edition as a reference when he was an animator at Walt Disney Studios in the early 1980s.
In the book, authors John Halas and Harold Whitaker advise:
Timing is the part of animation which gives meaning to movement. Movement can easily be achieved by drawing the same thing in two different positions and inserting a number of other drawings between the two. The result on the screen will be movement; but it will not be animation.
But that’s exactly what we’re doing with CSS3 and JavaScript: we’re moving elements, not animating them. We’re constantly specifying beginning and end states and allowing the technology to interpolate between the two. And yet, it’s the nuances within those middle frames that create the sense of life we’re looking for.
As bandwidth increases and browser rendering grows more consistent, we can create interactions in different ways than we’ve been able to before. We’re encountering motion more and more on sites we’d generally label ‘static.’ However, this motion is mostly just movement, not animation. It’s the manipulation of an element’s properties, most commonly width, height, x- and y-coordinates, and opacity.
So how do we create real animation?
The metaphor
In my experience, animation is most believable when it simulates, exaggerates, or defies the real world. A bowling ball falls differently than a racquetball. They each have different weights and sizes, which affect the way they land, bounce, and impact other objects.
This is a major reason that JavaScript animation frequently feels mechanical; it doesn’t complete a metaphor. Expanding and collapsing a
feels very different than a opening a door or unfolding a piece of paper, but it often shouldn’t. The interaction itself should tie directly to the art direction of a page.
Physics
Understanding the physics of a situation is key to creating convincing animation, even if your animation seeks to defy conventional physics. Isaac Newton’s first law of motion’s_laws_of_motion states, “Every body remains in a state of rest or uniform motion (constant velocity) unless it is acted upon by an external unbalanced force.” Once a force acts upon an object, the object’s shape can change accordingly, depending on the strength of the force and the mass of the object. Another nugget of wisdom from Halas and Whitaker:
All objects in nature have their own weight, construction, and degree of flexibility, and therefore each behaves in its own individual way when a force acts upon it. This behavior, a combination of position and timing, is the basis of animation. The basic question which an animator is continually asking himself is this: “What will happen to this object when a force acts upon it?” And the success of his animation largely depends on how well he answers this question.
In animating with CSS3 and JavaScript, keep physics in mind. How ‘heavy’ is the element you’re interacting with? What kind of force created the action? A gentle nudge? A forceful shove? These subtleties will add a sense of realism to your animations and make them much more believable to your users.
Misdirection
Magicians often use misdirection to get their audience to focus on one thing rather than another. They fool us into thinking something happened that actually didn’t.
Animation is the same, especially on a screen. By changing the arrangement of pixels on screen at a fast enough rate, your eyes fool your mind into thinking an object is actually in motion.
Another important component of misdirecting in animation is the use of multiple objects. Try to recall a cartoon where a character vanishes. More often, the character makes some sort of exaggerated motion (this is called anticipation) then disappears, and a puff a smoke follows. That smoke is an extra element, but it goes a long way into make you believe that character actually disappeared.
Very rarely does a vanishing character’s opacity simply go from one hundred per cent to zero. That’s not believable. So why do we do it with
s?
Armed with the ammunition of metaphors and misdirection, let’s code an example.
Shake, rattle, and roll
(These demos require at least a basic understanding of jQuery and CSS3. Run away if your’re afraid, or brush up on CSS animation and resources for learning jQuery. Also, these demos use WebKit-specific features and are best viewed in the latest version of Safari, so performance in other browsers may vary.)
We often see the design pattern of clicking a link to reveal content. Our “first demo”:”/examples/2010/real-animation/demo1/ shows us exactly that. It uses jQuery’s “ slideDown()”:http://api.jquery.com/slideDown/ method, as many instances do.
But what force acted on the
that caused it to open? Did pressing the button unlatch some imaginary hook? Did it activate an unlocking sequence with some gears?
Take 2
Our second demo is more explicit about what happens: the button fell on the
and shook its content loose. Here’s how it’s done.
function clickHandler(){
$('#button').addClass('animate');
return false;
}
Clicking the link adds a class of animate to our button. That class has the following CSS associated with it:
In our keyframe definition, we’ve specified from and to states. This is great, because we can be explicit about how an object starts and finishes moving.
What’s also extra handy is that these CSS keyframes broadcast events that you can react to with JavaScript. In this example, we’re listening to the webkitAnimationEnd event and opening the
only when the sequence is complete. Here’s that code.
function attachAnimationEventHandlers(){
var wrap = document.getElementById('wrap');
wrap.addEventListener('webkitAnimationEnd', function($e) {
switch($e.animationName){
case ""ANIMATE"" :
openMain();
break;
default:
}
}, false);
}
function openMain(){
$('#main .inner').slideDown('slow');
}
(For more info on handling animation events, check out the documentation at the Safari Reference Library.)
Take 3
The problem with the previous demo is that the subtleties of timing aren’t evident. It still feels a bit choppy.
For our third demo, we’ll use percentages instead of keywords so that we can insert as many points as we need to communicate more realistic timing. The percentages allow us to add the keys to well-timed animation: anticipation, hold, release, and reaction.
Take 4
The button animation is starting to feel much better, but the reaction of the
opening seems a bit slow.
This fourth demo uses jQuery’s delay() method to time the opening precisely when we want it. Since we know the button’s animation is one second long and its reaction starts at eighty per cent of that, that puts our delay at 800ms (eighty per cent of one second). However, here’s a little pro tip: let’s start the opening at 750ms instead. The extra fifty milliseconds makes it feel more like the opening is a reaction to the exact hit of the button. Instead of listening for the webkitAnimationEnd event, we can start the opening as soon as the button is clicked, and the movement plays on the specified delay.
function clickHandler(){
$('#button').addClass('animate');
openMain();
return false;
}
function openMain(){
$('#main .inner').delay(750).slideDown('slow');
}
Take 5
We can tweak the timing of that previous animation forever, but that’s probably as close as we’re going to get to realistic animation with CSS and JavaScript. However, for some extra sauce, we could relegate the whole animation in our final demo to a video sequence which includes more nuances and extra elements for misdirection.
Here’s the basis of video replacement. Add a
element to the page and adjust its opacity to zero. Once the button is clicked, fade the button out and start playing the video. Once the video is finished playing, fade it out and bring the button back.
function clickHandler(){
if($('#main .inner').is(':hidden')){
$('#button').fadeTo(100, 0);
$('#clickVideo').fadeTo(100, 1, function(){
var clickVideo = document.getElementById('clickVideo');
clickVideo.play();
setTimeout(removeVideo, 2400);
openMain();
});
}
return false;
}
function removeVideo(){
$('#button').fadeTo(500, 1);
$('#clickVideo').fadeOut('slow');
}
function openMain(){
$('#main .inner').delay(1100).slideDown('slow');
}
Wrapping up
I’m no JavaScript expert by any stretch. I’m sure a lot of you scripting wizards out there could write much cleaner and more efficient code, but I hope this gives you an idea of the theory behind more realistic motion with the technology we’re using most. This is just one model of creating more convincing animation, but you can create countless variations of this, including…
Exporting animations in 3-D animation tools or 2-D animation tools like Flash or After Effects
Using or SVG instead of
Employing specific JavaScript animation frameworks
Making use of all the powerful properties of CSS Transforms and CSS Animation
Trying out emerging CSS3 animation tools like Sencha Animator
If it wasn’t already apparent, these demos show an exaggerated example and probably aren’t practical in a lot of environments. However, there are a handful of great sites out there that honor animation techniques—metaphor, physics, and misdirection, among others—like Benjamin De Cock’s vCard, 20 Things I Learned About Browsers and the Web by Fantasy Interactive, and the Nike Snowboarding site by Ian Coyle and HEGA. They’re wonderful testaments to what you can do to aid interaction for users.
My goal was to show you the ‘why’ and the ‘how.’ Your charge is to discern the ‘where’ and the ‘when.’ Happy animating!",2010,Dan Mall,danmall,2010-12-15T00:00:00+00:00,https://24ways.org/2010/real-animation-using-javascript-css3-and-html5-video/,code
288,Displaying Icons with Fonts and Data- Attributes,"Traditionally, bitmap formats such as PNG have been the standard way of delivering iconography on websites. They’re quick and easy, and it also ensures they’re as pixel crisp as possible. Bitmaps have two drawbacks, however: multiple HTTP requests, affecting the page’s loading performance; and a lack of scalability, noticeable when the page is zoomed or viewed on a screen with a high pixel density, such as the iPhone 4 and 4S.
The requests problem is normally solved by using CSS sprites, combining the icon set into one (physically) large image file and showing the relevant portion via background-position. While this works well, it can get a bit fiddly to specify all the positions. In particular, scalability is still an issue. A vector-based format such as SVG sounds ideal to solve this, but browser support is still patchy.
The rise and adoption of web fonts have given us another alternative. By their very nature, they’re not only scalable, but resolution-independent too. No need to specify higher resolution graphics for high resolution screens!
That’s not all though:
Browser support: Unlike a lot of new shiny techniques, they have been supported by Internet Explorer since version 4, and, of course, by all modern browsers. We do need several different formats, however!
Design on the fly: The font contains the basic graphic, which can then be coloured easily with CSS – changing colours for themes or :hover and :focus styles is done with one line of CSS, rather than requiring a new graphic. You can also use CSS3 properties such as text-shadow to add further effects. Using -webkit-background-clip: text;, it’s possible to use gradient and inset shadow effects, although this creates a bitmap mask which spoils the scalability.
Small file size: specially designed icon fonts, such as Drew Wilson’s Pictos font, can be as little as 12Kb for the .woff font. This is because they contain fewer characters than a fully fledged font. You can see Pictos being used in the wild on sites like Garrett Murray’s Maniacal Rage.
As with all formats though, it’s not without its disadvantages:
Icons can only be rendered in monochrome or with a gradient fill in browsers that are capable of rendering CSS3 gradients. Specific parts of the icon can’t be a different colour.
It’s only appropriate when there is an accompanying text to provide meaning. This can be alleviated by wrapping the text label in a tag (I like to use rather than , due to the fact that it’s smaller and isn’ t being used elsewhere) and then hiding it from view with text-indent:-999em.
Creating an icon font can be a complex and time-consuming process. While font editors can carry out hinting automatically, the best results are achieved manually.
Unless you’re adept at creating your own fonts, you’re restricted to what is available in the font. However, fonts like Pictos will cover the most common needs, and icons are most effective when they’re using familiar conventions.
The main complaint about using fonts for icons is that it can mean adding a meaningless character to our markup. The good news is that we can overcome this by using one of two methods – CSS generated content or the data-icon attribute – in combination with the :before and :after pseudo-selectors, to keep our markup minimal and meaningful.
Our simple markup looks like this:
View Basket
Note the multiple class attributes. Next, we’ll import the Pictos font using the @font-face web fonts property in CSS:
@font-face {
font-family: 'Pictos';
src: url('pictos-web.eot');
src: local('☺'),
url('pictos-web.woff') format('woff'),
url('pictos-web.ttf') format('truetype'),
url('pictos-web.svg#webfontIyfZbseF') format('svg');
}
This rather complicated looking set of rules is (at the time of writing) the most bulletproof way of ensuring as many browsers as possible load the font we want. We’ll now use the content property applied to the :before pseudo-class selector to generate our icon. Once again, we’ll use those multiple class attribute values to set common icon styles, then specific styles for .basket. This helps us avoid repeating styles:
.icon {
font-family: 'Pictos';
font-size: 22px:
}
.basket:before {
content: ""$"";
}
What does the :before pseudo-class do? It generates the dollar character in a browser, even when it’s not present in the markup. Using the generated content approach means our markup stays simple, but we’ll need a new line of CSS, defining what letter to apply to each class attribute for every icon we add.
data-icon is a new alternative approach that uses the HTML5 data- attribute in combination with CSS attribute selectors. This new attribute lets us add our own metadata to elements, as long as its prefixed by data- and doesn’t contain any uppercase letters. In this case, we want to use it to provide the letter value for the icon. Look closely at this markup and you’ll see the data-icon attribute.
View Basket
We could add others, in fact as many as we like.
Favourites
History
Location
Then, we need just one CSS attribute selector to style all our icons in one go:
.icon:before {
content: attr(data-icon);
/* Insert your fancy colours here */
}
By placing our custom attribute data-icon in the selector in this way, we can enable CSS to read the value of that attribute and display it before the element (in this case, the anchor tag). It saves writing a lot of CSS rules. I can imagine that some may not like the extra attribute, but it does keep it out of the actual content – generated or not.
This could be used for all manner of tasks, including a media player and large simple illustrations. See the demo for live examples. Go ahead and zoom the page, and the icons will be crisp, with the exception of the examples that use -webkit-background-clip: text as mentioned earlier.
Finally, it’s worth pointing out that with both generated content and the data-icon method, the letter will be announced to people using screen readers. For example, with the shopping basket icon above, the reader will say “dollar sign view basket”. As accessibility issues go, it’s not exactly the worst, but could be confusing. You would need to decide whether this method is appropriate for the audience. Despite the disadvantages, icon fonts have huge potential.",2011,Jon Hicks,jonhicks,2011-12-12T00:00:00+00:00,https://24ways.org/2011/displaying-icons-with-fonts-and-data-attributes/,code
283,"CSS3 Patterns, Explained","Many of you have probably seen my CSS3 patterns gallery. It became very popular throughout the year and it showed many web developers how powerful CSS3 gradients really are. But how many really understand how these patterns are created? The biggest benefit of CSS-generated backgrounds is that they can be modified directly within the style sheet. This benefit is void if we are just copying and pasting CSS code we don’t understand. We may as well use a data URI instead.
Important note
In all the examples that follow, I’ll be using gradients without a vendor prefix, for readability and brevity. However, you should keep in mind that in reality you need to use all the vendor prefixes (-moz-, -ms-, -o-, -webkit-) as no browser currently implements them without a prefix. Alternatively, you could use -prefix-free and have the current vendor prefix prepended at runtime, only when needed.
The syntax described here is the one that browsers currently implement. The specification has since changed, but no browser implements the changes yet. If you are interested in what is coming, I suggest you take a look at the dev version of the spec.
If you are not yet familiar with CSS gradients, you can read these excellent tutorials by John Allsopp and return here later, as in the rest of the article I assume you already know the CSS gradient basics:
CSS3 Linear Gradients
CSS3 Radial Gradients
The main idea
I’m sure most of you can imagine the background this code generates:
background: linear-gradient(left, white 20%, #8b0 80%);
It’s a simple gradient from one color to another that looks like this:
See this example live
As you probably know, in this case the first 20% of the container’s width is solid white and the last 20% is solid green. The other 60% is a smooth gradient between these colors. Let’s try moving these color stops closer to each other:
background: linear-gradient(left, white 30%, #8b0 70%);
See this example live
background: linear-gradient(left, white 40%, #8b0 60%);
See this example live
background: linear-gradient(left, white 50%, #8b0 50%);
See this example live
Notice how the gradient keeps shrinking and the solid color areas expanding, until there is no gradient any more in the last example. We can even adjust the position of these two color stops to control where each color abruptly changes into another:
background: linear-gradient(left, white 30%, #8b0 30%);
See this example live
background: linear-gradient(left, white 90%, #8b0 90%);
See this example live
What you need to take away from these examples is that when two color stops are at the same position, there is no gradient, only solid colors. Even without going any further, this trick is useful for a number of different use cases like faux columns or the effect I wanted to achieve in my homepage or the -prefix-free page where the background is only shown on one side and hidden on the other:
Combining with background-size
We can do wonders, however, if we combine this with the CSS3 background-size property:
background: linear-gradient(left, white 50%, #8b0 50%);
background-size: 100px 100px;
See this example live
And there it is. We just created the simplest of patterns: (vertical) stripes. We can remove the first parameter (left) or replace it with top and we’ll get horizontal stripes. However, let’s face it: Horizontal and vertical stripes are kinda boring. Most stripey backgrounds we see on the web are diagonal. So, let’s try doing that.
Our first attempt would be to change the angle of the gradient to something like 45deg. However, this results in an ugly pattern like this:
See this example live
Before reading on, think for a second: why didn’t this produce the desired result? Can you figure it out?
The reason is that the gradient angle rotates the gradient inside each tile, not the tiled background as a whole. However, didn’t we have the same problem the first time we tried to create diagonal stripes with an image? And then we learned that every stripe has to be included twice, like so:
So, let’s try to create that effect with CSS gradients. It’s essentially what we tried before, but with more color stops:
background: linear-gradient(45deg, white 25%,
#8b0 25%, #8b0 50%,
white 50%, white 75%,
#8b0 75%);
background-size:100px 100px;
See this example live
And there we have our stripes! An easy way to remember the order of the percentages and colors it is that you always have two of the same in succession, except the first and last color.
Note: Firefox for Mac also needs an additional 100% color stop at the end of any pattern with more than two stops, like so: ..., white 75%, #8b0 75%, #8b0). The bug was reported in February 2011 and you can vote for it and track its progress at Bugzilla.
Unfortunately, this is essentially a hack and we will realize that if we try to change the gradient angle to 60deg:
See this example live
Not that maintainable after all, eh? Luckily, CSS3 offers us another way of declaring such backgrounds, which not only helps this case but also results in much more concise code:
background: repeating-linear-gradient(60deg, white, white 35px, #8b0 35px, #8b0 70px);
See this example live
In this case, however, the size has to be declared in the color stop positions and not through background-size, since the gradient is supposed to cover the entire container. You might notice that the declared size is different from the one specified the previous way. This is because the size of the stripes is measured differently: in the first example we specify the dimensions of the tile itself; in the second, the width of the stripes (35px), which is measured diagonally.
Multiple backgrounds
Using only one gradient you can create stripes and that’s about it. There are a few more patterns you can create with just one gradient (linear or radial) but they are more or less boring and ugly. Almost every pattern in my gallery contains a number of different backgrounds. For example, let’s create a polka dot pattern:
background: radial-gradient(circle, white 10%, transparent 10%),
radial-gradient(circle, white 10%, black 10%) 50px 50px;
background-size:100px 100px;
See this example live
Notice that the two gradients are almost the same image, but positioned differently to create the polka dot effect. The only difference between them is that the first (topmost) gradient has transparent instead of black. If it didn’t have transparent regions, it would effectively be the same as having a single gradient, as the topmost gradient would obscure everything beneath it.
There is an issue with this background. Can you spot it?
This background will be fine for browsers that support CSS gradients but, for browsers that don’t, it will be transparent as the whole declaration is ignored. We have two ways to provide a fallback, each for different use cases. We have to either declare another background before the gradient, like so:
background: black;
background: radial-gradient(circle, white 10%, transparent 10%),
radial-gradient(circle, white 10%, black 10%) 50px 50px;
background-size:100px 100px;
or declare each background property separately:
background-color: black;
background-image: radial-gradient(circle, white 10%, transparent 10%),
radial-gradient(circle, white 10%, transparent 10%);
background-size:100px 100px;
background-position: 0 0, 50px 50px;
The vigilant among you will have noticed another change we made to our code in the last example: we altered the second gradient to have transparent regions as well. This way background-color serves a dual purpose: it sets both the fallback color and the background color of the polka dot pattern, so that we can change it with just one edit. Always strive to make code that can be modified with the least number of edits. You might think that it will never be changed in that way but, almost always, given enough time, you’ll be proved wrong.
We can apply the exact same technique with linear gradients, in order to create checkerboard patterns out of right triangles:
background-color: white;
background-image: linear-gradient(45deg, black 25%, transparent 25%, transparent 75%, black 75%),
linear-gradient(45deg, black 25%, transparent 25%, transparent 75%, black 75%);
background-size:100px 100px;
background-position: 0 0, 50px 50px;
See this example live
Using the right units
Don’t use pixels for the sizes without any thought. In some cases, ems make much more sense. For example, when you want to make a lined paper background, you want the lines to actually follow the text. If you use pixels, you have to change the size every time you change font-size. If you set the background-size in ems, it will naturally follow the text and you will only have to update it if you change line-height.
Is it possible?
The shapes that can be achieved with only one gradient are:
stripes
right triangles
circles and ellipses
semicircles and other shapes formed from slicing ellipses horizontally or vertically
You can combine several of them to create squares and rectangles (two right triangles put together), rhombi and other parallelograms (four right triangles), curves formed from parts of ellipses, and other shapes.
Just because you can doesn’t mean you should
Technically, anything can be crafted with these techniques. However, not every pattern is suitable for it. The main advantages of this technique are:
no extra HTTP requests
short code
human-readable code (unlike data URIs) that can be changed without even leaving the CSS file.
Complex patterns that require a large number of gradients are probably better left to SVG or bitmap images, since they negate almost every advantage of this technique:
they are not shorter
they are not really comprehensible – changing them requires much more effort than using an image editor
They still save an HTTP request, but so does a data URI.
I have included some very complex patterns in my gallery, because even though I think they shouldn’t be used in production (except under very exceptional conditions), understanding how they work and coding them helps somebody understand the technology in much more depth.
Another rule of thumb is that if your pattern needs shapes to obscure parts of other shapes, like in the star pattern or the yin yang pattern, then you probably shouldn’t use it. In these patterns, changing the background color requires you to also change the color of these shapes, making edits very tedious.
If a certain pattern is not practicable with a reasonable amount of CSS, that doesn’t mean you should resort to bitmap images. SVG is a very good alternative and is supported by all modern browsers.
Browser support
CSS gradients are supported by Firefox 3.6+, Chrome 10+, Safari 5.1+ and Opera 11.60+ (linear gradients since Opera 11.10). Support is also coming in Internet Explorer when IE10 is released. You can get gradients in older WebKit versions (including most mobile browsers) by using the proprietary -webkit-gradient(), if you really need them.
Epilogue
I hope you find these techniques useful for your own designs. If you come up with a pattern that’s very different from the ones already included, especially if it demonstrates a cool new technique, feel free to send a pull request to the github repo of the patterns gallery. Also, I’m always fascinated to see my techniques put in practice, so if you made something cool and used CSS patterns, I’d love to know about it!
Happy holidays!",2011,Lea Verou,leaverou,2011-12-16T00:00:00+00:00,https://24ways.org/2011/css3-patterns-explained/,code
79,Responsive Images: What We Thought We Needed,"If you were to read a web designer’s Christmas wish list, it would likely include a solution for displaying images responsively. For those concerned about users downloading unnecessary image data, or serving images that look blurry on high resolution displays, finding a solution has become a frustrating quest.
Having experimented with complex and sometimes devilish hacks, consensus is forming around defining new standards that could solve this problem. Two approaches have emerged.
The element markup pattern was proposed by Mat Marquis and is now being developed by the Responsive Images Community Group. By providing a means of declaring multiple sources, authors could use media queries to control which version of an image is displayed and under what conditions:
Accessible text
A second proposal put forward by Apple, the srcset attribute, uses a more concise syntax intended for use with the element, although it could be compatible with the element too. This would allow authors to provide a set of images, but with the decision on which to use left to the browser:
Enter Scrooge
Men’s courses will foreshadow certain ends, to which, if persevered in, they must lead.
Ebenezer Scrooge
Given the complexity of this issue, there’s a heated debate about which is the best option. Yet code belies a certain truth. That both feature verbose and opaque syntax, I’m not sure either should find its way into the browser – especially as alternative approaches have yet to be fully explored.
So, as if to dampen the festive cheer, here are five reasons why I believe both proposals are largely redundant.
1. We need better formats, not more markup
As we move away from designs defined with fixed pixel values, bitmap images look increasingly unsuitable. While simple images and iconography can use scalable vector formats like SVG, for detailed photographic imagery, raster formats like GIF, PNG and JPEG remain the only suitable option.
There is scope within current formats to account for varying bandwidth but this requires cooperation from browser vendors. Newer formats like JPEG2000 and WebP generate higher quality images with smaller file sizes, but aren’t widely supported.
While it’s tempting to try to solve this issue by inventing new markup, the crux of it remains at the file level.
Daan Jobsis’s experimentation with image compression strengthens this argument. He discovered that by increasing the dimensions of a JPEG image while simultaneously reducing its quality, a smaller files could be produced, with the resulting image looking just as good on both standard and high-resolution displays.
This may be a hack in lieu of a more permanent solution, but it’s applied in the right place. Easy to accomplish with existing tools and without compatibility issues, it has few downsides. Further experimentation in this area should be encouraged, with standardisation efforts more helpful if focused on developing new image formats or, preferably, extending existing ones.
2. Art direction doesn’t belong in markup
A desired benefit of the markup pattern is to allow for greater art direction. For example, rather than scaling down images on smaller displays to the point that their content is hard to discern, we could present closer crops instead:
This can be achieved with CSS of course, although with a download penalty for those parts of an image not shown. This point may be negligible, however, since in the context of adaptable layouts, these hidden areas may end up being revealed anyway.
Art direction concerns design, not content. If we wish to maintain a separation of concerns, including presentation within our markup seems misguided.
3. The size of a display has little relation to the size of an image
By using media queries, the element allows authors to choose which characteristics of the screen or viewport to query for different images to be displayed.
In developing sites at Clearleft, we have noticed that the viewport is essentially arbitrary, with the size of an image’s containing element more important. For example, look at how this grid of images may adapt at different viewport widths:
As we build more modular systems, components need to be adaptable in and of themselves. There is a case to be made for developing more contextual methods of querying, rather than those based on attributes of the display.
4. We haven’t lived with the problem long enough
A key strength of the web is that the underlying platform can be continually iterated. This can also be problematic if snap judgements are made about what constitutes an improvement.
The early history of the web is littered with such examples, be it the perceived need for blinking text or inline typographic styling. To build a platform for the future, additions to it should be carefully considered. And if we want more consistent support across browsers, burdening vendors with an ever increasing list of features seems counterproductive.
Only once the need for a new feature is sufficiently proven, should we look to standardise it. Before we could declare hover effects, rounded corners and typographic styling in CSS, we used JavaScript as a polyfill. Sure, doing so was painful, but use cases were fully explored, and the CSS specification better reflected the needs of authors.
5. Images and the web aesthetic
The srcset proposal has emerged from a company that markets its phones as being able to browse the real – yet squashed down, tapped and zoomable – web. Perhaps Apple should make its own website responsive before suggesting how the rest of us should do so.
Converserly, while the proposal has the backing of a few respected developers and designers, it was born out of the work Mat Marquis and Filament Group did for the Boston Globe. As the first large-scale responsive design, this was a landmark project that ignited the responsive web design movement and proved its worth. But it was the first.
Its design shares a vernacular to that of contemporary newspaper websites, with a columnar, image-laden and densely packed layout. Compared to more recent examples – Quartz, The Next Web and the New York Times Skimmer – it feels out of step with the future direction of news sites. In seeking out a truer aesthetic for the web in which software interfaces have greater influence, we might discover that the need for responsive images isn’t as great as originally thought.
Building for the future
With responsive design, we’ve accepted the idea that a fully fluid layout, rather than a set of fixed layouts, is best suited to the web’s unpredictable nature. Current responsive image proposals are antithetical to this approach.
We need solutions that lack complexity, are device-agnostic and work within existing workflows. Any proposal that requires different versions of the same image to be created, is likely to have to acquiesce under the pressure of reality.
While it’s easy to get distracted about the size and quality of an image, and how we might choose to serve it, often the simplest solution is not to include it at all. After years of gluttonous design practice, in which fast connections and expansive display sizes were an accepted norm, we have got use to filling pages with needless images and countless items of page furniture.
To design more adaptable experiences, the presence of every element needs to be questioned, for its existence requires additional data to be downloaded or futher complexity within a design system. Conditional loading techniques mean that the inclusion of images is no longer a binary choice, but can instead appear in a progressively enhanced manner.
So here is my proposal. Instead of spending the next year worrying about responsive images, let’s embrace the constraints of the medium, and seek out new solutions that can work within them.",2012,Paul Lloyd,paulrobertlloyd,2012-12-11T00:00:00+00:00,https://24ways.org/2012/responsive-images-what-we-thought-we-needed/,code
96,Unwrapping the Wii U Browser,"The Wii U was released on 18 November 2012 in the US, and 30 November in the UK. It’s the first eighth generation home console, the first mainstream second-screen device, and it has some really impressive browser specs.
Consoles are not just for games now: they’re marketed as complete entertainment solutions. Internet connectivity and browser functionality have gone from a nice-to-have feature in game consoles to a selling point. In Nintendo’s case, they see it as a challenge to design an experience that’s better than browsing on a desktop.
Let’s make a browser that users can use on a daily basis, something that can really handle everything we’ve come to expect from a browser and do it more naturally.
Sasaki – Iwata Asks on Nintendo.com
With 11% of people using console browsers to visit websites, it’s important to consider these devices right from the start of projects. Browsing the web on a TV or handheld console is a very different experience to browsing on a desktop or a mobile phone, and has many usability implications.
Console browser testing
When I’m testing a console browser, one of the first things I do is run Niels Leenheer’s HTML5 test and Lea Verou’s CSS3 test. I use these benchmarks as a rough comparison of the standards each browser supports.
In October, IE9 came out for the Xbox 360, scoring 120/500 in the HTML5 test and 32% in the CSS3 test. The PS Vita also had an update to its browser in recent weeks, jumping from 58/500 to 243/500 in the HTML5 test, and 32% to 55% in the CSS3 test. Manufacturers have been stepping up their game, trying to make their browsing experiences better.
To give you an idea of how the Wii U currently compares to other devices, here are the test results of the other TV consoles I’ve tested. I’ve written more in-depth notes on TV and portable console browsers separately.
Year of releaseHTML5 scoreCSS3 scoreNotes
Wii U2012258/50048%Runs a Netfront browser (WebKit).
Wii200689/500Wouldn’t runRuns an Opera browser.
PS3200668/50038%Runs a Netfront browser (WebKit).
Xbox 3602005120/50032%A browser for the Xbox (IE9) was only recently released in October 2012. The Kinect provides voice and gesture support. There’s also SmartGlass, a second-screen app for platforms including Android and iOS.
The Wii U browser is Nintendo’s fifth attempt at a console browser. Based on these tests, it’s already looking promising.
Why console browsers used to suck
It takes a lot of system memory to run a good browser, and the problem of older consoles is that they don’t have much memory available. The original Nintendo DS needs a memory expansion pack just to run the browser, because the 4MB it has on board isn’t enough. I noticed that even on newer devices, some sites fail to load because the system runs out of memory.
The Wii came out six years ago with an Opera browser. Still being used today and with such low resources available, the latest browser features can’t reasonably be supported. There’s also pressure to add features such as tabs, and enable gamers to use the browser while a game is paused. Nintendo’s browser team have the advantage of higher specs to play with on their new console (1GB of memory dedicated to games, 1GB for the system), which makes it easier to support the latest standards. But it’s still a challenge to fit everything in.
…even though we have more memory, the amount of memory we can use for the browser is limited compared to a PC, so we’ve worked in ways that efficiently allocates the available memory per tab. To work on this, the experience working on the browser for the Nintendo 3DS system under a limited memory constraint helped us greatly.
Sasaki – Iwata Asks on Nintendo.com
In the box
The Wii U consists of a console unit which plugs into a TV (the first to support HD), and a wireless controller known as a gamepad. The gamepad is a lot bigger than typical TV console controllers, and it has a touchscreen on the front. The touchscreen is resistive, responding to pressure rather than electrical current. It’s intended to be used with a stylus (provided) but fingers can be used.
It might look a bit like one, but the gamepad isn’t a portable console designed to be taken out like the PS Vita. The gamepad can be used as a standalone screen with the TV switched off, as long as it’s within range of the console unit – it basically piggybacks off it.
It’s surprisingly lightweight for its size. It has a wealth of detectors including 9-axis control. Sensors wake the device from sleep when it’s picked up. There’s also a camera on the front, and a headphone port and speakers, with audio coming through both the TV and the gamepad giving a surround sound feel.
Up to six tabs can be opened at once, and the browser can be used while games are paused. There’s a really nice little feature here – the current game’s name is saved as a search option, so it’s really quick to look up contextual content such as walk-throughs.
Controls
Only one gamepad can be used to control the browser, but if there are Wiimotes connected, they can be used as pointers. This doesn’t let the user do anything except point (they each get a little hand icon with a number on it displayed on the screen), but it’s interesting that multiple people can be interacting with a site at once.
See a bigger version
The gamepad can also be used as a simple TV remote control, with basic functions such as bringing up the programme guide, adjusting volume and changing channel. I found the simplified interface much more usable than a full-featured remote control.
I’m used to scrolling being sluggish on consoles, but the Wii U feels almost as snappy as a desktop browser. Sites load considerably faster compared with others I’ve tested.
Tilt-scroll
Holding down ZL and ZR while tilting the screen activates an Instapaper-style tilt to scroll for going up and down the page quickly, useful for navigating very long pages.
Second screen
The TV mirrors most of what’s on the gamepad, although the TV screen just displays the contents of the browser window, while the gamepad displays the site along with the browser toolbar.
When the user with the gamepad is typing, the keyboard is hidden from the TV screen – there’s just a bit of text at the top indicating what’s happening on the gamepad.
Pressing X draws an on-screen curtain over the TV, hiding the content that’s on the gamepad from the TV. Pressing X again opens the curtains, revealing what’s on the gamepad. Holding the button down plays a drumroll before it’s released and the curtains are opened. I can imagine this being used in meetings as a fun presentation tool.
In a sense, browsing is a personal activity, but you get the idea that people will be coming and going through the room. When I first saw the curtain function, it made a huge impression on me. I walked around with it all over the company saying, “They’ve really come up with something amazing!”
Iwata – Iwata Asks on Nintendo.com
Text
Writing text
Unlike the capacitive screens on smartphones, the Wii U’s resistive screen needs to be pressed harder than you’re probably used to for registering a touch event. The gamepad screen is big, which makes it much easier to type on this device than other handheld consoles, even without the stylus. It’s still more fiddly than a full-sized keyboard though. When you’re designing forms, consider the extra difficulty console users experience.
Although TV screens are physically big, they are typically viewed from further away than desktop screens. This makes readability an issue, so Nintendo have provided not one, but four ways to zoom in and out:
Double-tapping on the screen.
Tapping the on-screen zoom icons in the browser toolbar.
Pressing the + and - buttons on the device.
Moving the right analogue stick up and down.
As well as making it easy to zoom in and out, Nintendo have done a few other things to improve the reading experience on the TV.
System font
One thing you’ll notice pretty quickly is that the browser lacks all the fonts we’re used to falling back to. Serif fonts are replaced with the system’s sans-serif font. I couldn’t get Typekit’s font loading method to work but Fontdeck, which works slightly differently, does display custom fonts.
The system font has been optimised for reading at a distance and is easy to distinguish because the lowercase e has a quirky little tilt.
Don’t lose :focus
Using the D-pad to navigate is similar to using a keyboard. Individual links are focused on, with a blue outline drawn around them.
The recently redesigned An Event Apart site is an example that improves the experience for keyboard and D-pad users. They’ve added a yellow background colour to links on focus. It feels nicer than the default blue outline on its own.
Media
This year, television overtook PCs as the primary way to watch online video content. TV is the natural environment for video, and 42% of online TVs in the US are connected to the internet via a console. Unfortunately, the tag isn’t supported in most console browsers, and those that have Flash installed often have such an old version that the video won’t play.
I suspect this has been a big driver in getting console browsers to support web standards. The Wii U is designed with video content in mind. It doesn’t support Flash but it does support the HTML5 tag.
Some video formats can’t be played, but those that are supported bring up an optimised interface with a custom scrub bar. This is where the device switches from mirroring the TV to being a second screen. The full-screen video is displayed on the TV, and the interface on the gamepad.
The really clever bit is that while a video is playing, the gamepad user can keep the video playing on the TV screen while searching for another video or browsing the web. This is the same for images too.
On the left, the video is being shown full-screen on the TV and gamepad. Only the gamepad gets the scrub bar. Clicking the slide up/down button (circled) lets the gamepad user browse the web while the video on the TV continues to play full-screen, as shown in the image on the right.
There’s support for SVG images, and they look great on a high-definition TV screen. However, there’s currently no way to save or download files.
Preparing for console users
I wasn’t expecting to be quite as impressed as I am by this browser. It’s encouraging to see console makers investing time into improving the experience as well as the standards support. In the same way there was an explosion in mobile browser use as the experience got better, I’m sure we’ll see the same with console browsers as the experience improves.
The value of detection
Consoles offer a range of inputs including gesture, voice and controller buttons. That means we have to think about more diverse methods of input than just touch and click.
This is where I could tell you to add some detection methods such as user agent string sniffing to target a different experience for console users. But the majority of the time, that really isn’t necessary. TV console browsers are getting a lot better at compensating for the living room environment, and they’re designed to work with websites that haven’t been optimised for this context.
Rather than tighten our grip on optimising experiences for every device out there, we’ve got to be pragmatic. There are so many new devices coming out every week, our designs need to be future-proof rather than fixed to a particular device in time.
Even fuzzy device detection isn’t reliable – the PS Vita declares itself to be mobile, a mobile device and a Kindle Fire tablet, while the two DS devices state they’re neither mobile nor mobile phones nor tablets, but computers. They’re weird outliers, but they’re still important devices to consider.
Thinking broadly about how our designs will be interacted with and viewed on a TV screen can help improve that experience for everyone. This is about accessibility. Considering how someone uses a site with a D-pad, we can improve the experience for keyboard users. When we think about colour contrast and text legibility on TV screens, we can apply that for anyone who reads content on the web. So why just offer this to the TV users?
Playing with the browser
…we want to prove to them through this Wii U Internet Browser that browsing itself can be an entertainment.
Iwata – Iwata Asks on Nintendo.com
Although I’m cautious about designing experiences for specific devices, it’s fun to experiment with the technology available. Nintendo have promised web developers access to the Wii U’s buttons and sensors. There’s already some JavaScript documentation, and a demo for you to try.
If you’re interested in making your own games, thanks to web standards, a lot of HTML5 games work already on the device. Matt Hackett wrote up his experience of testing the game he built, and he talks about some of features the browser lacks. There’s certainly an incentive there for console manufacturers to improve their HTML5 support so more games can be played in their browser.
What excites me about consoles is that it’s like looking at what might be available to us in future browsers. As well as thinking about how our sites work on small screens, we should also consider big screens. We’re already figuring out how images should work at different screen widths and connection speeds, but we’ve also got some interesting challenges ahead of us catering for second screen experiences and 3D-enabled devices.
So, this Christmas, if you’re huddled round the game console or a smart TV, give the browser in it a try.",2012,Anna Debenham,annadebenham,2012-12-22T00:00:00+00:00,https://24ways.org/2012/unwrapping-the-wii-u-browser/,ux
20,Make Your Browser Dance,"It was a crisp winter’s evening when I pulled up alongside the pier. I stepped out of my car and the bitterly cold sea air hit my face. I walked around to the boot, opened it and heaved out a heavy flight case. I slammed the boot shut, locked the car and started walking towards the venue.
This was it. My first gig. I thought about all those weeks of preparation: editing video clips, creating 3-D objects, making coloured patterns, then importing them all into software and configuring effects to change as the music did; targeting frequency, beat, velocity, modifying size, colour, starting point; creating playlists of these… and working out ways to mix them as the music played.
This was it. This was me VJing.
This was all a lifetime (well a decade!) ago.
When I started web designing, VJing took a back seat. I was more interested in interactive layouts, semantic accessible HTML, learning all the IE bugs and mastering the quirks that CSS has to offer. More recently, I have been excited by background gradients, 3-D transforms, the @keyframe directive, as well as new APIs such as getUserMedia, indexedDB, the Web Audio API
But wait, have I just come full circle? Could it be possible, with these wonderful new things in technologies I am already familiar with, that I could VJ again, right here, in a browser?
Well, there’s only one thing to do: let’s try it!
Let’s take to the dance floor
Over the past couple of years working in The Lab I have learned to take a much more iterative approach to projects than before. One of my new favourite methods of working is to create a proof of concept to make sure my theory is feasible, before going on to create a full-blown product. So let’s take the same approach here.
The main VJing functionality I want to recreate is manipulating visuals in relation to sound. So for my POC I need to create a visual, with parameters that can be changed, then get some sound and see if I can analyse that sound to detect some data, which I can then use to manipulate the visual parameters. Easy, right?
So, let’s start at the beginning: creating a simple visual. For this I’m going to create a CSS animation. It’s just a funky i element with the opacity being changed to make it flash.
See the Pen Creating a light by Rumyra (@Rumyra) on CodePen
A note about prefixes: I’ve left them out of the code examples in this post to make them easier to read. Please be aware that you may need them. I find a great resource to find out if you do is caniuse.com. You can also check out all the code for the examples in this article
Start the music
Well, that’s pretty easy so far. Next up: loading in some sound. For this we’ll use the Web Audio API. The Web Audio API is based around the concept of nodes. You have a source node: the sound you are loading in; a destination node: usually the device’s speakers; and any number of processing nodes in between. All this processing that goes on with the audio is sandboxed within the AudioContext.
So, let’s start by initialising our audio context.
var contextClass = window.AudioContext;
if (contextClass) {
//web audio api available.
var audioContext = new contextClass();
} else {
//web audio api unavailable
//warn user to upgrade/change browser
}
Now let’s load our sound file into the new context we created with an XMLHttpRequest.
function loadSound() {
//set audio file url
var audioFileUrl = '/octave.ogg';
//create new request
var request = new XMLHttpRequest();
request.open(""GET"", audioFileUrl, true);
request.responseType = ""arraybuffer"";
request.onload = function() {
//take from http request and decode into buffer
context.decodeAudioData(request.response, function(buffer) {
audioBuffer = buffer;
});
}
request.send();
}
Phew! Now we’ve loaded in some sound! There are plenty of things we can do with the Web Audio API: increase volume; add filters; spatialisation. If you want to dig deeper, the O’Reilly Web Audio API book by Boris Smus is available to read online free.
All we really want to do for this proof of concept, however, is analyse the sound data. To do this we really need to know what data we have.
Learning the steps
Let’s take a minute to step back and remember our school days and science class. I’m sure if I drew a picture of a sound wave, we would all start nodding our heads.
The sound you hear is caused by pressure differences in the particles in the air. Sound pushes these particles together, causing vibrations. Amplitude is basically strength of pressure. A simple example of change of amplitude is when you increase the volume on your stereo and the output wave increases in size.
This is great when everything is analogue, but the waveform varies continuously and it’s not suitable for digital processing: there’s an infinite set of values. For digital processing, we need discrete numbers.
We have to sample the waveform at set time intervals, and record data such as amplitude and frequency. Luckily for us, just the fact we have a digital sound file means all this hard work is done for us. What we’re doing in the code above is piping that data in the audio context. All we need to do now is access it.
We can do this with the Web Audio API’s analysing functionality. Just pop in an analysing node before we connect the source to its destination node.
function createAnalyser(source) {
//create analyser node
analyser = audioContext.createAnalyser();
//connect to source
source.connect(analyzer);
//pipe to speakers
analyser.connect(audioContext.destination);
}
The data I’m really interested in here is frequency. Later we could look into amplitude or time, but for now I’m going to stick with frequency.
The analyser node gives us frequency data via the getFrequencyByteData method.
Don’t forget to count!
To collect the data from the getFrequencyByteData method, we need to pass in an empty array (a JavaScript typed array is ideal). But how do we know how many items the array will need when we create it?
This is really up to us and how high the resolution of frequencies we want to analyse is. Remember we talked about sampling the waveform; this happens at a certain rate (sample rate) which you can find out via the audio context’s sampleRate attribute. This is good to bear in mind when you’re thinking about your resolution of frequencies.
var sampleRate = audioContext.sampleRate;
Let’s say your file sample rate is 48,000, making the maximum frequency in the file 24,000Hz (thanks to a wonderful theorem from Dr Harry Nyquist, the maximum frequency in the file is always half the sample rate). The analyser array we’re creating will contain frequencies up to this point. This is ideal as the human ear hears the range 0–20,000hz.
So, if we create an array which has 2,400 items, each frequency recorded will be 10Hz apart. However, we are going to create an array which is half the size of the FFT (fast Fourier transform), which in this case is 2,048 which is the default. You can set it via the fftSize property.
//set our FFT size
analyzer.fftSize = 2048;
//create an empty array with 1024 items
var frequencyData = new Uint8Array(1024);
So, with an array of 1,024 items, and a frequency range of 24,000Hz, we know each item is 24,000 ÷ 1,024 = 23.44Hz apart.
The thing is, we also want that array to be updated constantly. We could use the setInterval or setTimeout methods for this; however, I prefer the new and shiny requestAnimationFrame.
function update() {
//constantly getting feedback from data
requestAnimationFrame(update);
analyzer.getByteFrequencyData(frequencyData);
}
Putting it all together
Sweet sticks! Now we have an array of frequencies from the sound we loaded, updating as the sound plays. Now we want that data to trigger our animation from earlier.
We can easily pause and run our CSS animation from JavaScript:
element.style.webkitAnimationPlayState = ""paused"";
element.style.webkitAnimationPlayState = ""running"";
Unfortunately, this may not be ideal as our animation might be a whole heap longer than just a flashing light. We may want to target specific points within that animation to have it stop and start in a visually pleasing way and perhaps not smack bang in the middle.
There is no really easy way to do this at the moment as Zach Saucier explains in this wonderful article. It takes some jiggery pokery with setInterval to try to ascertain how far through the CSS animation you are in percentage terms.
This seems a bit much for our proof of concept, so let’s backtrack a little. We know by the animation we’ve created which CSS properties we want to change. This is pretty easy to do directly with JavaScript.
element.style.opacity = ""1"";
element.style.opacity = ""0.2"";
So let’s start putting it all together. For this example I want to trigger each light as a different frequency plays. For this, I’ll loop through the HTML elements and change the opacity style if the frequency gain goes over a certain threshold.
//get light elements
var lights = document.getElementsByTagName('i');
var totalLights = lights.length;
for (var i=0; i 160){
//start animation on element
lights[i].style.opacity = ""1"";
} else {
lights[i].style.opacity = ""0.2"";
}
}
See all the code in action here. I suggest viewing in a modern browser :)
Awesome! It is true — we can VJ in our browser!
Let’s dance!
So, let’s start to expand this simple example. First, I feel the need to make lots of lights, rather than just a few. Also, maybe we should try a sound file more suited to gigs or clubs.
Check it out!
I don’t know about you, but I’m pretty excited — that’s just a bit of HTML, CSS and JavaScript!
The other thing to think about, of course, is the sound that you would get at a venue. We don’t want to load sound from a file, but rather pick up on what is playing in real time. The easiest way to do this, I’ve found, is to capture what my laptop’s mic is picking up and piping that back into the audio context. We can do this by using getUserMedia.
Let’s include this in this demo. If you make some noise while viewing the demo, the lights will start to flash.
And relax :)
There you have it. Sit back, play some music and enjoy the Winamp like experience in front of you.
So, where do we go from here? I already have a wealth of ideas. We haven’t started with canvas, SVG or the 3-D features of CSS. There are other things we can detect from the audio as well. And yes, OK, it’s questionable whether the browser is the best environment for this. For one, I’m using a whole bunch of nonsensical HTML elements (maybe each animation could be held within a web component in the future). But hey, it’s fun, and it looks cool and sometimes I think it’s OK to just dance.",2013,Ruth John,ruthjohn,2013-12-02T00:00:00+00:00,https://24ways.org/2013/make-your-browser-dance/,code
23,Animating Vectors with SVG,"It is almost 2014 and fifteen years ago the W3C started to develop a web-based scalable vector graphics (SVG) format. As web technologies go, this one is pretty old and well entrenched.
See the Pen yJflC by Drew McLellan (@drewm) on CodePen
Embed not working on your device? Try direct.
Unlike rasterized images, SVG files will stay crisp and sharp at any resolution. With high-DPI phones, tablets and monitors, all those rasterized icons are starting to look a bit old and blocky. There are several options to get simpler, decorative pieces to render smoothly and respond to various device widths, shapes and sizes. Symbol fonts are one option; the other is SVG.
I’m a big fan of SVG. SVG is an XML format, which means it is possible to write by hand or to script. The most common way to create an SVG file is through the use of various drawing applications like Illustrator, Inkscape or Sketch. All of them open and save the SVG format.
But, if SVG is so great, why doesn’t it get more attention?
The simple answer is that for a long time it wasn’t well supported, so no one touched the technology. SVG’s adoption has always been hampered by browser support, but that’s not the case any more. Every modern browser (at least three versions back) supports SVG. Even IE9.
Although the browsers support SVG, it is implemented in many different ways.
SVG in HTML
Some browsers allow you to embed SVG right in the HTML: the element. Treating SVG as a first-class citizen works — sometimes. Another way to embed SVG is via the element; using the src attribute, you can refer to an SVG file. Again, this only works sometimes and leaves you in a tight space if you need to have a fallback for older browsers. The most common solution is to use the element, with the data attribute referencing the SVG file. When a browser does not support this, it falls back to the content inside the . This could be a rasterized fallback . This method gets you the best of both worlds: a nice vector image with an alternative rasterized image for browsers that don’t support SVG. The downside is that you need to manage both formats, and some browsers will download both the SVG and the rasterized version, becoming a performance problem.
Alexey Ten came up with a brilliant little trick that uses inline SVG combined with an SVG element. This has an SVG href pointing to the vector SVG representation and a src attribute to the rasterized version. Older browsers will rewrite the element as and use the rasterized src attribute, but modern browsers will show the vector SVG.
It is a great workaround for most situations. You will have to determine the browsers you want or need to support and consider performance issues to decide which method is best for you.
So it can be used in HTML. Why?
There are two compelling reasons why vector graphics in the form of icons and symbols are going to be important on the web. With higher resolution screens, going from 72dpi to 200, 300, even over 400dpi, your rasterized icons are looking a little too blocky. As we zoom and print, we expect the visuals on the site to also stay smooth and crisp.
The other main reason vector graphics are useful is scaling. As responsive websites become the norm, we need a way to dynamically readjust the heights, widths and styles of various elements. SVG handles this perfectly, since vectors remain smooth when changing size.
SVG files are text-based, so they’re small and can be gzipped nicely. There are also techniques for creating SVG sprites to further squeeze out performance gains. But SVG really shines when you begin to couple it with JavaScript. Since SVG elements are part of the DOM, they can be interacted with just like any other element you are used to.
The folks at Vox Media had an ingenious little trick with their SVG for a Playstation and Xbox One reviews. I’ve used the same technique for the 24 ways example. Vox Media spent a lot of time creating SVG line art of the two consoles, but once in place the artwork scaled and resized beautifully.
They still had another trick up their sleeves. In their example, they knew each console was line art, so they used SVG’s line dash property to simulate the lines being drawn by animating the growth of the line by small percentage increments until the lines were complete.
This is a great example of a situation where the alternatives wouldn’t be as straightforward to implement. Using an animated GIF would create a heavy file since it would need to contain all the frames of the animation at a large size to permit scaling; even then, smooth aliasing would be lost. canvas and plenty of JavaScript would be another alternative, but this is a rasterized format. It would need be redrawn at each scale, which is certainly possible, but smoothness would be lost when zooming or printing.
The HTML, SVG and JavaScript for this example is less than 4KB! Let’s have a quick look at the code:
First, we need to initialize a few variables to set the current frame, the number of frames, how fast the animation will run, and we get each of the paths based on their IDs. With those paths, we set the dash and dash offset.
path[i].style.strokeDasharray = l + ' ' + l;
path[i].style.strokeDashoffset = l;
We start the line as a dash, which effectively makes it blank or invisible.
Next, we move to the draw() function. This is where the magic happens. We want to increment the frame to move us forward in the animation and check it’s not finished. If it continues, we then take a percentage of the distance based on the frame and then set the dash offset to this new percentage. This gives the illusion that the line is being drawn. Then we have an animation callback, which starts the draw process over again.
That’s it! It will work with any SVG element that you can draw.
Libraries to get you started
If you aren’t sure where to start with SVG, there are several libraries out there to help. They also abstract all browser compatibility issues to make your life easier.
Raphaël
Snap.svg
svg.js
You can also get most vector applications to export SVG. This means that you can continue your normal workflows, but instead of flattening the image as a PNG or bringing it over to Photoshop to rasterize, you can keep all your hard work as vectors and reap the benefits of SVG.",2013,Brian Suda,briansuda,2013-12-07T00:00:00+00:00,https://24ways.org/2013/animating-vectors-with-svg/,
18,Grunt for People Who Think Things Like Grunt are Weird and Hard,"Front-end developers are often told to do certain things:
Work in as small chunks of CSS and JavaScript as makes sense to you, then concatenate them together for the production website.
Compress your CSS and minify your JavaScript to make their file sizes as small as possible for your production website.
Optimize your images to reduce their file size without affecting quality.
Use Sass for CSS authoring because of all the useful abstraction it allows.
That’s not a comprehensive list of course, but those are the kind of things we need to do. You might call them tasks.
I bet you’ve heard of Grunt. Well, Grunt is a task runner. Grunt can do all of those things for you. Once you’ve got it set up, which isn’t particularly difficult, those things can happen automatically without you having to think about them again.
But let’s face it: Grunt is one of those fancy newfangled things that all the cool kids seem to be using but at first glance feels strange and intimidating. I hear you. This article is for you.
Let’s nip some misconceptions in the bud right away
Perhaps you’ve heard of Grunt, but haven’t done anything with it. I’m sure that applies to many of you. Maybe one of the following hang-ups applies to you.
I don’t need the things Grunt does
You probably do, actually. Check out that list up top. Those things aren’t nice-to-haves. They are pretty vital parts of website development these days. If you already do all of them, that’s awesome. Perhaps you use a variety of different tools to accomplish them. Grunt can help bring them under one roof, so to speak. If you don’t already do all of them, you probably should and Grunt can help. Then, once you are doing those, you can keep using Grunt to do more for you, which will basically make you better at doing your job.
Grunt runs on Node.js — I don’t know Node
You don’t have to know Node. Just like you don’t have to know Ruby to use Sass. Or PHP to use WordPress. Or C++ to use Microsoft Word.
I have other ways to do the things Grunt could do for me
Are they all organized in one place, configured to run automatically when needed, and shared among every single person working on that project? Unlikely, I’d venture.
Grunt is a command line tool — I’m just a designer
I’m a designer too. I prefer native apps with graphical interfaces when I can get them. But I don’t think that’s going to happen with Grunt1.
The extent to which you need to use the command line is:
Navigate to your project’s directory.
Type grunt and press Return.
After set-up, that is, which again isn’t particularly difficult.
OK. Let’s get Grunt installed
Node is indeed a prerequisite for Grunt. If you don’t have Node installed, don’t worry, it’s very easy. You literally download an installer and run it. Click the big Install button on the Node website.
You install Grunt on a per-project basis. Go to your project’s folder. It needs a file there named package.json at the root level. You can just create one and put it there.
package.json at root
The contents of that file should be this:
{
""name"": ""example-project"",
""version"": ""0.1.0"",
""devDependencies"": {
""grunt"": ""~0.4.1""
}
}
Feel free to change the name of the project and the version, but the devDependencies thing needs to be in there just like that.
This is how Node does dependencies. Node has a package manager called NPM (Node packaged modules) for managing Node dependencies (like a gem for Ruby if you’re familiar with that). You could even think of it a bit like a plug-in for WordPress.
Once that package.json file is in place, go to the terminal and navigate to your folder. Terminal rubes like me do it like this:
Terminal rube changing directories
Then run the command:
npm install
After you’ve run that command, a new folder called node_modules will show up in your project.
Example of node_modules folder
The other files you see there, README.md and LICENSE are there because I’m going to put this project on GitHub and that’s just standard fare there.
The last installation step is to install the Grunt CLI (command line interface). That’s what makes the grunt command in the terminal work. Without it, typing grunt will net you a “Command Not Found”-style error. It is a separate installation for efficiency reasons. Otherwise, if you had ten projects you’d have ten copies of Grunt CLI.
This is a one-liner again. Just run this command in the terminal:
npm install -g grunt-cli
You should close and reopen the terminal as well. That’s a generic good practice to make sure things are working right. Kinda like restarting your computer after you install a new application was in the olden days.
Let’s make Grunt concatenate some files
Perhaps in our project there are three separate JavaScript files:
jquery.js – The library we are using.
carousel.js – A jQuery plug-in we are using.
global.js – Our authored JavaScript file where we configure and call the plug-in.
In production, we would concatenate all those files together for performance reasons (one request is better than three). We need to tell Grunt to do this for us.
But wait. Grunt actually doesn’t do anything all by itself. Remember Grunt is a task runner. The tasks themselves we will need to add. We actually haven’t set up Grunt to do anything yet, so let’s do that.
The official Grunt plug-in for concatenating files is grunt-contrib-concat. You can read about it on GitHub if you want, but all you have to do to use it on your project is to run this command from the terminal (it will henceforth go without saying that you need to run the given commands from your project’s root folder):
npm install grunt-contrib-concat --save-dev
A neat thing about doing it this way: your package.json file will automatically be updated to include this new dependency. Open it up and check it out. You’ll see a new line:
""grunt-contrib-concat"": ""~0.3.0""
Now we’re ready to use it. To use it we need to start configuring Grunt and telling it what to do.
You tell Grunt what to do via a configuration file named Gruntfile.js2
Just like our package.json file, our Gruntfile.js has a very special format that must be just right. I wouldn’t worry about what every word of this means. Just check out the format:
module.exports = function(grunt) {
// 1. All configuration goes here
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
concat: {
// 2. Configuration for concatinating files goes here.
}
});
// 3. Where we tell Grunt we plan to use this plug-in.
grunt.loadNpmTasks('grunt-contrib-concat');
// 4. Where we tell Grunt what to do when we type ""grunt"" into the terminal.
grunt.registerTask('default', ['concat']);
};
Now we need to create that configuration. The documentation can be overwhelming. Let’s focus just on the very simple usage example.
Remember, we have three JavaScript files we’re trying to concatenate. We’ll list file paths to them under src in an array of file paths (as quoted strings) and then we’ll list a destination file as dest. The destination file doesn’t have to exist yet. It will be created when this task runs and squishes all the files together.
Both our jquery.js and carousel.js files are libraries. We most likely won’t be touching them. So, for organization, we’ll keep them in a /js/libs/ folder. Our global.js file is where we write our own code, so that will be right in the /js/ folder. Now let’s tell Grunt to find all those files and squish them together into a single file named production.js, named that way to indicate it is for use on our real live website.
concat: {
dist: {
src: [
'js/libs/*.js', // All JS in the libs folder
'js/global.js' // This specific file
],
dest: 'js/build/production.js',
}
}
Note: throughout this article there will be little chunks of configuration code like above. The intention is to focus in on the important bits, but it can be confusing at first to see how a particular chunk fits into the larger file. If you ever get confused and need more context, refer to the complete file.
With that concat configuration in place, head over to the terminal, run the command:
grunt
and watch it happen! production.js will be created and will be a perfect concatenation of our three files. This was a big aha! moment for me. Feel the power course through your veins. Let’s do more things!
Let’s make Grunt minify that JavaScript
We have so much prep work done now, adding new tasks for Grunt to run is relatively easy. We just need to:
Find a Grunt plug-in to do what we want
Learn the configuration style of that plug-in
Write that configuration to work with our project
The official plug-in for minifying code is grunt-contrib-uglify. Just like we did last time, we just run an NPM command to install it:
npm install grunt-contrib-uglify --save-dev
Then we alter our Gruntfile.js to load the plug-in:
grunt.loadNpmTasks('grunt-contrib-uglify');
Then we configure it:
uglify: {
build: {
src: 'js/build/production.js',
dest: 'js/build/production.min.js'
}
}
Let’s update that default task to also run minification:
grunt.registerTask('default', ['concat', 'uglify']);
Super-similar to the concatenation set-up, right?
Run grunt at the terminal and you’ll get some deliciously minified JavaScript:
Minified JavaScript
That production.min.js file is what we would load up for use in our index.html file.
Let’s make Grunt optimize our images
We’ve got this down pat now. Let’s just go through the motions. The official image minification plug-in for Grunt is grunt-contrib-imagemin. Install it:
npm install grunt-contrib-imagemin --save-dev
Register it in the Gruntfile.js:
grunt.loadNpmTasks('grunt-contrib-imagemin');
Configure it:
imagemin: {
dynamic: {
files: [{
expand: true,
cwd: 'images/',
src: ['**/*.{png,jpg,gif}'],
dest: 'images/build/'
}]
}
}
Make sure it runs:
grunt.registerTask('default', ['concat', 'uglify', 'imagemin']);
Run grunt and watch that gorgeous squishification happen:
Squished images
Gotta love performance increases for nearly zero effort.
Let’s get a little bit smarter and automate
What we’ve done so far is awesome and incredibly useful. But there are a couple of things we can get smarter on and make things easier on ourselves, as well as Grunt:
Run these tasks automatically when they should
Run only the tasks needed at the time
For instance:
Concatenate and minify JavaScript when JavaScript changes
Optimize images when a new image is added or an existing one changes
We can do this by watching files. We can tell Grunt to keep an eye out for changes to specific places and, when changes happen in those places, run specific tasks. Watching happens through the official grunt-contrib-watch plugin.
I’ll let you install it. It is exactly the same process as the last few plug-ins we installed. We configure it by giving watch specific files (or folders, or both) to watch. By watch, I mean monitor for file changes, file deletions or file additions. Then we tell it what tasks we want to run when it detects a change.
We want to run our concatenation and minification when anything in the /js/ folder changes. When it does, we should run the JavaScript-related tasks. And when things happen elsewhere, we should not run the JavaScript-related tasks, because that would be irrelevant. So:
watch: {
scripts: {
files: ['js/*.js'],
tasks: ['concat', 'uglify'],
options: {
spawn: false,
},
}
}
Feels pretty comfortable at this point, hey? The only weird bit there is the spawn thing. And you know what? I don’t even really know what that does. From what I understand from the documentation it is the smart default. That’s real-world development. Just leave it alone if it’s working and if it’s not, learn more.
Note: Isn’t it frustrating when something that looks so easy in a tutorial doesn’t seem to work for you? If you can’t get Grunt to run after making a change, it’s very likely to be a syntax error in your Gruntfile.js. That might look like this in the terminal:
Errors running Grunt
Usually Grunt is pretty good about letting you know what happened, so be sure to read the error message. In this case, a syntax error in the form of a missing comma foiled me. Adding the comma allowed it to run.
Let’s make Grunt do our preprocessing
The last thing on our list from the top of the article is using Sass — yet another task Grunt is well-suited to run for us. But wait? Isn’t Sass technically in Ruby? Indeed it is. There is a version of Sass that will run in Node and thus not add an additional dependency to our project, but it’s not quite up-to-snuff with the main Ruby project. So, we’ll use the official grunt-contrib-sass plug-in which just assumes you have Sass installed on your machine. If you don’t, follow the command line instructions.
What’s neat about Sass is that it can do concatenation and minification all by itself. So for our little project we can just have it compile our main global.scss file:
sass: {
dist: {
options: {
style: 'compressed'
},
files: {
'css/build/global.css': 'css/global.scss'
}
}
}
We wouldn’t want to manually run this task. We already have the watch plug-in installed, so let’s use it! Within the watch configuration, we’ll add another subtask:
css: {
files: ['css/*.scss'],
tasks: ['sass'],
options: {
spawn: false,
}
}
That’ll do it. Now, every time we change any of our Sass files, the CSS will automaticaly be updated.
Let’s take this one step further (it’s absolutely worth it) and add LiveReload. With LiveReload, you won’t have to go back to your browser and refresh the page. Page refreshes happen automatically and in the case of CSS, new styles are injected without a page refresh (handy for heavily state-based websites).
It’s very easy to set up, since the LiveReload ability is built into the watch plug-in. We just need to:
Install the browser plug-in
Add to the top of the watch configuration:
. watch: {
options: {
livereload: true,
},
scripts: {
/* etc */
Restart the browser and click the LiveReload icon to activate it.
Update some Sass and watch it change the page automatically.
Live reloading browser
Yum.
Prefer a video?
If you’re the type that likes to learn by watching, I’ve made a screencast to accompany this article that I’ve published over on CSS-Tricks: First Moments with Grunt
Leveling up
As you might imagine, there is a lot of leveling up you can do with your build process. It surely could be a full time job in some organizations.
Some hardcore devops nerds might scoff at the simplistic setup we have going here. But I’d advise them to slow their roll. Even what we have done so far is tremendously valuable. And don’t forget this is all free and open source, which is amazing.
You might level up by adding more useful tasks:
Running your CSS through Autoprefixer (A+ Would recommend) instead of a preprocessor add-ons.
Writing and running JavaScript unit tests (example: Jasmine).
Build your image sprites and SVG icons automatically (example: Grunticon).
Start a server, so you can link to assets with proper file paths and use services that require a real URL like TypeKit and such, as well as remove the need for other tools that do this, like MAMP.
Check for code problems with HTML-Inspector, CSS Lint, or JS Hint.
Have new CSS be automatically injected into the browser when it ever changes.
Help you commit or push to a version control repository like GitHub.
Add version numbers to your assets (cache busting).
Help you deploy to a staging or production environment (example: DPLOY).
You might level up by simply understanding more about Grunt itself:
Read Grunt Boilerplate by Mark McDonnell.
Read Grunt Tips and Tricks by Nicolas Bevacqua.
Organize your Gruntfile.js by splitting it up into smaller files.
Check out other people’s and projects’ Gruntfile.js.
Learn more about Grunt by digging into its source and learning about its API.
Let’s share
I think some group sharing would be a nice way to wrap this up. If you are installing Grunt for the first time (or remember doing that), be especially mindful of little frustrating things you experience(d) but work(ed) through. Those are the things we should share in the comments here. That way we have this safe place and useful resource for working through those confusing moments without the embarrassment. We’re all in this thing together!
1 Maybe someday someone will make a beautiful Grunt app for your operating system of choice. But I’m not sure that day will come. The configuration of the plug-ins is the important part of using Grunt. Each plug-in is a bit different, depending on what it does. That means a uniquely considered UI for every single plug-in, which is a long shot.
Perhaps a decent middleground is this Grunt DevTools Chrome add-on.
2 Gruntfile.js is often referred to as Gruntfile in documentation and examples. Don’t literally name it Gruntfile — it won’t work.",2013,Chris Coyier,chriscoyier,2013-12-11T00:00:00+00:00,https://24ways.org/2013/grunt-is-not-weird-and-hard/,code
27,Putting Design on the Map,"The web can leave us feeling quite detached from the real world. Every site we make is really just a set of abstract concepts manifested as tools for communication and expression. At any minute, websites can disappear, overwritten by a newfangled version or simply gone. I think this is why so many of us have desires to create a product, write a book, or play with the internet of things. We need to keep in touch with the physical world and to prove (if only to ourselves) that we do make real things.
I could go on and on about preserving the web, the challenges of writing a book, or thoughts about how we can deal with the need to make real things. Instead, I’m going to explore something that gives us a direct relationship between a website and the physical world – maps.
A map does not just chart, it unlocks and formulates meaning; it forms bridges between here and there, between disparate ideas that we did not know were previously connected.
Reif Larsen, The Selected Works of T.S. Spivet
The simplest form of map on a website tends to be used for showing where a place is and often directions on how to get to it. That’s an incredibly powerful tool. So why is it, then, that so many sites just plonk in a default Google Map and leave it as that? You wouldn’t just use dark grey Helvetica on every site, would you? Where’s the personality? Where’s the tailored experience? Where is the design?
Jumping into design
Let’s keep this simple – we all want to be better web folk, not cartographers. We don’t need to go into the history, mathematics or technology of map making (although all of those areas are really interesting to research). For the sake of our sanity, I’m going to gloss over some of the technical areas and focus on the practical concepts.
Tiles
If you’ve ever noticed a map loading in sections, it’s because it uses tiles that are downloaded individually instead of requiring the user to download everything that they might need. These tiles come in many styles and can be used for anything that covers large areas, such as base maps and data. You’ve seen examples of alternative base maps when you use Google Maps as Google provides both satellite imagery and road maps, both of which are forms of base maps. They are used to provide context for the real world, or any other world for that matter. A marker on a blank page is useless.
The tiles are representations of the physical; they do not have to be photographic imagery to provide context. This means you can design the map itself. The easiest way to conceive this is by comparing Google’s road maps with Ordnance Survey road maps. Everything about the two maps is different: the colours, the label fonts and the symbols used. Yet they still provide the exact same context (other maps may provide different context such as terrain contours).
Comparison of Google Maps (top) and the Ordnance Survey (bottom).
Carefully designing the base map tiles is as important as any other part of the website. The most obvious, yet often overlooked, aspect are aesthetics and branding. Maps could fit in with the rest of the site; for example, by matching the colours and line weights, they can enhance the full design rather than inhibiting it. You’re also able to define the exact purpose of the map, so instead of showing everything you could specify which symbols or labels to show and hide.
I’ve not done any real research on the accessibility of base maps but, having looked at some of the available options, I think a focus on the typography of labels and the colour of the various elements is crucial. While you can choose to hide labels, quite often they provide the data required to make sense of the map. Therefore, make sure each zoom level is not too cluttered and shows enough to give context. Also be as careful when choosing the typeface as you are in any other design work. As for colour, you need to pay closer attention to issues like colour-blindness when using colour to convey information. Quite often a spectrum of colour will be used to show data, or to show the topography, so you need to be aware that some people struggle to see colour differences within a spectrum.
A nice example of a customised base map can be found on Michael K Owens’ check-in pages:
One of Michael K Owens’ check-in pages.
As I’ve already mentioned, tiles are not just for base maps: they are also for data. In the screenshot below you can see how Plymouth Marine Laboratory uses tiles to show data with a spectrum of colour.
A map from the Marine Operational Ecology data portal, showing data of adult cod in the North Sea.
Technical
You’re probably wondering how to design the base layers. I will briefly explain the concepts here and give you tools to use at the end of the article. If you’re worried about the time it takes to design the maps, don’t be – you can automate most of it. You don’t need to manually draw each tile for the entire world!
We’ve learned the importance of web standards the hard way, so you’ll be glad (and I won’t have to explain the advantages) of the standard for web mapping from the Open Geospatial Consortium (OGC) called the Web Map Service (WMS). You can use conventional file formats for the imagery but you need a way to query for the particular tiles to show for the area and zoom level, that is what WMS does.
Features
Tiles are great for covering large areas but sometimes you need specific smaller areas. We call these features and they usually consist of polygons, lines or points. Examples include postcode boundaries and routes between places, or even something more dynamic such as borders of nations changing over time.
Showing features on a map presents interesting design challenges. If the colour or shape conveys some kind of data beyond geographical boundaries then it needs to be made obvious. This is actually really hard, without building complicated user interfaces. For example, in the image below, is it obvious that there is a relationship between the colours? Does it need a way of showing what the colours represent?
Choropleth map showing ranked postcode areas, using ViziCities.
Features are represented by means of lines or colors; and the effective use of lines or colors requires more than knowledge of the subject – it requires artistic judgement.
Erwin Josephus Raisz, cartographer (1893–1968)
Where lots of boundaries are small and close together (such as a high street or shopping centre) will it be obvious where the boundaries are and what they represent? When designing maps, the hardest challenge is dealing with how the data is represented and how it is understood by the user.
Technical
As you probably gathered, we use WMS for tiles and another standard called the web feature service (WFS) for specific features. I need to stress that the difference between the two is that WMS is for tiling, whereas WFS is for specific features. Both can use similar file formats but should be used for their particular use cases. You may be wondering why you can’t just use a vector format such as KML, GeoJSON (or even SVG) – and you can – but the issue is the same as for WMS: you need a way to query the data to get the correct area and zoom level.
User interface
There is of course never a correct way to design an interface as there are so many different factors to take into consideration for each individual project. Maps can be used in a variety of ways, to provide simple information about directions or for complex visualisations to explain large amounts of data. I would like to just touch on matters that need to be taken into account when working with maps.
As I mentioned at the beginning, there are so many Google Maps on the web that people seem to think that its UI is the only way you can use a map. To some degree we don’t want to change that, as people know how to use them; but does every map require a zoom slider or base map toggle? In fact, does the user need to zoom at all? The answer to that one is generally yes, zooming does provide more context to where the map is zoomed in on.
In some cases you will need to let users choose what goes on the map (such as data layers or directions), so how do they show and hide the data? Does a simple drop-down box work, or do you need search? Google’s base map toggle is quite nice since it doesn’t offer many options yet provides very different contexts and styling.
It isn’t until we get to this point that we realise just plonking a quick Google map is really quite ridiculous, especially when compared to the amount of effort we make in other areas such as colour, typography or how the CSS is written. Each of these is important but we need to make sure the whole site is designed, and that includes the maps as much as any other content.
Putting it into practice
I could ramble on for ages about what we can do to customise maps to fit a site’s personality and correctly represent the data. I wanted to focus on concepts and standards because tools constantly change and it is never good to just rely on a tool to do the work. That said, there are a large variety of tools that will help you turn these concepts into reality. This is not a comparison; I just want to show you a few of the many options you have for maps on the web.
Google
OK, I’ve been quite critical so far about Google Maps but that is only because there is such a large amount of the default maps across the web. You can style them almost as much as anything else. They may not allow you to use custom WMS layers but Google Maps does have its own version, called styled maps. Using an array of map features (in the sense of roads and lakes and landmarks rather than the kind WFS is used for), you can style the base map with JavaScript. It even lets you toggle visibility, which helps to avoid the issue of too much clutter on the map. As well as lacking WMS, it doesn’t support WFS, but it does support GeoJSON and KML so you can still show the features on the map. You should also check out Google Maps Engine (the new version of My Maps), which provides an interface for creating more advanced maps with a selection of different base maps. A premium version is available, essentially for creating map-based visualisations, and it provides a step up from the main Google Maps offering. A useful feature in some cases is that it gives you access to many datasets.
Leaflet
You have probably seen Leaflet before. It isn’t quite as popular as Google Maps but it is definitely used often and for good reason. Leaflet is a lightweight open source JavaScript library. It is not a service so you don’t have to worry about API throttling and longevity. It gives you two options for tiling, the ability to use WMS, or to directly get the file using variables in the filename such as /{z}/{x}/{y}.png. I would recommend using WMS over dynamic file names because it is a standard, but the ability to use variables in a file name could be useful in some situations. Leaflet has a strong community and a well-documented API.
Mapbox
As a freemium service, Mapbox may not be perfect for every use case but it’s definitely worth looking into. The service offers incredible customisation tools as well as lots of data sources and hosting for the maps. It also provides plenty of libraries for the various platforms, so you don’t have to only use the maps on the web.
Mapbox is a service, though its map design tool is open source. Mapbox Studio is a vector-only version of their previous tool called Tilemill. Earlier I wrote about how typography and colour are as important to maps as they are to the rest of a website; if you thought, “Yes, but how on earth can I design those parts of a map?” then this is the tool for you. It is incredibly easy to use. Essentially each map has a stylesheet.
If you do not want to open a paid-for Mapbox account, then you can export the tiles (as PNG, SVG etc.) to use with other map tools.
OpenLayers
After a long wait, OpenLayers 3 has been released. It is similar to Leaflet in that it is a library not a service, but it has a much broader scope. During the last year I worked on the GIS portal at Plymouth Marine Laboratory (which I used to show the data tiles earlier), it essentially used OpenLayers 2 to create a web-based geographic information system, taking a large amount of data and permitting analysis (such as graphs) without downloading entire datasets and complicated software. OpenLayers 3 has improved greatly on the previous version in both performance and accessibility. It is the ideal tool for complex map-based web apps, though it can be used for the simple use cases too.
OpenStreetMap
I couldn’t write an article about maps on the web without at least mentioning OpenStreetMap. It is the place to go for crowd-sourced data about any location, with complete road maps and a strong API.
ViziCities
The newest project on this list is ViziCities by Robin Hawkes and Peter Smart. It is a open source 3-D visualisation tool, currently in the very early stages of development. The basic example shows 3-D buildings around the world using OpenStreetMap data. Robin has used it to create some incredible demos such as real-time London underground trains, and planes landing at an airport. Edward Greer and I are currently working on using ViziCities to show ideal housing areas based on particular personas. We chose it because the 3-D aspect gives us interesting possibilities for the data we are able to visualise (such as bar charts on the actual map instead of in the UI). Despite not being a completely stable, fully featured system, ViziCities is worth taking a look at for some use cases and is definitely going to go from strength to strength.
So there you have it – a whistle-stop tour of how maps can be customised. Now please stop plonking in maps without thinking about it and design them as you design the rest of your content.",2014,Shane Hudson,shanehudson,2014-12-11T00:00:00+00:00,https://24ways.org/2014/putting-design-on-the-map/,design
42,An Overview of SVG Sprite Creation Techniques,"SVG can be used as an icon system to replace icon fonts. The reasons why SVG makes for a superior icon system are numerous, but we won’t be going over them in this article. If you don’t use SVG icons and are interested in knowing why you may want to use them, I recommend you check out “Inline SVG vs Icon Fonts” by Chris Coyier – it covers the most important aspects of both systems and compares them with each other to help you make a better decision about which system to choose.
Once you’ve made the decision to use SVG instead of icon fonts, you’ll need to think of the best way to optimise the delivery of your icons, and ways to make the creation and use of icons faster.
Just like bitmaps, we can create image sprites with SVG – they don’t look or work exactly alike, but the basic concept is pretty much the same.
There are several ways to create SVG sprites, and this article will give you an overview of three of them. While we’re at it, we’re going to take a look at some of the available tools used to automate sprite creation and fallback for us.
Prerequisites
The content of this article assumes you are familiar with SVG. If you’ve never worked with SVG before, you may want to look at some of the introductory tutorials covering SVG syntax, structure and embedding techniques. I recommend the following:
SVG basics: Using SVG.
Structure: Structuring, Grouping, and Referencing in SVG — The , , and Elements. We’ll mention and quite a bit in this article.
Embedding techniques: Styling and Animating SVGs with CSS. The article covers several topics, but the section linked focuses on embedding techniques.
A compendium of SVG resources compiled by Chris Coyier — contains resources to almost every aspect of SVG you might be interested in.
And if you’re completely new to the concept of spriting, Chris Coyier’s CSS Sprites explains all about them.
Another important SVG feature is the viewBox attribute. For some of the techniques, knowing your way around this attribute is not required, but it’s definitely more useful if you understand – even if just vaguely – how it works. The last technique mentioned in the article requires that you do know the attribute’s syntax and how to use it. To learn all about viewBox, you can refer to my blog post about SVG coordinate systems.
With the prerequisites in place, let’s move on to spriting SVGs!
Before you sprite…
In order to create an SVG sprite with your icons, you’ll of course need to have these icons ready for use.
Some spriting tools require that you place your icons in a folder to which a certain spriting process is to be applied. As such, for all of the upcoming sections we’ll work on the assumption that our SVG icons are placed in a folder named SVG.
Each icon is an individual .svg file.
You’ll need to make sure each icon is well-prepared and optimised for use – make sure you’ve cleaned up the code by running it through one of the optimisation tools or processes available (or doing it manually if it’s not tedious).
After prepping the icon files and placing them in a folder, we’re ready to create our SVG sprite.
HTML inline SVG sprites
Since SVG is XML code, it can be embedded inline in an HTML document as a code island using the element. Chris Coyier wrote about this technique first on CSS-Tricks.
The embedded SVG will serve as a container for our icons and is going to be the actual sprite we’re going to use. So we’ll start by including the SVG in our document.