boogdesign blog

Web design, web development, standards compliance, Linux, events I went to related to that, and random things I found on the internet.

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

14/02/10

12:26:55 am Permalink Links for February 14th

Categories: Delicious

Tweet this!
Send feedback »PermalinkPermalink

12/02/10

03:04:05 am Permalink Real World CSS 3

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

I've done a number of posts recently on new features coming in CSS level 3. These posts have mostly been based on features available in the version fours of Safari and Chrome and the Firefox 3.6 release so, while they may be useful if you're producing an iPhone app, they don't seem like they'll be much use on general purpose websites where IE users need to be considered. In this post I'm going to look at how these new CSS features can be made to work, or at least degrade gracefully, in older browsers, including Internet Explorer. I'm going to extend the example from my earlier post on scaling background images and gradients to see what's possible.

So my scaled background image looks OK in Firefox 3.6:

Screenshot of perfectly scaled background image

But it looks a bit crappy in Firefox 3.5, not to mention any other browser which doesn't support background-size:

Screenshot of background image tiling inappropriately

There are going to be some cases where there's nothing you can do, for instance if you want some page elements to be in position over bits of the background, and will just need to take another approach (like putting the image in the page and using a negative z-index). However, in my case, I think that if users can't be treated to a nice full screen photo of palm trees then a tiling 'leafy' image would be an acceptable substitute without ruining the ambience. In order to provide one background image to browser which support sizing and another to those that don't I'm going to make use of another CSS3 feature, multiple background images. In CSS3 compatible browsers you can just provide multiple images in a comma separated list:

background-image: url('1-rhus-typhena-leaf-tile.jpg'), url('bg-image-1.jpg');

All the other background rules accept a similar comma separated list, including background-size. The nice thing about this is the stacking order of the images is defined in the spec:

The first image in the list is the layer closest to the user, the next one is painted behind the first, and so on. The background color, if present, is painted below all of the other layers.

So I put the tiling image 'closest to the user' then in my background-size set it to be zero size. Browsers which support background-size make that image disappear and show the scaled image behind it, those that don't show the tiling image:

background-size: 0% 0%, 100% 100%;
-moz-background-size: 0% 0%, 100% 100%;           /* Gecko 1.9.2 (Firefox 3.6) */
-o-background-size: 0% 0%, 100% 100%;             /* Opera 9.5 */
-webkit-background-size: 0% 0%, 100% 100%;        /* Safari 3.0 */
-khtml-background-size: 0% 0%, 100% 100%;         /* Konqueror 3.5.4 */

Note, the image doesn't actually disappear in WebKit, but if you set background-repeat: no-repeat it's very hard to spot. Opera 10.10 supports background-size (on Windows, anyway) but not multiple background images, which is unfortunate, but things work well on Opera 10.50. So now all we have to worry about is those browsers which don't support background-size or multiple background images. This is easy enough, as they should ignore all the rules they don't understand, so we just need to precede all of the above with a single background-image rule

background-image: url('1-rhus-typhena-leaf-tile.jpg');

Now each browser displays a background image according to their abilities, here's Firefox 3.5 after the fix:

Screenshot of background image tiling with multiple background hack

With one further tweak, we can support IE too. The issue with IE is that it parses the multiple background images even though it doesn't understand them, treating them as a single, invalid background image. For this I resort to IE conditional comments:

<!--[if IE]>
<style type="text/css">
body {
    background-image: url('1-rhus-typhena-leaf-tile.jpg');
}
</style>
<![endif]-->

Screenshot of background image tiling in IE8

Something still needs to be done about the menu examples; to refresh your memory, the first menu example used a single 'button' background image:

Links with scaled background image

This is amenable to the same multiple background hack. This time I used a one pixel wide slice of the button image and repeated it across the background:

background: url('bg-image-3.png') repeat-x;
background: url('bg-image-3.png') no-repeat, url('bg-image-2.png') no-repeat;   /* Image courtesy of http://blog.entropiads.com/2009/01/29/free-3-d-glossy-button-icons/ */
background-size: 0 0, 100% 100%;
-moz-background-size: 0 0, 100% 100%;           /* Gecko 1.9.2 (Firefox 3.6) */
-o-background-size: 0 0, 100% 100%;             /* Opera 9.5 */
-webkit-background-size: 0% 0%, 100% 100%;        /* Safari 3.0 */
-khtml-background-size: 0% 0%, 100% 100%;         /* Konqueror 3.5.4 */

Add some rounded corners and you end up with a reasonable approximation of the original buttons in Firefox 3.5:

Links with tiled background image

The next set of buttons all used gradient backgrounds:

Links with CSS gradient background

I'm just going to look at the first and the last one of these, as all the interesting bits will get covered in these two cases. One thing worth noting at this point - the syntax for specifying gradients has changed significantly in Firefox (and the standard) since the last time I discussed them. It's actually now a lot simpler. Old way:

background-image: -moz-linear-gradient(top, bottom, from(#090), to(#060), color-stop(25%, #cfc));

New way:

background-image: -moz-linear-gradient(top, #090, #cfc 25%, #060);

As you can see, the from, to and color-stop tokens have been removed and now, instead of stating the start and end colours and then any steps in between after that, the colours are now in the order they'll appear. The percentage value is now optional, if you don't specify it then the colour stops will be evenly distributed.

Because this example involves no transparency, supporting browsers which don't understand gradients is easy - just provide a background colour:

background-color: #080;
background-image: -moz-linear-gradient(top, #090, #cfc 25%, #060);
background-image: -webkit-gradient(linear, left top, left bottom, from(#090), to(#060), color-stop(25%, #cfc));

And (for a bit of variety), here's what it looks like in Opera 10.50 Alpha (on Linux):

Links with fallback solid background

You might settle for that in Internet Explorer, but you don't need to! IE has supported gradients since 5.5 thanks to the gradient filter. Here's a simple lighter to darker green gradient in IE8 CSS syntax:

-ms-filter: "progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr=#FF009900, endColorstr=#FF006600)";

And this is what it looks like in Internet Explorer 8:

Links in IE with CSS gradient background

While you sit there flabbergasted that, once again, IE seems to have been ahead all along in the race to snazzy CSS3 effects, there are a couple of caveats. First off, like all IE filters, underlying this is an ActiveX control, so expect strange issues related to stacking, clicking and (possibly) problems due to the security settings of extremely paranoid Windows admins. Secondly, you can't specify anything other than a flat gradient, there is no equivalent to colour stops. Finally, unlike the 'true' CSS gradients in Firefox and Safari, a filter in IE applies to the entire element instead of just a single property. So while in Firefox you can happily use a gradient in the background-image property and also specify a separate box-shadow property, in IE you have to use all the filters on a single -ms-filter property; this may not be a problem for you, but I've found that combining more than one filter of a different type on a single element can lead to some rather strange results, more on this below.

In my final example in my earlier post, I tried to do some no Image Aqua Buttons without adding additional markup to my fake menu. You may recall one of the issues I had was simulating the 'glare' with a radial gradient because there wasn't a way to make it anything other than round. In the new gradient syntax supported by Firefox, there is now a way to change the shape of the radial gradient:

background-image: -moz-radial-gradient(center 25%, ellipse farthest-side, rgba(255, 255, 255, 0.7), rgba(255, 255, 255, 0.1) 50%, rgba(255, 255, 255, 0));

You can now specify a shape, circle or ellipse, as well as a number of different 'size constants' - farthest-side in my example above. This allows a lot more flexibility for the radial gradients. Compare the orginal version:

Sort of Aqua buttons with no extra markup

With the new 'ellipse farthest-side' version:

Sort of Aqua buttons now with ellipsoidal glare

Yes, I know, the difference is subtle &amp;#58;&amp;#41;

As I alluded to above, the main issue with these buttons is that we want them to be semi-transparent. Apart from IE, it's been a while since any other major browser didn't support RGBA colour - Opera 9.64 didn't support it, but Firefox 3.0 did. As long as a non-transparent colour is an acceptable fallback we can just rely on normal CSS precedence and specify two background colours:

background-color: rgb(60, 132, 198);
background-color: rgba(60, 132, 198, 0.8);

If you want a completely transparent background in the case where gradients are supported and a coloured background otherwise, you can specify everything in two background rules instead, browsers should ignore the rules they don't understand.:

background: rgb(60, 132, 198);
background: -moz-linear-gradient(left, rgba(28, 91, 155, 0.8), rgba(108, 191, 255, 0.9)) transparent;

Once again for IE we turn to the -ms-filter property. In the earlier gradient example you will have seen startColorstr=#FF009900 - the alpha value is that first hexadecimal pair (the rest make up a standard hex colour declaration), if you set it to something less than FF the colour will be partly transparent. Since I have two elements to use, the li and the a within it, I will attach a gradient filter to both:

div#nav2 ul li {
    -ms-filter: "progid:DXImageTransform.Microsoft.gradient(GradientType=1, startColorstr=#CC1C5B9B, endColorstr=#E56CBFFF)";
}
div#nav2 ul li a {
    -ms-filter: "progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr=#88FFFFFF, endColorstr=#00FFFFFF)";
}

The GradientType is 1 for horizontal and 0 for vertical, so the first declaration is a relatively solid dark blue to light blue horizontal gradient and the second declaration is a white to transparent vertical gradient. Finally in IE, because the -ms-filter property is stand-alone, the normal background colour has to be turned off in conditional comments:

<!--[if IE]>
<style type="text/css">
h1, div#nav1 ul li, div#nav2 ul li, div#nav2 ul li a {
    background-color: transparent;
}
</style>
<![endif]-->

This produces some acceptably 'glassy' buttons:

Sort of Aqua buttons in IE 8

In Gecko and WebKit there is also text and box shadow, these can also be emulated by -ms-filter in IE8. It is possible to tack multiple filters on to the declaration like this:

div#nav2 ul li {
    -ms-filter: "progid:DXImageTransform.Microsoft.gradient(GradientType=1, startColorstr=#CC1C5B9B, endColorstr=#E56CBFFF) progid:DXImageTransform.Microsoft.Shadow(color=#3399EE,direction=180,strength=10)";
}
div#nav2 ul li a {
    -ms-filter: "progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr=#88FFFFFF, endColorstr=#00FFFFFF) progid:DXImageTransform.Microsoft.Shadow(color=#3399EE,direction=180,strength=10)";
}

The filters are applied in the order they appear in the rule. However, as I alluded to above, this doesn't always have the effect you might expect, here's the result of the above rules:

IE 8 multiple filter fail

Not very useful! You may have better luck mixing other filters, or applying multiple filters of the same type, but in general I would recommend a one filter per element approach. In this case, I think the gradient is more important than the shadow for the general feel, so I'll stick with that.

So now the final 'compatible' version of my example page is ready. For some side by side comparisons, here it is at it's best in Firefox 3.6:

CSS3 Backgrounds example page in Firefox 3.6

This is the same page in Internet Explorer 8:

CSS3 Backgrounds example page in IE 8

And this is the same page again in the legacy Opera 9.64:

CSS3 Backgrounds example page in Firefox 3.6

As you can see, the pages are by no means identical in every browser, but each is displaying the page according to its capabilities, with no need for Javascript hacks and only a little CSS trickery. So, if you are willing to accept that less capable browsers will show less stylish pages (and are willing to write a few redundant CSS rules), it is possible to use several CSS3 features on websites today.


Tweet this!
Send feedback »PermalinkPermalink

07/02/10

02:24:49 am Permalink Links for February 7th

Categories: Delicious

Tweet this!
Send feedback »PermalinkPermalink

31/01/10

12:32:20 am Permalink Links for January 31st

Categories: Delicious

Tweet this!
Send feedback »PermalinkPermalink

24/01/10

12:19:28 am Permalink Links for January 24th

Categories: Delicious

Tweet this!
Send feedback »PermalinkPermalink

19/01/10

11:56:15 pm Permalink London Web Standards: Web Fonts with Ben Weiner

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

Review: LWS January: Web Fonts with Ben Weiner at The Square Pig, 30 - 32 Procter Street, Holborn, London, WC1V 6NX 19:00 to 20:30

I've been experimenting a bit with @font-face recently so I was intrigued when I heard about this talk. It was booked out within hours of announcement but fortunately (for me) a few folk couldn't make it and the people on the waiting list got to attend.

Jeff has already done a 'live blog' of the talk, and there's a full transcript on Ben's site, so I'll just give a brief and slightly out of order outline and concentrate on the bits I found interesting.

Ben is a typography geek who got into web design so he had a good understanding of both the typographical world and the history of web fonts. This he discussed for the first third of the talk - explaining what a font is, why font design is difficult, why typography is important and why, more than twelve years after Microsoft first brought web fonts into the world with IE4 and EOT, we might finally have a chance at a solution that works for users, designers and the font foundries. One of the interesting aspects he discussed here was ligatures - where two letters, when placed consecutively, are melded into a single symbol. This happens in English fonts for things like 'ff' and 'fi', although the individual letter shapes remain, but the effect is even more marked in Arabic scripts where the combined character looks significantly different to the two (or more) which it represents. Having to deal with all this sort of stuff is why font design is so difficult, why even the 'open source' fonts have mostly been paid for (one way or another) and why font foundries have been generally paranoid about the possibility of all their hard work being stolen as soon as it's uploaded on to the internet.

Although most of the excited noises about web fonts are coming from designers, there are a few reasons why they're important. Firstly, while the font support for English and other languages based on the Roman alphabet is good, there are others where it's not so good and some (relatively popular) languages which have no font support at all in most operating systems (Telugu, a language of the Indian subcontinent, has 74 million speakers but no support in Windows). In this situation many sites have resorted to delivering their textual content as images. Delivering textual content as images is also an issue for accessibility as many designers, desperate to use their fonts of choice, resort to image replacement techniques which, if done badly, can result in poor accessibility.

This leads neatly in to Ben's discussion of the various hacks people have used because of the lack of working, cross browser web fonts. In order from the stupidest to the cleverist:

  • Image replacement - Basically, write your text in Photoshop and save it as an image, then put it in your page. An accessibility nightmare, particularly if the designer 'forgets' to provide the alt content.
  • Fahrner image replacement - In this technique the normal text is left in the HTML and the 'rendered' font is put in a background image. CSS is then used to move the normal text out of the viewport, leaving only the background image. Less stupid than straight image replacement, but still not perfect - no support for text resizing and you have to generate all your images in advance.
  • sIFR - Moving on to the clever hacks, sIFR works by embedding your font into a Flash movie then using Javascript to replace the headings dynamically. This was the first hack to be CMS-friendly - the text to be displayed is a run time parameter, but it introduced the additional requirements of JS and Flash.
  • Cufón - Getting to the first of the really clever hacks, Cufón uses a generator to convert your font into a set of JSON encoded outlines and then uses canvas to render it in the page.
  • Typeface.js - The cleverest of all, by making use of a server side component with access to the Freetype library, and then applying according to your existing CSS.

While these libraries get the job done, they do have a number of drawbacks - sIFR's use of Flash, Cufón's requirement to specify your fonts outside of CSS, the way it splits the words up into separate elements for each letter, and the general dependence on Javascript. They also have some drawbacks on the typography front, particularly to do with ligatures and letters that change shapes in different contexts - Ben showed us a number of example slides which you can check out on his site. Also, none of the use 'real fonts' - the same things that any other application would recognise as a font file.

We moved on to web fonts and the @font-face rule. Here is what it looks like:

@font-face {
	font-family: 'CantarellRegular';
	src: url('Cantarell-Regular.eot');
	src: local('Cantarell Regular'), 
		url('Cantarell-Regular.ttf') format('truetype');
}
You can then reference your downloaded font like this:
p { font-family: "CantarellRegular";}

All relatively straightforward, this will work in recent versions of all the major browsers - a standards compliant way to render actual fonts of your own choosing, with no need for any scripting or third party plugins, taking full advantage of typesetting capabilities already available within browsers and operating systems. Of course it's not quite that straightforward, there is some server side setup to consider, and then the ideological and technical hurdles that still need to be overcome before this all becomes practical for mainstream sites.

To deal with the idealogical problem first - font foundries are still not playing ball. This is a problem because, unlike music, a font is software rather than data and gets the same protections, also, as should be clear from some of the difficulties described above, good font design is difficult and so professional designers realise it is worth paying for a good font. So, even though the technology and standards are now getting in to place, font foundries are still unwilling to license 'desktop' fonts for distribution with websites.

And it's not like there are no practical problems. First you've got to consider what adding a few fonts to the mix is going to do to your bandwidth requirements. Regular desktop fonts, with just normal, bold, italic and bold/italic options, exceed 100k in size, especially if they include a full unicode character set. A font from a foundry, which is likely to have many more variations (extra heavy, expanded, smallcaps etc.) can be up to 1Gb in size. This gives you another thing to think about - what will the user see while waiting for the font to download? In Firefox they'll see the page rendered in whatever the default font is - this is likely to have a different geometry to the font you're delivering, so the page will have to be reflowed when the font arrives. This causes usability difficulties as elements users have started interacting with suddenly move around. In Safari the user will see nothing until the entire font is downloaded, making it impractical to use a large font for body text. This is the flash of unstyled text problem. You might be able to subset the font to reduce download times, but then you need a font with a permissive license, which leaves you back at the idealogical roadblock outlined above. You might have the idea of a single repository for web fonts to increase the chance users already have the font you want to use, similar to Google's Ajax library (and you wouldn't be the first), or even just to share a font across multiple domains in a portfolio. In this case you've got to set up Cross-Origin Resource Sharing for Firefox.

Although @font-face itself has wide support there are some differences in the details when it comes to defining families of fonts. Firefox seems to do pretty well and Safari/Chrome behave similarly, there are some issues that crop up in Opera and Konqueror, but most of the problems occur in IE. Here is how you declare a font family according to the spec:

@font-face {
    font-family: "DejaVu Serif";
    src: url("/fonts/DejaVuSerif.ttf") format("TrueType");
    font-weight: 400;
    font-style: normal;
}
@font-face {
    font-family: "DejaVu Serif";
    src: url("/fonts/DejaVuSerif-Italic.ttf") format("TrueType");
    font-weight: 400;
    font-style: italic;
}
@font-face {
    font-family: "DejaVu Serif";
    src: url("/fonts/DejaVuSerif-Bold.ttf") format("TrueType");
    font-weight: 700;
    font-style: normal;
}
@font-face {
    font-family: "DejaVu Serif";
    src: url("/fonts/DejaVuSerif-BoldItalic.ttf") format("TrueType");
    font-weight: 700;
    font-style: italic;
}
Each different weight and style has it's own definition and associated font file - multiple font files can be listed and the browser should pick the first format it can handle. However, of the above, this is all IE understands:
@font-face {
    font-family: "DejaVu Serif";
    src: url("/fonts/DejaVuSerif.ttf");
}
@font-face {
    font-family: "DejaVu Serif";
    src: url("/fonts/DejaVuSerif-Italic.ttf");
}
@font-face {
    font-family: "DejaVu Serif";
    src: url("/fonts/DejaVuSerif-Bold.ttf");
}
@font-face {
    font-family: "DejaVu Serif";
    src: url("/fonts/DejaVuSerif-BoldItalic.ttf");
}

Internet Explorer ignores all the font-weight and font-style rules so essentially all that happens (leaving aside the issue of file format) is that DejaVu Serif gets redefined repeatedly. A common work around is to define each font style explicitly in it's own font family, but this is hardly ideal.

In the final part of his talk Ben moved on to WOFF (Web Open Font Format) - the new standard which could finally get the font foundries behind web fonts. It was initially worked on by Erik van Blokland and Tel Leming, two guys well respected in the world of type, then worked on by Jonathan Kew and John Daggett of Mozilla, two guys with a lot of respect in the web browser world - so it was able to gain a lot of traction in both areas very quickly. So the future looks good, in the meantime there are a number of startups and other websites looking to exploit the demand for web fonts in TTF and EOT format:

This was a very useful talk on what is a hot topic in the web design world right now, I was particularly interested to learn about some of the history behind web fonts and some of the issues surrounding support of non latin languages, so 5 out of 5.
Technorati tags for this review:      

Tweet this!
1 feedback »PermalinkPermalink

17/01/10

03:19:12 am Permalink Links for January 17th

Categories: Delicious

Tweet this!
Send feedback »PermalinkPermalink