boogdesign posts

Longer posts on standards based web design, portable web development and Linux, intermingled with some stuff on my other nerd interests.

Rob Crowther, London, UK based Blogger, Web Developer, Web Designer and System Administrator - read my Curriculum Vitae

Buy my book!

Book CoverHello! HTML5 and CSS3 available now

Buy my other book!

Book CoverEarly access to HTML5 in Action available now

Categories: Web Design, Information Architecure, Standards, HTML and CSS, Usability & Accessibility

12/06/13

12:16:00 am Permalink Update: Features for Font Fanatics

Categories: Standards, HTML and CSS

Some time ago I wrote a blog post Firefox 4.0 Features for Font Fanatics. Since that time the spec has evolved and support has arrived in Chrome and IE10 so I thought it was worth an update.
Here's the example CSS rule from the original post:

.example {
    font-feature-settings: "dlig=1,tnum=1,ss01=1";
}

This is what the syntax now looks like:

.example {
    font-feature-settings: "dlig" 1, "tnum" 1, "ss01" 1;
}

As you can see the change is subtle. For practical support you'll need to use vendor prefixes, of course:

.example {
    -moz-font-feature-settings: "dlig" 1, "tnum" 1, "ss01" 1;
    -webkit-font-feature-settings: "dlig" 1, "tnum" 1, "ss01" 1;
    -ms-font-feature-settings: "dlig" 1, "tnum" 1, "ss01" 1;
}

I've updated my examples to use the new syntax:


Tweet this!
Send feedback »PermalinkPermalink

23/05/13

02:09:00 am Permalink OpenTech 2013

Categories: Web Design, Web Develop, Blogging and Internet Culture, Society and Politics

It's been a while since I've written a proper blog post but now that my 'professional' writing obligations are mostly out of the way I've been meaning to return to my amateur ramblings. As I attended OpenTech 2013 at the weekend I thought this was a great opportunity to get back into the swing of things. I've been to a few of these events now and they're always well organised and thought provoking, this year was no exception. Each of the six timetable slots through the day had three rooms with sessions and each of those sessions had 2 or (usually) 3 talks. So obviously I was only able to be in one of those rooms at once and see only about one third of the speakers, but I've assembled all those speakers into my OpenTech 2013 twitter list and in this post I'll give my potted impressions of each talk.

Session 1 (Stream C)

  • Farmification - the joystick factory - Lisa Ma - When everyone is using touchscreen devices, what happens to all the people working in the mouse factories? Lisa has been creating programmes to encourage workers to do part time farming work so that they have something to fall back on when the hard times come. An interesting alternative to 20% time.
  • House on Github - Francis Irving - Francis is recording issues with his house on GitHub, he thinks that in the same way that he put his CV online in 1996 and now everyone's doing it, by 2023 everyone will be doing this too. The serious point of the talk was that to effect change in the behaviour of the general population, to cross the chasm, requires geeks to hack the market, not just the tech.
  • The Constitutional Excerpts Project - James Melton - a project to create semantically indexed and fully searchable database of the world's constitutions, because generally people that are writing constitutions are doing it for the first and only time in their lives and could do with some help.

Session 2 (Stream B)

  • The Children's Republic of Shoreditch - Lucy Macnab - a fascinating project run from the back of a fascinating shop, I urge you to check out the video.
  • Writers Centre Norwich - Chris Gribble - Chris wants 'creative people' and 'technical people' to get together and create fictional works featuring and about technology while still being 'literature'. However it was clear he'd never read any SciFi, which I think set him apart from most of his audience, and when directly asked why he didn't think 'technical people' couldn't also be 'creative people' his answer, even though he denied he thought that, described them as two separate communities who needed to be somehow united.
  • School of Data - Tony Hirst - a project to educate civil society organizations, journalists and citizens in the skills needed to analyse publically available data and 'find the story' through a combination of outreach, training and crowd sourcing.

Session 3 (Stream B)

Graeme Burnett talking about FPGA

  • Unix FPGA - Beyond just Finance - Graeme Burnett - using Field-programmable gate arrays in high speed trading platforms where 80GbE throughput will soon be a common requirement.
  • Raspberry Pi - Rob Bishop - An interesting talk on problems and possibilities from one of the Pi developers. Although four fifths of the audience owned a Pi only one fifth had actually built something with one.

Session 4 (Stream A)

KickBackStarter ushers in the politics of the future

  • Tiny Data - Richard Pope - A number of practical projects for easy data visualization, including the bicycle barometer.
  • Bribing MPs with Crowdsourcing *Satire* (probably) - Terence Eden - definitely the most amusing talk of the day, but inspired some discussion on the serious issue of how the general public can overcome the concentrated buying power of rich people with special interests.
  • The Domain Logic of Direct Action - Stephen Reid - Beautiful Trouble is a book and web toolbox that puts the accumulated wisdom of decades of creative protest into the hands of the next generation of change-makers.

Session 5 (Stream B)

  • Big Data for Real People - Chris Osborne - The 4 rules of data visualization are that data should be:
    • Personalized - relevant to the person viewing the data
    • Accessible - don't set a science exam because, unlike you, most people dislike science (and graphs)
    • Actionable - data is no use if you can't do anything as the result of seeing it
    • Instinctive - recognizes human behaviour and the environment the decision is being made in
    The full version of this talk was recorded for Big Data Week if you're interested.
  • Doing Good With (open) Data - Duncan Ross - As we enter the age of big data what will the legal and moral framework for using that data look like? The major pieces of legislation which govern big data are old (1995 for the EU Data Protection Directive, 1791 for the US Bill of Rights) and cannot hope to keep pace with the speed of change of the Internet. How will society ensure big business uses big data in a moral way when we're not event sure what that morality will be? DataKind UK brings together leading data scientists with high impact social organizations through a comprehensive, collaborative approach that leads to shared insights, greater understanding, and positive action through data in the service of humanity.
  • What do Open Sensor Networks mean for citizen science? - Dan McQuillan - There is so much data available nowadays that statistical methods are often used in place of traditional knowledge gathering, for instance drone strike targets are governed by a data mining algorithm rather than on the ground intelligence. But this huge pool of data can be used for good if we can stimulate people with technical and data mining skills to consider social issues.

Session 6 (Stream A)

  • The STEMettes - Stemettes - Providing events, support and strong role models for women in Science, Technology, Engineering and Maths. Role models are important: hack days delivered by women for women and girls produce better engagement than those delivered by men, similarly recruitment events delivered by a team including female members produce a far higher proportion of female applicants. Also women tend to be motivated by the outcomes rather than the opportunity to simply experiment.
  • FOSSbox - Paula Graham - it is understood that diverse teams produce better solutions, but only 3% of FLOSS contributions are from women. Fossbox actively support women contributing to open source projects.
  • Practical Diversity - Meri Williams - an excellent presentation with practical advice for fostering a more diverse work environment.

Tweet this!
Send feedback »PermalinkPermalink

20/04/11

01:16:00 am Permalink IE10 and the Future of CSS Layout

Categories: Front End Web Development, Standards, HTML and CSS, Blogging and Internet Culture

Last week the first developer preview of IE10 was released. Among several experimental features included were the first Microsoft implementations of CSS3 Flexible Box Layout Module and CSS3 Grid Alignment. These are possibly the most exciting things to be added to CSS since drop shadows...

First up the flexible box layout module, or flexboxes. This has already been implemented in Firefox and WebKit, but that version of flexboxes isn't very intuitive, and the draft has since seen a lot of updates. Interestingly, IE10PR1 implements the same version of the spec as Firefox and WebKit but with one important addition: multi-line flexboxes. For me the multi-line properties are what make flexboxes worthwhile for layout, otherwise nearly everything you might currently want to achieve can be done just as easily (and with better backwards compatibility) with display: table-cell.

This is the sort of thing that multi-line flexboxes are useful for, it's a layout typical of shopping and photo gallery sites:

A multiline flexbox layout at 800 pixels width

Here's what my markup looks like, nothing more complex than a list with sixty items in it:

<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    ...
    <li>59</li>
    <li>60</li>
</ul>

And here's the CSS, the key things to look out for are the display: -ms-box and the -ms-box-lines:

body {
    width: 90%;
    margin: 0 5%;
}
ul {
    display: -ms-box;
    -ms-box-lines: multiple;
    list-style: none;
    width: auto;
    padding: 10px;
    border: 4px dashed #000;
}
li {
    display: block;
    -ms-box-flex: 1;
    padding: 1em;
    margin: 0.5em;
    min-width: 3em;
    border: 4px dashed #000;
}

You may be thinking that's not a hard thing to pull off, so let me show you the same page, in an 800 pixel wide browser above, at 640 and 480 pixels:

A multiline flexbox layout at 640 pixels width

A multiline flexbox layout at 480 pixels width

The number of cells across adjusts to match the width available, but, because these are flexboxes, the width of the elements themselves also adjust so that they always exactly fit the available width. This is unique among our current alternatives:

  • If you were using floats or inline blocks then you'd have to set each element to a fixed width, meaning the container would have to be a fixed width so that the elements could fill it exactly. You'd have to use media queries to assign different fixed widths to the container to change the items per row according to screen resolution.
  • If you were using a layout table or display: table-cell then, although the elements would expand to fit exactly, the number of items per row would be fixed by the markup.

However, nothing is perfect. My multi-line flexbox example has a total of 60 elements, and I picked this number because it is an exact multiple of 2, 3, 4, 5 and 6 (it's the expansion of them if I've got my maths terms right&amp;#58;&amp;#63;&amp;#58;) - meaning that the number of elements will fill the grid whether there's 2, 3, 4, 5 or 6 elements per row. If there's a less perfect number, say 24, then the grid will look a little strange on the last row:

A multiline flexbox layout at 640 pixels width with only 24 elements

I think the box-align property should help with this, but I couldn't make it work in IE10PR1.

So, multi-line flexboxes could be a useful addition to the CSS toolbox when everyone gets round to upgrading to IE10, but, cool as they are, that's not the coolest experimental CSS layout implementation in IE10PR1. There have been a few grid and template based CSS proposals over the years but, apart from an incomplete JavaScript library for CSS Template Layout, none of them have ever been implemented in a major desktop browser. That is until last week, when IE10PR1 implemented Microsoft's own CSS Grid Align proposal from October 2010.

I want you to reflect, now, on all the fun you've had over the last ten years constructing CSS layouts of three equal height columns, with a header and footer, and making them work in IE6. Layouts something like this:

A three column layout with header and footer

Are you remembering all the fun you had? Good, now look at this markup and contemplate how you'd turn it into a three column layout:

<header>Header</header>
<aside class="b">Side bar</aside>
<article>I never am really satisfied...</article>
<aside class="d">Side bar</aside>
<footer>Footer</footer>

Now look at this CSS and start wishing the future would arrive soon:

body {
    width: 90%;
    margin: 0 5%;
    display: -ms-grid;
    -ms-grid-columns: auto minmax(min-content, 1fr) auto;
    -ms-grid-rows: auto minmax(min-content, 1fr) auto;
}
article, aside, header, footer {
    margin: 1em;
    padding: 1em;
    outline: 4px dashed black;
}
header { -ms-grid-column: 1; -ms-grid-row: 1; -ms-grid-column-span: 3; }
aside.b { -ms-grid-column: 1; -ms-grid-row: 2; }
article { -ms-grid-column: 2; -ms-grid-row: 2; }
aside.d { -ms-grid-column: 3; -ms-grid-row: 2; }
footer { -ms-grid-column: 1; -ms-grid-row: 3; -ms-grid-column-span: 3; }

That's it, seven declarations is all you need for that three column layout with CSS Grid Align. For this first example I'm going to step through the key points line by line:

display: -ms-grid;

This is the bit which declares we will use the grid layout manager on the children of this element, in the same way that the flexbox layout manager was declared above with display: -ms-box.

-ms-grid-columns: auto minmax(min-content, 1fr) auto;

This line defines three columns, the first and last will shrink to fit the content - that's the default behaviour, similar to a table. The middle column will be a minimum of min-content, which is basically the same as auto, and a maximum of 1fr which is a 'fraction of available space' - quite similar to a flex unit and, since there's only one fractional column, basically equivalent to all the available space.

-ms-grid-rows: auto minmax(min-content, 1fr) auto;

We'll have three rows to go along with our three columns, I won't go over the individual values again. Now the fun stuff:

header { -ms-grid-column: 1; -ms-grid-row: 1; -ms-grid-column-span: 3; }

Put the header in the first column of the first row, and make it span three columns. That's it. Really, it's that simple. Let's just do one more:

article { -ms-grid-column: 2; -ms-grid-row: 2; }

Put the article in the second column and the second row. And make me some coffee, white, no sugar. Actually there isn't a CSS property for that yet, maybe CSS4...

But it gets more cool than that. In the example above the order of the elements in the markup matched up with the order they were placed into the grid, but it doesn't have to be that way:

A three column layout with header and footer, with elements placed in a different order

This amazing transformation was achieved without any changes in markup, just messing around with CSS:

header { -ms-grid-column: 1; -ms-grid-row: 2; }
aside.b { -ms-grid-column: 2; -ms-grid-row: 2; }
article { -ms-grid-column: 1; -ms-grid-row: 1; -ms-grid-column-span: 3; }
aside.d { -ms-grid-column: 1; -ms-grid-row: 3; -ms-grid-column-span: 3; }
footer { -ms-grid-column: 3; -ms-grid-row: 2; }

In the current draft there's a grid-cell-stacking property which will let you flow multiple elements into a single cell, but in the IE10PR1 implementation things just stack on top of each other:

Multiple elements in cells not working

This is a shame, because the markup is quite straightforward, I won't post all of it because this is already getting quite long (have a look), but here's the nice bit:

article:nth-child(2n+1) { -ms-grid-column: 1; }
article:nth-child(2n) { -ms-grid-column: 2; }

The article elements are assigned to grid cells alternately, unfortunately it doesn't work yet. However you can nest elements set to display: -ms-grid inside each other:

A three column layout with header and footer

Have a look at the source code for that one, it gets pretty hairy, so rather than try and do that sort of thing it's probably best to use some wrapper elements like this:

Grid Align with wrapper elements for cells

Again, view the source code yourself to see how it's put together, but I think these things will be worth re-visiting in a later preview release.

I'm going to finish off with some adaptive layout. Grid Align is a great fit for this because of the complete independence of layout from source order. Here's what I put together based off the previous example at 800 pixel width:

An adaptive Grid Align at 800px width

Now here's the same page at 640 and 480 pixel widths:

An adaptive Grid Align at 640px width

An adaptive Grid Align at 480px width

The markup is, of course, the same in each case:

<header>Header</header>
<div id="sidebar">
    <aside>Side bar 1</aside>
    <aside>Side bar 2</aside>
</div>
<div id="content1">
    <article>Content 1</article>
    <article>Content 3</article>
    <article>Content 5</article>
</div>
<div id="content2">
    <article>Content 2</article>
    <article>Content 4</article>
    <article>Content 6</article>
</div>
<footer>Footer</footer>

By default I've assumed a single column layout:

body {
    width: 90%;
    height: 90%;
    margin: 0 5%;
    display: -ms-grid;
    -ms-grid-rows: auto;
    -ms-grid-columns: 1fr;
}
article, aside, header, footer {
     margin: 1em;
     padding: 1em;
     outline: 4px dashed black;
}
header { -ms-grid-row: 1; }
#sidebar { -ms-grid-row: 3; }
#content1 { -ms-grid-row: 2; }
#content2 { -ms-grid-row: 4; }
footer {  -ms-grid-row: 5; }

Moving on to windows of a minimum width of 600 pixels, move up to two columns:

@media screen and (min-width: 600px) {
    body {
        -ms-grid-columns: auto 1fr;
        -ms-grid-rows: auto 1fr 1fr auto;
    }
    header { -ms-grid-column: 1; -ms-grid-row: 1; -ms-grid-column-span: 2; }
    #sidebar { -ms-grid-column: 1; -ms-grid-row: 2; -ms-grid-rowspan: 2; }
    #content1 { -ms-grid-column: 2; -ms-grid-row: 2; }
    #content2 { -ms-grid-column: 2; -ms-grid-row: 3; }
    footer { -ms-grid-column: 1; -ms-grid-row: 4; -ms-grid-column-span: 2; }
}

This is nothing you haven't seen already, but I'll just point out again how cool it is that you can place the elements wherever you want them. Finally, for windows of greater than 760 pixels width, switch back to the three column layout:

@media screen and (min-width: 760px) {
    body {
        -ms-grid-columns: auto 1fr 1fr;
        -ms-grid-rows: auto 1fr auto;
    }
    header { -ms-grid-column: 1; -ms-grid-row: 1; -ms-grid-column-span: 3; }
    #sidebar { -ms-grid-column: 1; -ms-grid-row: 2; }
    #content1 { -ms-grid-column: 2; -ms-grid-row: 2; }
    #content2 { -ms-grid-column: 3; -ms-grid-row: 2; }
    footer { -ms-grid-column: 1; -ms-grid-row: 3; -ms-grid-column-span: 3; }
}

If you've downloaded the IE10 developer preview have a play round with it yourself, and try not to think about how long you'll have to wait until all this stuff is available in production browsers &amp;#58;&amp;#112;


Tweet this!
Send feedback »PermalinkPermalink

16/12/10

01:58:42 am Permalink Fun with HTML5 Forms

Categories: Front End Web Development, Standards, HTML and CSS

There have been many blog posts describing all the new elements and input types HTML5 provides, check out this 24ways post for a good summary, or you could even read chapter 3 of my book. In this post I'm going to focus instead on the validation API and some related HTML5 features by building a simple game based on entering an email address. The goal is to explore some HTML5 features rather than do everything in the most straightforward way, but there should be some practically useful code snippets.

The form itself is going to be very straightforward:

<form id="game">
    <fieldset>
        <legend>Enter a valid email address before the timer runs down</legend>
        <label for="email">Email</label>
        <input id="email" type="email" autofocus required>
    </fieldset>
    <label for="countdown">You have
        <output id="countdown">10</output>
        seconds.
    </label>
    <label for="score">You have
        <output id="score">0</output>
        points.
    </label>
</form>

In the initial version we will take advantage of three HTML5 features:

  • The output element
  • The email input type
  • The checkValidity method from the the HTML5 Form Validation API

In the countdown function we use the value property of the the output element The output element is something like a span, it's a start and end tag with arbitrary content, but you can access the contents using the value attribute like a form field :

var counter = function (cd, sc, em) {
    cd.value -= 1;
    sc.value = calcScore(em.value);
}

This may not look particularly helpful, but consider what the code would look like without the output element (or in a browser which doesn't support output):

var counter = function (cd, sc, em) {
    var count = cd.innerHTML;
	count -= 1;
    cd.innerHTML = count;
	sc.innerHTML = calcScore(em.innerHTML);
}

The function is now mostly about the details of manipulating the DOM, rather than the more straightforward algebraic style of the original. Granted, libraries like jQuery have for a long time provided abstractions which allow you to write this code more cleanly but, like design patterns, these are as much an indication of the lack of expressiveness in the underlying platform as they are examples of best practice.

The game needs a function to calculate a 'score' from the email address. This is, of course, completely arbitrary:


function calcScore(email) {
    var s = 0;
    s += email.length;
    s += email.indexOf('@')>-1?email.indexOf('@'):0;
    s += email.lastIndexOf('.')>-1?email.lastIndexOf('.'):0;
    return s;
}

Now we need to wire up the functions to appropriate events when the game starts. To keep things simple I'm going to store a reference to the interval in a global variable:

var cdInterval;
var gameStart = function () {
    window.clearInterval(cdInterval);
    var em = document.getElementById('email');
    var cd = document.getElementById('countdown');
    var sc = document.getElementById('score');
    cd.value = 10;
    sc.value = 0;
    em.value = '';
    em.readOnly = false;
    cdInterval = window.setInterval(counter,1000, cd, sc, em);
    window.setTimeout(gameOver,10000, cd, sc, em);
}

Again, this function takes advantage of the value attribute on the output elements. The last line calls a gameOver function after ten seconds, we'll use that to clear the interval and calculate the score. The checkValidity method of the email field will be used to determine if the email address is currently valid:

var gameOver = function (cd, sc, em) {
    window.clearInterval(cdInterval);
    var score = calcScore(em.value);
    if (!em.checkValidity()) {
        score = 0;
        window.alert("You lose!");
    }
    cd.value = 0;
    sc.value = score;
    em.readOnly = true;
}

The checkValidity() method is part of the HTML5 validation API, it returns true if the browser understands the contents of the field as a valid email. Note that we are able to call this method without submitting the form, so it is easy to hook form submission into a custom validation function if we want. At no point do we have to implement any code to determine what a valid email address would be. This is a second major saving, have a look at this regular expression example if you thought that code was straightforward:

(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])

Finally, start the game when the page loads:

window.addEventListener('load', gameStart, false);

The first version of the game will work in Opera, and the development versions of Firefox (4 - relevant bugs are 345624 and 346485 ) and Chrome (9 - relevant bugs are 27452 and 29363). If you want it to work on older versions of Chrome and Safari then you'll need to replace the output based syntax with the innerHTML approach as per the alternate version of counter above.

For the second iteration we're going to look at these two features:

  • Using the pageshow event from the History API
  • How to reset output elements

If the user visits another page after completing the game and then goes back then the game will sit there inert until you reload the page. This is because the game logic hangs off the onload event, and navigating forward and backwards in the browser history doesn't fire onload. The HTML5 History API gives us another option: the onpageshow event. This fires whenever a page is displayed rather than when it is loaded. There is currently support for onpageshow in Firefox and Chrome, but not in Opera, so we'll use the iseventsupported script to detect support and fall back to onload if it's not available:

if (isEventSupported('pageshow')) {
    window.addEventListener('pageshow', gameStart, false);
} else {
    window.addEventListener('load', gameStart, false);
}

We'll also do some extra work in the gameStart function to clear and reinstate the timeout and, since the autofocus attribute gets ignored in onpageshow, focus the input field:

var gameStart = function () {
    window.clearInterval(cdInterval);
    window.clearTimeout(cdTimeout);
    var em = document.getElementById('email');
    var cd = document.getElementById('countdown');
    var sc = document.getElementById('score');
	cd.value = 10;
	sc.value = 0;
	em.value = '';
    em.readOnly = false;
    cdInterval = window.setInterval(counter,1000, cd, sc, em);
    cdTimeout = window.setTimeout(gameOver,10000, cd, sc, em);
    em.focus();
}

Missing from the first version of the game is any way to restart or replay. Let's start off by adding a reset button to the form:

<input id="restart" type="reset" value="New Game">

There are some obvious issues with this, not least that the form reset isn't going to remove the countdown and game over timeouts. However, rather than deal with that by hooking the event in a sensible way, we're going to take this opportunity to investigate an interesting feature of the output element, the defaultValue.

If you try clicking the reset button as it stands, this is what happens to the two output elements:

Picture of the two output elements after a form reset

The output element is something of a hybrid. Although it can be created, declaratively, in markup, it isn't really any use without JavaScript. While not a direct consequence of this state of affairs, it therefore doesn't matter that there's no way to set the default value of an output element in the HTML, you have to do it with JavaScript using the defaultValue property in the DOM. Let's add a function to set up these fields correctly which will be run onload:

var gameSetup = function() {
    document.getElementById('countdown').defaultValue = "10";
    document.getElementById('score').defaultValue = "0";
    document.getElementById('restart').addEventListener('click', gameStart, false);
}

You'll note that there's also an onclick handler added to the button to restart the game. The reason we don't want to capture the form reset event itself is that we're going to use the form reset method within gameStart. These three lines of code:

cd.value = 10;
sc.value = 0;
em.value = '';

Will become this one line of code:

document.getElementById('game').reset();

But now resetting the form will restore the output fields to their defaultValue, as can been seen in the second checkpoint:

Picture of the two output elements after a form reset now that they have defaultValue set

For the third iteration we're going to concentrate on user feedback. This is going to involve both HTML5 and CSS3:

  • Using the onforminput event to update the score immediately
  • Giving instant feedback on the current validity of the email with CSS3

So far feedback to the user happens every second, in the counter function. Instead of updating the the score every second let's update it every time the input changes. There are a number of options in HTML4 already for handling this - we could attach an event to the email field and monitor it for changes, however HTML5 (for now) presents us with another option: onforminput. Instead of being associated with the input field, the item being updated, onforminput can be associated with the output element, the item we want to update:

document.getElementById('score').addEventListener('forminput', updateScore, false);

Because the output element is the target, the update score function looks like this:

var updateScore = function(ev) {
    ev.target.value = calcScore(document.getElementById('email').value);
}

Unfortunately it seems that onforminput may be dropped from HTML5, so we'd better check for support and fall back to capturing any oninput event on the whole form through event bubbling:

if (isEventSupported('forminput')) {
    document.getElementById('score').addEventListener('forminput', updateScore, false);
} else {
    document.getElementById('game').addEventListener('input', updateGlobalScore, false);
}

This does complicate the function to update the score as the target of the event is no longer the output element, it's whatever input element has been updated. At least in our simple case there's only one input element so we can use the ev.target shortcut, just on the other side of the assignment:

var updateGlobalScore = function(ev) {
    document.getElementById('score').value = calcScore(ev.target.value);
}

If you've been following along in Firefox you will have seen that both provide some default styling for invalid fields:

Default invalid field in Firefox

However Chrome (top) and Opera (bottom) don't show any indication:

default invalid field in Chrome

Default invalid field in Opera

Let's apply some styles explicitly to make everything consistent across browsers:

input[type=email]:invalid {
    box-shadow: none;
    background-color: rgba(255,0,0,0.5);
}
input[type=email]:valid {
    box-shadow: none;
    background-color: rgba(0,255,0,0.5);
}

The box-shadow overrides the Firefox default, while the background-color will be applied in all three browsers, as you can see in the third checkpoint.

The game is now functionally complete, but before we wrap this up I'd like to use one further iteration to examine the checkValidity method more closely. Here's what the spec says about checkValidity:

Returns true if the element's value has no validity problems; false otherwise. Fires an invalid event at the element in the latter case.

We only perform additional work so, instead of using the boolean return value of the function to guide or logic, we could make the end of the game event driven. First we'll simplify the gameOver function, as all we need to do there now is ensure the event gets triggered if the email is invalid (and, thanks to onforminput, we know the score will always be up to date):

var gameOver = function (cd, sc, em) {
    window.clearInterval(cdInterval);
    cd.value = 0;
    em.checkValidity();
}

Now we need to declare an function to handle the oninvalidevent, I've chosen to name it in tribute to cheesy European rock:

var theFinalCountdown = function(e) {
    document.getElementById('score').value = 0;
    window.alert("You lose!");
    e.target.readOnly = true;
}

Then we attach it to the oninvalid of the email field:

document.getElementById('email').addEventListener('invalid', theFinalCountdown, false);

Thus concludes my slightly erratic tour through HTML5 form features with the final checkpoint. If you've enjoyed this please check out the more extensive introduction to HTML5 Forms in Chapter 3 of my book.


Tweet this!
Send feedback »PermalinkPermalink

15/11/10

11:22:02 pm Permalink Hello! HTML5 and CSS3 - 50% Off Until 16th December

Categories: Front End Web Development, Standards, HTML and CSS

Buy early access to my book Hello! HTML5 and CSS3 and get a 50% discount for the next month with the code html550. Coming soon will be the chapter on HTML5 Forms, which should be pretty useful for getting up to speed in time for the release of Firefox 4.


Tweet this!
Send feedback »PermalinkPermalink

20/07/10

03:17:00 pm Permalink Firefox 4.0 Features for Font Fanatics

Categories: Standards, HTML and CSS

Check out the updated syntax in this newer post.

If you're following the development of CSS3 you may have seen, last June, a proposal from John Daggett of Mozilla to bring advanced typography control to the web. A few months later we saw some experimental Firefox builds which demonstrated the features. The terminology has been through a slight update since then, from font-feature-opentype to font-feature-settings, but last week these experiments finally made their way into the trunk builds of Firefox 4.0 on Windows and Mac.

Even though it doesn't yet work under Linux, I thought it was time to start investigating. In this post I'm going to have a look at what these features can look like, mostly following the examples from the October Mozilla Hacks blog post put using the Calluna Regular font. Then I'll show how to turn them on and off in Firefox with CSS, and find the various features using a font editor.

Open Type Font Features

A font is a collection of glyphs, graphical representations of letters, which are associated with characters. Font features are a scheme for getting alternative glyphs for a given character or sequence of characters. The full list of open type features is available in the spec. Each feature is associated with a four character identifier and can be set to on (1) or off (0), here's an example CSS rule:

.example {
    font-feature-settings: "dlig=1,tnum=1,ss01=1";
}

In the current Firefox 4.0 nightly builds you can enable support for the features below by setting the gfx.font_rendering.harfbuzz.level preference to 1 in about:config.

Ligatures

the characters fb with and without standard ligaturesLigatures are special glyphs which replace runs of commonly occurring characters. There are two levels of ligatures, the standard ligatures are turned on by default in Firefox 4.0. To the left is an example in Calluna. The image on the left is from Firefox 3.6, on the right is Firefox 4.0, you can see the slight different where the two characters connect at the top. the combined glyph is also slightly narrower but that's quite hard to stop.

the characters ffb with and without standard ligatures The second example is slightly more obviously different, though with Calluna being a refined font they're still quite subtle. Again it's Firefox 3.6 on the right and 4.0 on the left, the first 'f' is noticeably smaller than the standard one and there's a single bar across both 'f' characters.

the characters - /> and ->> with and without standard ligaturesThere are some ligatures which don't map to commonly occurring sequences of characters (I know fb might not strike you as particularly common, but there are at least 26 just in English). Calluna has two whole sets of arrow glyphs which replace sequences like '-->>' and '-->', more examples to the right.

So in Firefox 4.0, if the font being used supports standard ligatures, you'll see them. If you want to give directions to Firefox users which will appear like random sequences of dashes and greater thans to everyone else you now can. But that's not all! There's also a more decorative set of combinations called discretionary ligatures. Here's some examples, normal on the left, discretionary ligatures on the right:

  • ct with and without discretionary ligatures
  • qu with and without discretionary ligatures
  • sh with and without discretionary ligatures

The point of all this is, of course, that it can all be controlled through CSS. I've constructed an example sentence which could easily occur in conversation at any time and just so happens to contain plenty of words which show off our ligatures. First, let's see what it looks like with everything disabled:

A sample sentence in Calluna with all ligature features turned off

Here's the code to disable the standard ligatures in Firefox 4.0 using -moz-font-feature-settings:

.alloff {
    -moz-font-feature-settings: "liga=0";
}

The ligature feature is called liga. As I mentioned above, we can set it to 1 to enable (which is the default in Firefox 4.0) and 0 to disable. For comparison let's have a look at the standard Firefox 4.0 rendering:

A sample sentence in Calluna with default ligature features

The CSS for this is straightforward as, of course, there isn't any:

.normal {
    /* it's normal, no setting required...*/
}

Now let's turn on the discretionary ligatures:

A sample sentence in Calluna with all ligature features turned on

The discretionary ligature feature is called dlig, again it's 1 to enable and 0 to disable:

.allon {
    -moz-font-feature-settings: "dlig=1";
}

It could be that, for some reason, you want the discretionary ligatures but not the standard ones:

A sample sentence in Calluna with just discretionary ligature features turned on

Probably not much point with Calluna, but perhaps with a more decorative typeface this would be useful. You can pass several features to -moz-font-feature-settings in a comma separated list:

.discretionary {
    -moz-font-feature-settings: "liga=0,dlig=1";
}

How do you go about finding all these ligatures, standard or discretionary? I used FontForge because it was easily installable on my laptop using yum, the interface is a bit archaic but it seems perfectly functional. Here's what it looks like after I've opened up the Calluna font:

Calluna in FontForge

On the view menu there's a combinations sub-menu upon which the ligatures option lives:

FontForge selecting ligatures from the Combinations sub-menu of the View menu

Now you have a list of ligatures to choose from:

FontForge ligatures window

I opened up the 'ffb' ligature:

Calluna f_f_b glyph in FontForge

Now go to the view menu again and look up the Glyph Info option:

FontForge selecting Glyph Info from the Element menu

In the resulting dialogue you can see that 'ffb' is part of the set of standard ligatures:

Calluna in FontForge, Glyph Info for f_f_b

If instead I open up the 'sk' glyph you can see this is part of the discretionary ligature set:

Calluna in FontForge, Glyph Info for s_k

Numerals

Now that we've had some fun with ligatures you may be wondering what other cool tricks are hidden inside open type fonts. One very practical feature is different styles of numbers. Quick pop quiz time, which is the highest number in the screenshot below?

Numbers in Calluna, default settings

Did you guess it was the second one, or did you have to count carefully? Numbers by default are proportionally spaced, which looks nice when they appear in text but can be misleading when looking at tables of figures. But now, thanks to -moz-font-feature-settings, we have some other options:

Numbers in Calluna, tabular figures

The numbers are now using tabular alignment - each number glyph is an equal width. Tabular numerals use the tnum feature:

.tabular {
    -moz-font-feature-settings: "tnum=1";
}

There are a few other number features. The default numbers in Calluna are 'old style' (onum), you can see there's quite a lot of variance caused by the descenders and ascenders going above and below the line. The alternative to that is 'lining figures' (lnum):

Numbers in Calluna, lining figures

As you can see, they give a much more consistent line shape. And you can also have tabular, lining numerals:

Numbers in Calluna, tabular lining figures

.tabular-lining {
    -moz-font-feature-settings: "lnum=1,tnum=1";
}

Once again you can find all these alternatives in FontForge in the Glyph Info window:

Calluna in FontForge, Glyph info window for 1

Before we finish up with numbers, two more features are worth mentioning. You can control whether or not the zero is 'slashed' with the zero feature:

Calluna in FontForge

The bottom number has -moz-font-feature-settings: "zero=1"; applied. You can also enable fractions with the frac feature setting:

Calluna in FontForge

Stylistic Alternatives

There's plenty more stuff in the open type spec, there are 134 different features listed in the spec I linked to in the introduction. The really fancy bits of fonts are often in the twenty 'stylistic sets' ss01 to ss20. You can find what options you may have in FontForge for a particular font by looking for the display substitutions option on the view menu:

Selecting the view menu in FontForge

You then get a dialogue with a list of the options:

FontForge substitutions dialogoue

From which you can see that Calluna only has glyphs for one of the stylistic sets, and when you select ss01 you'll see that there's not a lot of (regular) characters in that:

Calluna stylstic set 01 in FontForge

And there's more...

There's plenty of other interesting stuff wrapped up in open type font feature settings, we haven't yet discussed swashes, contextual alternates or historical forms for just three examples, but I'll leave exploring those as an exercise for the reader.

Practical Considerations

It may seem slightly superfluous for me to mention this about a CSS feature which, so far, has only an experimental implementation in just one browser, but it would be unwise to build a site which depended on font-feature-opentype, for example by relying on certain ligatures or stylistic sets to convey information. However, for making your typography look a bit nicer for a subset of your users, this stuff will be usable on real web pages from the day of Firefox 4.0's release.

The Future

Now you're salivating for a future where all web browsers support font-feature-settings this is probably a good time to point out that, once that support exists, you'll hardly ever use it &amp;#58;&amp;#41; No, this is not a trick, font-feature-settings itself is only intended to be used for obscure and little used options in the open font features list, the common stuff will be accessible through new values on the font-variant property as well as several font-variant-* properties. The current level of support in Firefox is really only to see how things will look once all that gets implemented.

Let's have a look at how a future you will be recreating my examples with the proposed font-variant property extensions. First, discretionary ligatures:

.discretionary {
    font-variant: additional-ligatures;
}

Alternatively we cold use the specific ligatures property:

.discretionary {
    font-variant-ligatures: additional-ligatures;
}

Each value has a corresponding no-* version, so you could specify no-common-ligatures to turn off the common ones, or no-additional-ligatures in order to override the above rule further down the inheritance chain. What about lining, tabular numerals?

.tabular-lining {
    font-variant-numeric: lining-nums tabular-nums;
}

None of this is implemented yet, so I can't test I've got it right, and all this syntax is still subject to change as the fonts module is still a working draft, so I'll stop there. Hopefully this has given you some ideas for fancy typography to give Firefox 4.0 users a special treat and will set you off on your own investigations.


Tweet this!
1 feedback »PermalinkPermalink

31/05/10

12:40:37 am Permalink London Web Standards: Beautiful Design for Everyone with Ann McMeekin

Categories: Web Design, Usability & Accessibility

Review: LWS May: Beautiful Design for Everyone at The Melton Mowbray, 18 Holborn, EC1N 2LE, London 19:00 to 20:30

This event was originally going to be a double act, but Antonia Hyde unfortunately had to pull out. We were fortunate to have someone of the calibre of Ann McMeekin to pick up the slack. Ann had some very beautiful slides and spent a lot of time talking about each one, I made some necessarily limited notes from which I will attempt to reconstruct the gist of what she said (hopefully I don't misrepresent anything too badly!) and tried to locate some of the pictures from the presentation to give the flavour of it.

Ann began by talking about her background as an accessibility consultant, which she initially thought would be her dream job but, over time, she came to realize that what she really valued was not great accessibility but great design. Great design, of course, includes accessibility, but the focus is not on a check-list of requirements but the overall experience each user will have.

While accessibility is a widely accepted goal, honest discussion about it is often difficult as many people find talking about disability uncomfortable. A common reaction when seeing for the first time the rigmarole a screen reader user has to go through to get useful information out of some websites, is to feel empathy and start thinking how terrible it must be to put up with that, which leads immediately to that uncomfortable feeling. However, to provide accessible design solutions we must get past the stage of empathy in order to develop understanding about what tools we need to provide. Disabled people are not passively waiting for us to make their lives better, they just want the tools to make a better life for themselves.

Next Ann showed us a segment from a TED talk by Aimee Mullins. Aimee, who had her lower legs amputated as a child, famously competed in the 1996 Paralympics on a set of carbon fibre 'cheetah legs' (this TED talk includes a description of her experiences at the games) and has since gained fame as a speaker, model and actress. Aimee talked about her collection of prosthetic legs and the different abilities and attributes each provided her with, like the cheetah legs for running or the set she was wearing for the talk which added six inches to her normal height:

I have a variable of five different heights. (Laughter) Today, I'm 6'1". And I had these legs made a little over a year ago at Dorset Orthopaedic in England and when I brought them home to Manhattan, my first night out on the town, I went to a very fancy party. And a girl was there who has known me for years at my normal 5'8". Her mouth dropped open when she saw me, and she went, "But you're so tall!" And I said, "I know. Isn't it fun?" I mean, it's a little bit like wearing stilts on stilts, but I have an entirely new relationship to door jams that I never expected I would ever have. And I was having fun with it. And she looked at me, and she said, "But, Aimee, that's not fair."

For Aimee the loss of her lower legs is not so much a disability as an opportunity. And the opportunity isn't just to 'be normal', whatever that may mean, she can exceed normal.

Aimee Mullins gives a TED talk, standing in front of slide which highlights the popular negative connotations which go with the term disabled - showing the synonyms listed in a thesaurus

She doesn't see herself as limited, and so she isn't limited (from another TED talk by Aimee):

I loved almost everything about my time spent at this hospital, with the exception of my physical therapy sessions. I had to do what seemed like innumerable repetitions of exercises with these thick, elastic bands -- different colors -- you know, to help build up my leg muscles. And I hated these bands more than anything. I hated them, had names for them. I hated them. And, you know, I was already bargaining, as a five year-old child, with Dr. P to try to get out of doing these exercises, unsuccessfully, of course. And, one day, he came in to my session -- exhaustive and unforgiving, these sessions -- and he said to me, "Wow. Aimee, you are such a strong, powerful little girl, I think you're going to break one of those bands. When you do break it, I'm going to give you a hundred bucks."

Now, of course, this was a simple ploy on Dr. P's part to get me to do the exercises I didn't want to do before the prospect of being the richest five year-old in the second floor ward, but what he effectively did for me was reshape an awful daily occurrence into a new and promising experience for me. And I have to wonder today, to what extent his vision, and his declaration of me as a strong and powerful little girl, shaped my own view of myself as an inherently strong, powerful and athletic person well into the future.

Good design should create this same feeling of empowerment, for everybody. It is not about ticking off boxes, but about enabling people to achieve their goals, provide tools for augmentation, not just equalization. And just because a tool serves a purpose, doesn't mean it can't be beautiful:

This is where it really hit home for me -- that my legs could be wearable sculpture. And even at this point, I started to move away from the need to replicate humanness as the only aesthetic ideal. So we made what people lovingly referred to as glass legs even though they're actually optically clear polyurethane, a.k.a. bowling ball material. Heavy! Then we made these legs that are cast in soil with a potato root system growing in them, and beetroots out the top, and a very lovely brass toe [...] Then another character was a half-woman, half-cheetah -- a little homage to my life as an athlete. 14 hours of prosthetic make-up to get into a creature that had articulated paws, claws and a tail that whipped around, like a gecko. And then another pair of legs we collaborated on were these look like jellyfish legs. Also polyurethane. And the only purpose that these legs can serve, outside the context of the film, is to provoke the senses and ignite the imagination. So whimsy matters.

So prosthetic legs are not just a utilitarian accessibility tool but something beautiful in their own right, a work of art, and the same can be true of our own designs. As to how to achieve beautiful, accessible design, Ann covered that in three sections: Structure; Alternatives; and Flexibility.

Structure

The foundation of good design is structure, which implies planning. As an example of what happens when there's no structure Ann talked about the Winchester Mystery House. This was a house built by the widow of a member of the Winchester Repeating Arms Company dynasty, she believed that the ghosts of all the people ever killed by one of the rifles were out to get her and the only way to keep them at bay was to keep building the house. So it was built, 24 hours a day for 38 years with no plan or goal in mind other than to be building continuously.

The Winchester House, California

Although the end result is, in many ways, fascinating, from the point of view of being a usable living space it's a complete disaster - it's almost impossible to navigate without a map, and so unusable. If you are willing to do a little planning, and from the recent boom in User Experience it seems companies are able to appreciate the value, then you can build an accessible structure without compromising your design. Ann had a number of examples, the first was these bus stops in Bristol:

Integrated Accessibility: Raised paving at Bristol bus stops

The paving is raised at each bus stop, even well out into the suburbs, so that people on wheel chairs (and mothers with wheelchairs) can simply roll on to the bus - no need for leaning buses that the driver has to remember to operate, or special ramps that have to be got out and attached, slowing everyone's journey. The bus stops are a shared space, anyone can use them, there was no need for having 'normal' bus stops and 'special' bus stops. Another example of shared spaces in action is the steps at the Brunswick Shopping Centre. Ann had been walking up and down these steps for two months before noticing that they had an integrated ramp:

Integrated Accessibility: Integrated steps and ramp at the Brunswick Centre

Alternatives

As we've just seen, alternatives don't have to be hidden - there doesn't have to be a ramp round the back while everyone else goes up the steps at the front, but they do have to be discoverable. An example is Braille labels - you see these all over the place now alongside the visible labels on signs and buttons, but how do these actually help blind people? Does anyone really expect blind people to walk around feeling all the walls on the off chance there'll be Braille there? Designers have ticked the box - 'provide an alternative for blind people' - but they've not really thought about what a blind person needs to be able to navigate the environment. Don't simply provide a Braille version of the menu, think about what a blind person needs to be able to independently go to a restaurant and order a meal.

One area where it's always appropriate to provide text alternatives is for pictures and videos. Captions on images can be integrated into the design fairly easily, like, for example, on the The Big Picture blog on Boston.com. Transcripts for videos have traditionally been regarded as prohibitively expensive, especially for small producers. But there are a number of cheap options these days:

Flexibility

Not all disabilities are constituted of a fixed and unchanging set of symptoms (eg. MS sufferers can vary from day to day and hour to hour). An insufficiently flexible site, may, even for the same user, be reasonably usable one day, but unusable the next.

Also not all people who would benefit from making use of 'accessible' options will self identify as disabled. Older users are likely to benefit from font sizing and readability options just as much as the partially sighted or those with learning disabilities, but they may be unlikely to click on a link for 'disabled users' in order to find them.

When thinking about flexibility bear in mind that people don't need to have the same experience, but that doesn't pre-dispose that anyone should have a lesser experience. Ann used an example of a blind friend of hers who liked to visit the Tate Modern. You might wonder what a blind person could get out of looking at a painting, but he could listen to the painting by listening to ambient sound reflected off them, the different colours get reflected in different ways. Obviously he's not getting the same experience a sighted person would do, bet then sighted people aren't getting the experience he is and both can get a lot out of it (and, by the way, the Tate Modern has help and tours for blind and visually impaired visitors).

If you have compelling content, of course, you'll get users no matter how badly designed your site is. Amazon, for a long time, had terrible accessibility, but everybody liked cheap books. In this situation users develop coping strategies - Ann told us about one blind user who'd worked out a very detailed method of getting to what he wanted on Amazon, to the extent that it went "do this, then hit the tab key 43 times." Sure you might take comfort in the fact that someone has figured out how to use your site anyway, but did you need to make it that painful?

To finish with, Ann reminded us that while good design can be difficult, it's from solving the difficult problems that we derive the most satisfaction.

Post Talk Discussion and Questions

To conclude the talk, instead of going straight into questions, Ann asked us for examples of good design to add to her, regrettably, somewhat small collection. The first example was a blind person who went around sticking irreverent and subversive Braille messages on to signs, a sort of graffiti that few people are aware is even there. Another person mentioned some recent improvements to the riverside area in Bedford which had been done with accessibility in mind so that everyone could enjoy the river.

As counterpoint, another attendee described a lift he'd seen where they'd put Braille labels on the buttons, the only problem was - they were touch sensitive buttons! This was clearly an example of ticking the boxes rather than trying to understand what a blind person would need in order to use the lift.

There were a lot of other good examples and discussion but I'm already closing in on seven days to write up a two hour talk, so I'll leave it there. Another excellent LWS event, 5 out of 5 once again. Antonia will hopefully be able to make a future talk, in the meantime watch out for the June event on Flash vs HTML5.

Technorati tags for this review:    

Tweet this!
Send feedback »PermalinkPermalink