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

22/12/09

07:08:57 pm Permalink FizzBuzz in CSS3

Categories: Standards, HTML and CSS

I was reading Rachel Andrew's 24 ways post on Cleaner Code with CSS3 Selectors today, in which she covered nth-child selectors, and I was reminded of the FizzBuzz phenomenon which swept through Programming Reddit a couple of years ago. I thought it would be relatively easy to implement a CSS solution to the problem based on the nth-child selectors and generated content.

First I tried a quick test based on an ordered list and Rachel's example code for the table:

ol:nth-child(3n) li:after {
    content: "Fizz";
}

Using the advanced technique of copy and paste I quickly produced an ol element with 100 li's in it and observed the results. It wasn't quite a spectacular failure, but no Fizz appeared. A little reflection and I think I've figured out what I was doing wrong - the li is already the nth-child of ol and there are no further li child elements, so the rule doesn't match anything. After a bit of fiddling around I came up with two alternatives, cut out the li altogether:

ol :nth-child(3n):after {
    content: "Fizz";
}

Or use nth-of-type directly on li instead of nth-child:

ol li:nth-of-type(3n):after {
    content: "Fizz";
}

Then I realised that the ordered list was probably a mistake - I ought to be printing the number when none of Fizz, Buzz or FizzBuzz applies. My initial thinking was that having the number built into the markup would make it easier, but now I realised I'd have to both remove the default numbers and then insert new numbers in. So I switched to a table with 100 rows in it and started reading up on counters and numbering. This seems to work almost like a programming language, first you declare your variable on the root element:

table {
    counter-reset: number;
}

Then you stick it in a loop:

tr td:before {
    counter-increment: number;
    content: counter(number);
}

So now I have a table which counts up to 100, I override the generated content for each third and fifth child:

tr:nth-child(3n) td:before {
    content: "Fizz";
}
tr:nth-child(5n) td:before {
    content: "Buzz";
}

Finally specify the content for elements which are both a third and a fifth child:

tr:nth-child(3n):nth-child(5n) td:before {
    content: "FizzBuzz";
}

And, ta-da, FizzBuzz implemented in CSS (with the slightly unusual input requirement of a 100 row HTML table).


Tweet this!
Send feedback »PermalinkPermalink

01/12/09

01:04:35 am Permalink YDN: More Accessible User Interfaces with ARIA

Categories: Usability & Accessibility, Front End Web Development

Review: More Accessible User Interfaces with ARIA at Skills Matter, 116-120 Goswell Road, London, England EC1V 7DP 18:30 to 20:00

I've long been meaning to take a closer look at WAI-ARIA, so last week's YDN talk at Skills Matter by YUI developer Todd Kloots seemed like an excellent opportunity to learn the basics. With them starting at half six, forcing me to travel halfway across London in the middle of rush hour, I often miss the start of Skills Matter events and this one was no exception - though this time the main problem was that they are now at new offices and I went to the old one first.

The talk was split into four parts, followed by some Q & A:

  • How ARIA solves problems of perception
  • How ARIA solves problems of context
  • How ARIA solves problems of discoverability
  • Tips and tricks for working with ARIA

How ARIA solves problems of perception

One of the problems faced by screen reader users is working out what a page element they come across is for and what state the element is in. A sighted user can look at a web page and easily see an area devoted to navigation and an area for main content, what things are toolbars and buttons and what state they're in (eg. bold mode in a text formatting toolbar).

How ARIA solves problems of context

HTML has only a limited palette of context setting elements - headings, lists and form grouping elements, such as h1 and fieldset can be used to indicate section breaks in your content. But if you wanted to indicate a tab control or a toolbar to assistive technology there's no standard markup to do that.

To address this ARIA has landmark roles, as we saw earlier, but it also allows you to indicate which sections of your page should be treated as a document and which should be treated as an application. In document mode, the screen reader responds to its own keyboard shortcuts for browsing, in application mode you can provide keyboard shortcuts for working with your widgets. ARIA also provides recommendations for keyboard shortcuts to use.

Todd discussed two ways of making sure your widget is keyboard accessible without drowning the user in choices. For example, if you have a toolbar widget you may not want the keyboard user to have to tab through every item on the toolbar every time they encounter it. It would be better if they could tab to select the toolbar but then tab again to skip over it if they didn't need any toolbar functions at this time. The two techniques are to use aria-activedescendent or to use a roaming tab index - set a tabindex of -1 on all the child elements of your widget and then adjust focus programmatically in response to key strokes. Todd has previously published a blog post which describes both focus management techniques in detail, he currently prefers the roaming tabindex approach because of its backwards compatibility (though watch out for the known focus event delegation issues).

How ARIA solves problems of discoverability

After you've created a keyboard accessible widget using ARIA roles and states you need to make sure users can actually discover your widget - all your good engineering work goes to waste if users never realise the functionality is there. This is where aria-live and aria-describedby are useful.

A live region allows text to be spoken to the user without that text gaining focus, thus losing the reader's place in the content. Depending on the nature of the message it can either be polite, assertive or rude - ranging from waiting until a pause or interrupting the user whatever they may be doing. An auto-complete list would be an ideal candidate for a live region - Todd demonstrated how live regions work on the Yahoo! Suggest feature on their search page.

The aria-describedby property allows you to link to a longer description of what your widget does, so you can inform the user, the first time they focus on your widget, of how to access the functionality of your widget as well as what to expect when they interact with it - again this was demonstrated in the suggest feature on Yahoo! search.

Tips and tricks for working with ARIA

The key tip if you're going to delve in ARIA is to install a screen reader and test things yourself! There are free ones for various platforms (eg. Windows and Linux). If you're unsure where to start, read this tutorial about setting up a test environment with NVDA and Firefox.

The second tip was more of a warning - ARIA gives developers a great deal of control over the end user experience, because it allows them to bypass the virtual buffer of the screenreader and talk directly to the user. This brings with it a risk - having all web browsing mediated by the screen reader made for a consistent user experience, now there's the potential for every site to be different leading to user confusion.

Q & A

There was an interesting question and answer session at the end. The first question was about the new semantic elements in HTML5 and whether screen readers were taking advantage of them yet - not so much, Todd felt that mush of ARIA is available today to far more users. Further questions brought up the frightening prospect of web developers having to take into account not just compatibility across various browsers but also a second dimension of cross screenreader compatibility and finally if any of the popular Javascript libraries had built in support for ARIA (YUI 3 has built in support).
http://skillsmatter.com/podcast/os-mobile-server/aria

All in all this was an excellent talk, 5 out of 5. One of the most technically detailed talks I've attended at Skills Matter - far more stuff was discussed than I've managed to fit into this blog post. If you're interested I recommend you watch the video.

Technorati tags for this review:    

Tweet this!
Send feedback »PermalinkPermalink

21/10/09

02:50:26 pm Permalink Adventures in Web 3.0: Part 4 - Yet More CSS 3

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

In my last post on CSS3 I looked at scaling background images, RGBA colours and CSS gradients. In the early hours of Saturday morning it became increasingly apparent to me that I'd bitten off a bit more than I could chew in terms of a single post, as there were a few other things I wanted to cover. These were some practical layouts you could achieve thanks to these new features and some more details of cross-browser and backwards compatibility, which I shall now attempt to cover in this post.

I decided to see what interesting effects could can be achieved in terms of navigation menus, assuming the fairly standard 'list of links' markup. I began with some fairly innocuous markup in the 'navigation as list of links' tradition:

<div id="nav">
    <ul>
        <li><a href="#">Link One</a></li>
        <li><a href="#">2</a></li>
        <li><a href="#">Link Number Three</a></li>
    </ul>
</div>

You can see that there are three links/buttons with varying lengths. Traditionally this causes problems with image backgrounds which lead to using sliding doors and related techniques. The task I set myself was to see what I could achieve visually with this using only CSS, no additional markup allowed. My first idea was simply to use a 'shiny button' background image and scale it using background-size:

div#nav ul li {
    padding: 1em;
    background-image: url('bg-image-2.png');   /* Image courtesy of http://blog.entropiads.com/2009/01/29/free-3-d-glossy-button-icons/ */
    background-size: 100% 100%;
    -moz-background-size: 100% 100%;           /* Gecko 1.9.2 (Firefox 3.6) */
    -o-background-size: 100% 100%;             /* Opera 9.5 */
    -webkit-background-size: 100% 100%;        /* Safari 3.0 */
    -khtml-background-size: 100% 100%;         /* Konqueror 3.5.4 */
}
div#nav ul li a {
    color: #fff;
    padding: 1em;
}

It seems to work quite well:

Links with scaled background image

Note that this is doing something that you can't achieve with sliding doors - a typical sliding door image is uniform most of the way across, with something different in the first and last few pixels (eg. a rounded corner). So with a sliding doors approach as the button gets progressively wider the actual rounding becomes relatively smaller, whereas with a scaled background the rounding is relative to the size. This is something background scaling has in common with CSS gradients (ultimately they're just a different way to specify a scaled background) as we'll see below. This may or may not be an effect you want, I think if it's a more traditional sliding doors style look you're after then border-image is probably the thing to use.

For my next trick I decided to use CSS gradients to make some shiny buttons:

div#nav ul li {
    -moz-border-radius: 0.5em;
    -webkit-border-radius: 0.5em;
    background-image: -moz-linear-gradient(top, bottom, from(#090), to(#060), color-stop(25%, #cfc));
    background-image: -webkit-gradient(linear, left top, left bottom, from(#090), to(#060), color-stop(25%, #cfc));
}
div#nav ul li a {
    display: block;
    color: #fff;
    padding: 1em;
}

I discussed gradients towards the end of my last post on CSS3. The main gotcha is that Gecko and WebKit use a different syntax, though it's straightforward to translate between the two. I'm creating a top to bottom gradient from medium green to slightly darker green, but stopping at very light green one quarter of the way down. This is what it looks like:

Links with CSS gradient background

Next I started thinking about whether it was possible to achieve a sliding doors style bevel effect with CSS gradients, by using a gradient with dark edges. My approach was to layer the gradients using alpha transparency to let the bottom one show through, a top to bottom one on the li with a left to right one on the a:

div#nav ul li {
    -moz-border-radius: 0.5em;
    -webkit-border-radius: 0.5em;
    overflow: hidden;
    background-image: -moz-linear-gradient(top, bottom, from(rgba(0,255,0,1)), to(rgba(0,51,0,1)), color-stop(2%, rgba(0,255,0,1)), color-stop(4%, rgba(102,255,102,1)), color-stop(96%, rgba(102,255,102,1)),color-stop(98%, rgba(0,153,0,1)));
    background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0,255,0,1)), to(rgba(0,51,0,1)), color-stop(2%, rgba(0,255,0,1)), color-stop(4%, rgba(102,255,102,1)), color-stop(96%, rgba(102,255,102,1)),color-stop(98%, rgba(0,153,0,1)));
}
div#nav ul li a {
    color: #fff;
    display: block;
    padding: 1em;
    -moz-border-radius: 0.5em;
    background-image: -moz-linear-gradient(left, right, from(rgba(0,255,0,0.5)), to(rgba(0,51,0,0.5)), color-stop(2%, rgba(0,255,0,0.5)), color-stop(4%, rgba(102,255,102,0.5)), color-stop(96%, rgba(102,255,102,0.5)),color-stop(98%, rgba(0,153,0,0.5)));
    background-image: -webkit-gradient(linear, left top, right top, from(rgba(0,255,0,0.5)), to(rgba(0,51,0,0.5)), color-stop(2%, rgba(0,255,0,0.5)), color-stop(4%, rgba(102,255,102,0.5)), color-stop(96%, rgba(102,255,102,0.5)),color-stop(98%, rgba(0,153,0,0.5)));
}

Here is the end result:

Links with overlaid CSS gradient backgrounds for bevel effect

As you can see, it's not entirely effective thanks to the scaling issue I pointed out above. The width of the element is linked to the apparent depth of the bevel as you can only set the colour stops as percentages. For my test case of a collection of different width buttons this makes it look a bit funny, where it might work better is if you have a set of equal size buttons which scale according to font size - then the bevel wouldn't get less significant as the text got bigger.

Also note that, in CSS3, there's no need to use multiple elements in order to get multiple background images as a single element can have multiple backgrounds defined in its CSS rule. In this case it doesn't really matter, because the nature of a menu means I had two elements overlaid anyway, but I can get exactly the same effect as above by using the following CSS instead:

div#nav ul li {
    -moz-border-radius: 0.5em;
    -webkit-border-radius: 0.5em;
    overflow: hidden;
}
div#nav ul li a {
    color: #fff;
    display: block;
    padding: 1em;
    -moz-border-radius: 0.5em;
    background-image: -moz-linear-gradient(left, right, from(rgba(0,255,0,0.5)), to(rgba(0,51,0,0.5)), color-stop(2%, rgba(0,255,0,0.5)), color-stop(4%, rgba(102,255,102,0.5)), color-stop(96%, rgba(102,255,102,0.5)),color-stop(98%, rgba(0,153,0,0.5))),
                      -moz-linear-gradient(top, bottom, from(rgba(0,255,0,1)), to(rgba(0,51,0,1)), color-stop(2%, rgba(0,255,0,1)), color-stop(4%, rgba(102,255,102,1)), color-stop(96%, rgba(102,255,102,1)),color-stop(98%, rgba(0,153,0,1)));
    background-image: -webkit-gradient(linear, left top, right top, from(rgba(0,255,0,0.5)), to(rgba(0,51,0,0.5)), color-stop(2%, rgba(0,255,0,0.5)), color-stop(4%, rgba(102,255,102,0.5)), color-stop(96%, rgba(102,255,102,0.5)),color-stop(98%, rgba(0,153,0,0.5))),
                      -webkit-gradient(linear, left top, left bottom, from(rgba(0,255,0,1)), to(rgba(0,51,0,1)), color-stop(2%, rgba(0,255,0,1)), color-stop(4%, rgba(102,255,102,1)), color-stop(96%, rgba(102,255,102,1)),color-stop(98%, rgba(0,153,0,1)));
}

Simply list the images top to bottom in a comma separated list, so I simply took the gradient from the li rule above (the 'underneath' element) and added it after the a background.

At this point I gave up on the bevelled buttons and started thinking about some other 3D style effects that could be achieved. I went for some shiny, metallic style buttons with pseudo 3D indented text - the sort of thing you'd normally do in Photoshop:

div#nav ul li {
    -moz-border-radius: 0.5em;
    -webkit-border-radius: 0.5em;
    background-image: -moz-linear-gradient(top, bottom, from(#090), to(#060), color-stop(25%, #cfc));
    background-image: -webkit-gradient(linear, left top, left bottom, from(#090), to(#060), color-stop(25%, #cfc));
}
div#nav ul li a {
    color: rgba(0,51,0,0.5);
    text-decoration: none;
    font-weight: bold;
    display: block;
    padding: 1em;
    -moz-border-radius: 0.5em;
    text-shadow: 1px 1px rgba(204,255,204,0.5), -1px -1px rgba(51,102,51,0.5);
}

As you can see the gradient is the same as in the example above, but I've used multiple text shadows, one offset slightly above and left, the other below and right, to fake the 3D look:

Links with CSS gradient background and text shadow for 3D effect

This gives me an opportunity to do a declarative interactive effect with the hover rule. Reverse the text shadows and, because this will produce an apparent one pixel shift in the position of the text, translate the item to counter that:

div#nav ul li a:hover {
    text-shadow: -1px -1px rgba(204,255,204,0.5), 1px 1px rgba(51,102,51,0.5);
    -moz-transform:  translate(-1px, -1px);
    -webkit-transform:  translate(-1px, -1px);
}

Here's what one of the buttons looks like with the mouse pointer over:

Links with CSS gradient background and text shadow for 3D effect in hover mode

It occurred to me that it would be possible to invert the apparent 3D of the whole button rather than just the text:

div#nav ul li:hover {
    -moz-border-radius: 0.5em;
    -webkit-border-radius: 0.5em;
    background-image: -moz-linear-gradient(bottom, top, from(#090), to(#060), color-stop(25%, #cfc));
    background-image: -webkit-gradient(linear, left bottom, left top, from(#090), to(#060), color-stop(25%, #cfc));
}
div#nav ul li a:hover {
    text-shadow: -1px -1px rgba(204,255,204,0.5), 1px 1px rgba(51,102,51,0.5);
    -moz-transform:  translate(-1px, -1px);
    -webkit-transform:  translate(-1px, -1px);
}

Of course, I'm not a graphic designer, so when I say reverse I really mean I just flipped it upside down, but I'm sure someone with some artistic skills could make it work properly. Here's what mine looks like:

Links with CSS gradient background and text shadow for 3D effect in hover mode on both link and containing element

So, on the subject of my lack of graphic design skills, I wondered if someone who had some skills had attempted this sort of thing. Google presented me with GirlieMac's CSS3 Gradients: No Image Aqua Button. Although this is pure CSS and uses no images, it does add additional markup. I started with her CSS but tried to apply it to my existing markup. Instead of adding an extra element for the glare I tried to achieve a similar effect with a radial gradient:

div#nav ul li {
    -webkit-border-radius: 16px;
    -moz-border-radius: 16px;
    border: 2px solid #ccc;
    position: relative;
    font-family: Lucida Sans, Helvetica, sans-serif;
    font-weight: 800;
    color: #fff;
    text-shadow: rgba(10, 10, 10, 0.5) 1px 2px 2px;
    text-align: center;
    vertical-align: middle;
    white-space: nowrap;
    text-overflow: ellipsis;
    overflow: hidden;
    background-color: rgba(60, 132, 198, 0.8);
    background-image: -moz-linear-gradient(0% 0%, 0% 100%, from(rgba(28, 91, 155, 0.8)), to(rgba(108, 191, 255, .9)));
    background-image: -webkit-gradient(linear, 0% 0%, 0% 90%, from(rgba(28, 91, 155, 0.8)), to(rgba(108, 191, 255, .9)));
    border-top-color: #8ba2c1;
    border-right-color: #5890bf;
    border-bottom-color: #4f93ca;
    border-left-color: #768fa5;
    -webkit-box-shadow: rgba(66, 140, 240, 0.5) 0px 10px 16px;
    -moz-box-shadow: rgba(66, 140, 240, 0.5) 0px 10px 16px; /* FF 3.5+ */
}
div#nav ul li a {
    display: block;
    color: #fff;
    text-decoration: none;
    padding: 10px 32px 6px;
    -webkit-border-radius: 8px;
    -moz-border-radius: 8px;
    background-color: rgba(255, 255, 255, 0.25);
    background-repeat: no-repeat;
    background-image: -moz-radial-gradient(center top, 5px, center top, 50px, from(rgba(255, 255, 255, 0.7)), to(rgba(255, 255, 255, 0)));
    background-image: -webkit-gradient(radial, 50% 0%, 5, 50% 0%, 50, from(rgba(255, 255, 255, 0.7)), to(rgba(255, 255, 255, 0)));
}

The radial gradient for the glare was the toughest thing as I couldn't find a way to make it anything other than round. There doesn't seem to be a way within the definition and applying background size to it didn't seem to work. In the end I settled for positioning it so the middle of the gradient was aligned with the top border:

Sort of Aqua buttons with no extra markup

That concludes my experiments with buttons, here's a page with all the button examples above, you need Firefox 3.6 or later or a recent Chrome/Safari to see everything working. As per usual there's more to say, but that will have to wait for (yet) another post &amp;#59;&amp;#41;


Tweet this!
Send feedback »PermalinkPermalink

26/09/09

11:55:14 pm Permalink Standards.Next Cognition and Accessibility

Categories: Web Design, Usability & Accessibility, Front End Web Development

Review: Standards.Next Cognition and Accessibility at City University, Room C343, Northampton Square, London, England EC1V 0HB 13:00 to 17:00

Last weekend I went to the second Standards.Next event, a whole afternoon devoted to talks and discussion related to the often ignored and misunderstood area of accessibility for people with cognitive impairments.
Picture of the audience listening attentively to Ian Pouncey

Accessibility beyond code - Antonia Hyde (slides)

Antonia talked about some of the issues in enabling access outside of the details of code. With the range of disabilities, plethora of personal preferences and array of access methods are there any general approaches which help to address all the combinations? To provide some context we watched two video clips of Martin, an experienced web user with learning difficulties. First we saw him using a site he was familiar with, eBay, then a site he was unfamiliar with, Amazon.

Martin got on very well with eBay, he made extensive use of its consistent search features and the nature of the site means that it features a lot of large meaningful pictures which are the focus of the content. Even so, there were some details which caused issues which perhaps were not significant enough that the designer would even think of them. For instance there is a 'Buy it now' button on the product pages which, not surprisingly, allows you to bid for the item, but there is also an identical 'Buy it now' image on the search results which wasn't clickable.

On Amazon, a site often lauded for its usability, Martin had a great deal of difficulty. There was a lack of meaningful icons, a lot of the most striking imagery on a page was unrelated to the main content, there was often bad typography and poor contrast and the buttons were not clearly defined. Martin had great difficulty first of all trying to sign up for the site and then trying to buy something.

Antonia then talked about some general strategies for making sites more accessible:

  • Be literal: This doesn't mean going in to excruciating detail, it means saying things simply and clearly with no contradictions. It also means grouping page elements and respecting the hierarchy of visual language, having consistent colour coding and using meaningful icons with related words. There was a great (but bad) example taken from a warning sign on the Underground - the text says "Don't run on the escalator" but the graphic shows a man happily running down the escalator with his briefcase.
  • Make things bigger: Not just literally, for instance having space around items can make them appear bigger. Also having obvious tools for text sizing, alternative colour schemes and content access methods can really make or break the accessibility of a site. We got into a bit of a side discussion at this point about why users didn't just use built in browser functionality for this, the gist of it was that browser manufacturers need to find a way to make stuff more discoverable.
  • Responsibility: Accessibility is the responsibility of all people involved in creating a website - designers, developer, content producers and managers are all equally responsible. Cohesion and consistency is a key factor in accessiblity, and content is useless if it can't be accessed.

What is Autism - Jamie Knight (slides)

Jamie is a web developer who is autistic. He gave a presentation on what autism is and this was followed by an open discussion. Autism means having a thinking process which is slightly different in the way it processes ideas and inputs from the environment. Some things which are problematic for autistic people are:

  • Background music on websites, and background noise in general, make it impossible to read
  • Language coming too quickly (eg. in video or audio), especially if there are multiple speakers with no delay or visual pause between them
  • A literal mindedness can lead to confusion, eg. "Add friends" means a different thing on almost every website, especially in Facebook where it means different things on different pages

On the other hand the web can be extremely liberating and empowering for autistic people, because it removes a lot of the time pressures of traditional social interaction (Antonia also mentioned this). In the interesting discussion that followed Jamie discussed how he used a screenreader (originally one he'd written himself) when he was too tired to read, highlighting that the set of people that are using screenreaders is not necessarily identical to the set of people that can't see your site. I also learned about the different voice options available in screenreaders - a faster 'robot voice' or the slower but more 'human' voice which differ in the algorithms used to determine sounds. Jamie used different voices in different situations - the robot sounded a bit strange reading out text in the first person, the human voice has difficulty with some pronunciations.

Why user testing beats dogma - David Owens

David had recently completed a project which included a lot of testing with users who have cognitive issues. There were no slides but it was good to hear from someone with practical experience of the sort of issues which can come up:

  • Before they even started their testing they had to rewrite all their user testing scripts as they were too complex and lacked context - it's not just your website that needs to be accessible.
  • Don't overcomplicate. When developing they'd paid particular attention to the source order - putting the main content first and the navigation after it. What this does is completely confuse screen reader users, especially the partially sighted ones for whom the layout of the page on screen no longer matched what they were hearing.
  • Reiterating one of Antonia's points, you must signpost the tools. Mostly users won't remember how to find their browser's text size option, or the key combination required.
  • If it comes to a choice between 'best practice' or the standards and what your test results show, always choose to make things easier for your users.

Content and Cognition - Ian Pouncey (slides)

Ian presented some practical advice based on his years of experience working in web accessibility:

  • Consistency: Make your navigation consistent, don't chop and change main navigation between pages; use a small number of fonts, counting different sizes and weights as different fonts; make sure your interactive elements, links and buttons, are the same across all pages and clearly are links and buttons.
  • Structure: Make sure your headings are clear and meaningful and represent their associated content; Break content up into lists, keeping each point short and concise; Make use of whitespace, particularly horizontal spacing; clearly differentiate content types, eg, quotes.
  • Focus: Avoid contrasting blocks of colour, eg. don't make your navigation more visually appealing than your main content; Avoid unexpected sound and moving content; Avoid popup windows and (after some comments from the audience) light boxes.
  • Readability: Make sure you have adequate text size and line height; Limit your line length to 70-80 characters but avoid justification because of the 'rivers of white' problem; Make sure you have good colour contrast; Keep your paragraphs short.
  • Transformability: Bearing in mind that you can't please everyone, you should make sure your content is easily transformed - ie. allows for resizing; Supports user stylesheets; Works well with images and/or styles disabled;; Make sure your content is printable, as many people prefer to read from paper; Provide an API or feed for when all else fails. In this section also mentioned that he thinks elastic layouts (where the size is based on the font size) are a bad idea - they make text resizing behave like page zoom, in effect taking an option away from the user.
  • Content: Pay attention to your spelling and grammar, if you can't get someone else to review your writing then leave it for a few days and look at it with a fresh eye, also getting a screen reader to read it to you may help; Define your terms, avoid jargon but not at the expense of clarity; Always summarise your content - point, example, explanation, summary.
Ian then gave a practical example of reworking a simple web page to be more accessible and some of the techniques you might consider. In the discussion we got on to CAPTCHAs and related techniques:
  • Don't assume that 'simple' tasks are simple, eg. 2+2 and Dyscalculia.
  • Similarly, questions like "What colour is the sky?" can cause problems both for those with a literal turn of mind and for those who struggle with language.
  • Remember it's your job to determine if it's spam or not, not your user's.

The day concluded with Bruce asking for people to get involved with the WHAT-WG HTML5 work and share their opinion on two particular issues:

  • The table summary attribute is to be removed in HTML5, as in HTML4 it is little used and is only to be read out to screen readers. The alternative currently recommended by the working group is to summarise the table in the preceding content.
  • Another issue of concern is with the new HTML5 form controls. Currently they are not styleable with CSS, which means they will present as the host operating system defaults, which is good for consistency. On the other hand, if they're not styleable it's far more likely designers won't use them and will instead come up with their own non-standard controls, thus losing the semantic benefits.

If you have any opinions, please contact Bruce.

All in all another great day, 5 out of 5. Watch the website for news of future events in the series or follow #standardsnext on Twitter.

Technorati tags for this review:  

Tweet this!
Send feedback »PermalinkPermalink

02:46:50 am Permalink Adventures in Web 3.0: Part 3 - More CSS 3

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

I talked about CSS3 in the last post in this semi-regular series on the web standards of the future, but there are some new features supported in the latest Chrome release and Firefox alpha which make this worth a second post. This time I'm going to focus on background sizing, CSS gradients and RGBA colours.

To start with, scaling background images with the background-size rule. I started off with the example code from the MDC article on -moz-background-size and tried to make a background image that covers the entire page:

body {
    background-image: url('bg-image-1.jpg');
    background-size: 100% 100%;
    -moz-background-size: 100% 100%;           /* Gecko 1.9.2 (Firefox 3.6) */
    -o-background-size: 100% 100%;             /* Opera 9.5 */
    -webkit-background-size: 100% 100%;        /* Safari 3.0 */
    -khtml-background-size: 100% 100%;         /* Konqueror 3.5.4 */
    -moz-border-image: url('bg-image-1.jpg') 0;/* Gecko 1.9.1 (Firefox 3.5) */
}

This results in a page which looks like this:

Screenshot of scaled background image in Firefox

As you can see above, there is a way to support scaled backgrounds in Firefox 3.5 by using -moz-border-image. A while back I'd read a comment which indicated that border image ought to be able to achieve this sort of thing but, when I tried to understand the spec, I couldn't figure it out. The example above shows it's a lot less complex than I thought back then, unfortunately it doesn't work that well for this particular use case as the border-image inherits from body to html. This is not as weird as it might seem, there's specific discussion in the CSS spec of the inheritance relationship between the two - read the third and fourth paragraphs of this section. Unfortunately, you end up with a repeated background, even if you explicitly set the background and border images to none. The workaround for this, if you want to support Firefox 3.5, is to make sure there's no margins, padding or border on body in which case the repeated background will be covered up. The alternative, which I will follow for most of the rest of my examples, is not to worry about supporting Firefox 3.5.

A second problem is that the background image only covers the area taken up by the body, if your browser window is longer than the body then the image repeats down the page. For certain images this may be what you want, in this case I wanted it to cover the whole background. This is easy to fix by adding background-attachment: fixed; to the CSS to arrive at my second example. This is what it looks like in Firefox with that change:

Screenshot of scaled background image in Firefox

In Chromium, the scaled background image generally seems to be better quality - there is an image-rendering property but it didn't seem to make much difference.

Screenshot of scaled background image in Chromium

It also works in Opera 10, but only on Windows, and it doesn't scale to the full page height, and looks only marginally better than browsers with no background scaling:

Screenshot of scaled background image in Opera 10

The other problem with background-attachment: fixed; is, if your page is longer than a single screen, it noticeably impacts performance as you scroll up and down the page and the browser is forced to re-render everything.

So, having successfully scaled a background image across the entire page my thoughts turned to the page content, now almost unreadable. Since this is the sort of arty design which is all about the background image we don't want to cover it up completely, but we do want to provide enough contrast to read by, so some sort of semi-transparent background is in order. There are all sorts of ways to do this already, and several of them can be made to work across browser (and so would be the ones to use in any 'real' website, of course). But rather than have an alpha transparent PNG as a background, or use CSS transparency on the back one of a pair of nested elements, let's use RGBA colours to set a semi-transparent background colour:

h1, p {
    background-color: rgba(255,255,255,0.5);
}

This specifies values for red, green and blue respectively as numbers between 0 and 255 and then a number between 0 and 1 for the transparency. So bright red would be rgba(255,0,0,1). This does make the text a bit more readable while leaving the background visible:

Screenshot of RGBA backgrounds Firefox

But perhaps, in the interests of exploration, we should relax this pesky 'readable' requirement and see what other effects can be achieved with CSS 3. One interesting possibility is the new gradient property introduced by WebKit and now also supported in the next version of Firefox. This allows you to produce some pretty crazy effects without any images at all:

Screenshot of gradient backgrounds Firefox

The bottom paragraph is the one I started with and it's fairly straightforward, here's the code for it:

p {
    background-color: transparent;
    background-image: -moz-linear-gradient(top left, bottom left, from(rgba(255,255,255,0.9)), to(rgba(255,255,255,0)));
    background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(255,255,255,0.9)), to(rgba(255,255,255,0)));
}

Unfortunately there are two different syntaxes. In Firefox/Gecko the gradient type is part of the rule name - -moz-linear-gradient - whereas in WebKit the type is the first parameter (the alternative to linear is radial). There's no W3C spec at the moment, so it's possible neither option will be the same as the standard. I also found that Chromium didn't work too well with top left though I don't think the order should make any difference. In both cases, what is specified is a linear gradient, from top left to bottom left starting at white with 90% opacity, ending at white with 0% opacity (ie. transparent). Note that, because I was inheriting a background-color of 50% opacity white on the p elements, I had to override that in this rule to make the bottom of the gradient fully transparent. This could cause some problems in practical scenarios, as you may want there to be a background colour where there is no gradient support and the gradient otherwise. An approach which works in Firefox is to use a background property instead of background-image, Firefox 3.5 then displays the default inherited RGBA background and ignores the whole rule with the gradient:

background: -moz-linear-gradient(top left, bottom left, from(rgba(255,255,255,0.9)), to(rgba(255,255,255,0))) transparent;

Of course, you could achieve the gradient effect with a tiled PNG background image, with background-size you could even make it stretch to fill behind arbitrary content, so why would you bother? There are two reasons:

  1. There is no need to download an additional file from the server, so pages should load (slightly) faster
  2. The gradient is recalculated when the browser is zoomed, so it will always be smooth, no image resizing artefacts

So, now we're into the spirit of things, let's try something a little more complex. The next gradient I added a colour as well as a transparency and also tried to make at an angle by going from top left to bottom right:

p {
    background-image: -moz-linear-gradient(top left, bottom right, from(green), to(rgba(0,255,0,0)));
    background-image: -webkit-gradient(linear, left top, right bottom, from(green), to(rgba(0,255,0,0)));
}

As far as I could tell, this made no difference - the gradient still went straight across the image:

Screenshot of linear gradient from top left to bottom right Firefox

Since the browsers seem to be ignoring it anyway, I removed the top and bottom. In Firefox this made no difference, however in Chromium it stopped the gradient showing at all. So although you have to specify both directions in Chromium, it always ignores at least one of them. If two match then they will be ignored, if they're all different then it's not clear which way round your gradient will be - try it and see.

With CSS gradients you're not limited to heading smoothly from a single starting colour to a single ending colour, you can also visit any colour you want in between with a color-stop:

p {
    background-image: -moz-linear-gradient(left, right, from(rgba(255,0,0,0.8)), to(rgba(128,0,255,0.8)), color-stop(16%, rgba(255,165,0,0.7)), color-stop(32%, rgba(255,255,0,0.6)), color-stop(48%, rgba(0,128,0,0.5)), color-stop(60%, rgba(0,0,255,0.6)), color-stop(76%, rgba(75,0,130,0.7)));
    background-image: -webkit-gradient(linear, left top, right top, from(red), to(violet), color-stop(16%, rgba(255,165,0,0.7)), color-stop(32%, rgba(255,255,0,0.6)), color-stop(48%, rgba(0,128,0,0.5)), color-stop(60%, rgba(0,0,255,0.6)), color-stop(76%, rgba(75,0,130,0.7)));
}

This final example, which I adapted from the MDC page, paints a rainbow in the background. You can have an unlimited number of colour stops in your gradients, simply specify a percentage and a colour. If you specify 25% and blue then you gradient will pass through blue a quarter of the way along.

This post has been in gestation for over two months and I find myself well over my thousand word target for a post and only halfway through all the stuff I wanted to cover, so there will be at least one further post on CSS3. Having covered the basics of scaled backgrounds and gradients in this post, I'm aiming for some practical ways to use these features in web pages of the future.


Tweet this!
1 feedback »PermalinkPermalink

04/09/09

12:38:03 am Permalink Arbitrary Element Rotation in IE - the Matrix Filter

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

There was a post on WebDesign-L today asking about angled text, which reminded me of the excellent Text Rotation with CSS a few months back on snook.ca. Jonathan focussed on the IE only BasicImage filter to provide an alternative to the (also proprietary but future standard) -webkit-transform and -moz-transform properties to rotate text. That's fine as far as it goes, but BasicImage can only rotate in increments of 90. Jonathan mentions the alternative, the Matrix filter, but says "the coordinates still don't make any sense to me."

Now, WebKit and Gecko also support matrix transformations, so I'm thinking if I can only work out what the co-ordinates mean we might have the basis of a more general purpose solution. So I looked at the Wikipedia examples of linear transformation matrices and then the Mathamazement introduction linked to from the MDC page. If you can hear a loud whooshing sound right now, that's the echo of a load of math stuff flying completely over my head...

However, all was not lost - if we go back to the MSDN Matrix transform article you'll see there's some example code. With something to hack around I thought I had a much better chance of figuring out how things worked. I started off with the fourth sample, it uses Javascript to animate the Matrix transform, rotating and expanding a div element.

I modified the code a bit, but I'll take you through the key points before I show you what I finished up with. First of all, the Matrix transform needs to be defined on the element in question before you can script it:

<DIV ID="oDiv" STYLE="position:absolute;
filter:progid:DXImageTransform.Microsoft.Matrix(sizingMethod='auto expand')"
		onfilterchange="fnSpin(this)" >

The animation is powered by fnSpin which calls two subsidiary functions, fnResize to resize the image and fnSetRotation to rotate it. Here's the original code for the rotation:

//oObj input requires that a matrix filter be applied. 
//deg input defines the requested angle of rotation.
var deg2radians = Math.PI * 2 / 360;
function fnSetRotation(oObj, deg)
{    rad = deg * deg2radians ;
    costheta = Math.cos(rad);
    sintheta = Math.sin(rad);

    oObj.filters.item(0).M11 = costheta;
    oObj.filters.item(0).M12 = -sintheta;
    oObj.filters.item(0).M21 = sintheta;
    oObj.filters.item(0).M22 = costheta;

}

So here's it all nicely laid out with all the hard math stuff already done for us. The basic math stuff is it's converting the degrees into radians, then using sine and cosine functions to calculate the four matrix values. So now I'm thinking I can reverse engineer this function to work out what the matrix values will be for any angle. I started off with modifying the fnSetRotation so that the matrix values were visible on the page - adding four text inputs and these lines:

    document.getElementById("fM11").value = oObj.filters.item(0).M11;
    document.getElementById("fM12").value = oObj.filters.item(0).M12;
    document.getElementById("fM21").value = oObj.filters.item(0).M21;
    document.getElementById("fM22").value = oObj.filters.item(0).M22;

Then I added a button which rotates the element to 45 when clicked (warning, IE only):

Rotate element by 45 degrees in IE

The next step was to make the page work cross browser, accept a value for the input number of degrees and, for bonus credits, generate the relevant CSS for copy and pasting. First of all I cleaned up the output a bit with toFixed method as, when the values got close to zero, they end up in exponent format rather than just rounding to 0. This gave me numbers I could plug straight into a CSS template, for example here's the declaration to rotate an element by 45:

filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678);

So now I thought it would be a fairly straightforward task of plugging these values into the Mozilla format:

-moz-transform:  matrix(a, b, c, d, tx, ty)

The tx and ty are for translation, so I just set them to zero, then plugged M11, M12, M21 and M22 into a, b, c and d respectively. Unfortunately, it didn't work! The element was reflected in respect to IE in Firefox for certain rotations.

Someone who actually understands what's going on with the matrices could probably explain what's happening (probably I have the co-ordinate system the wrong way up?) but I fell back on trial and error and eventually decided that swapping b and c worked. See my final matrix calculator here - input an angle in degrees, click the button and see the CSS code for achieving it in IE, Gecko and WebKit.

Some things I noticed but didn't have time to investigate fully:

  • IE seems to rotate around the center, Firefox and Chrome seem to rotate from top left. There's a -moz-transform-origin and equivalent WebKit property to control things in those browsers, not sure what equivalents IE offers.
  • Other CSS declarations are applied after the transform in IE, while they seem to be applied before the transform in Firefox and Chrome (ie. if you add 200px padding to the top of an element, Firefox will rotate around a point 200px above the 'start' of the element, IE will apply 200px padding after the transform).
  • Using the rotate syntax in Gecko and WebKit is a lot simpler, but if you want to rotate stuff in IE too using a similar format in all three might be more simple in the long run? Especially if you want to script it.

Tweet this!
10 feedbacks »PermalinkPermalink

02/09/09

06:21:22 pm Permalink Rounded Corners for Image Elements in Firefox with SVG

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

In my post on CSS3 a few months back I mentioned some issues I had getting -moz-border-radius to clip content that it contained. After my writing the post the question came up a couple of times on stackoverflow, first from Brandon Wang and later a similar one from dougoftheabaci. Here is a simple example of the problem, the CSS is uncomplicated:

.target {
    border-radius: 20px;
    -moz-border-radius: 20px;
    -webkit-border-radius: 20px;
}

With that class applied direct to an img element it looks great in Safari and Chrome:

Example page in Chrome

But it doesn't work so well in Firefox:

Example page in Firefox

Today I came across the Applying SVG effects to HTML content article on the MDC wiki, one of the things it discusses is using SVG as a clipping mask for HTML elements. It occurred to me that it ought to be relatively straightforward to use a clipping mask to create the rounded corner effect directly on an img element in Firefox.

So I started off with the example code from the article, removed the circle, made the rectangle full size and used the rx and ry attributes to round the corners:

<svg:svg height="0">
    <svg:clipPath id="c1" clipPathUnits="objectBoundingBox">
        <svg:rect x="0" y="0" rx="0.05" ry="0.05" width="1" height="1"/>
    </svg:clipPath>
</svg:svg>

Then use a CSS class to apply it to my image:

.target { clip-path: url(#c1); }

It didn't work at first, but then I realised I'd created my document with a .html extension rather than .xhtml - to allow mixing of SVG into XHTML the document must have content type application/xhtml+xml. Once I fixed this the effect was exactly as I'd hoped:

Example SVG page in Firefox

Here is the full code. Of course, embedding it all this way isn't going to work for any browser other than Firefox 3.5, and serving application/xhtml+xml is going to break Internet Explorer, so it's not really a practical solution in it's current state. It's more useful to break the content into separate files, then the SVG can be served as image/svg+xml while your HTML is text/html. This final example works across browsers and will round the corners of the image in Chrome, Safari and Firefox.


Tweet this!
5 feedbacks »PermalinkPermalink