Entries tagged “css3.”

Happier IE fallbacks with CSS, LESS and conditional comments

Nobody likes writing CSS fallbacks. They’re a speed bump in your creative flow. Here’s how I use a couple different techniques to simplify the process

This assumes that you’re using conditional comments on the html tag to define classes for certain versions of IE. This technique was originally proposed by Paul Irish and refined in the HTML5 Boilerplate to something like this:

<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="en"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="en"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="en"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en"> <!--<![endif]-->

You can omit the “no-js” class if you aren’t using Modernizr, and feel free to remove or tweak the conditional comments to suit the versions of IE that actually require fixes (I recommend referring to this Quirksmode post for examples).

With this markup is in place, you can conveniently target styles to specific versions of IE. For example, let’s say I’m running into a box model bug in IE7 that’s resulting in a div not having the correct amount of top margin. Thanks to the classes I’ve applied using conditional comments, I can apply extra margin only for that browser version and below.

.example { margin-top: 24px; }
.lt-ie8 .example { margin-top: 48px; }

Voila! .example will have extra margin to account for the bug in IE7 and below without impacting any other browsers.

Vanilla CSS works well for a simple, top-level item like that, but it can get a bit hairy when you try to apply similar fixes with particularly deep inheritance. An example:

.l-container.example.s-active .button {
    background-color: #00ccff;
    display: block;
    line-height: 42px;
}
.lt-ie8 .l-container.example.s-active .button {
    height: 42px;
}

Yeesh… that’s pretty verbose! Here’s where the beauty of LESS comes in handy, particularly its support for scoped variables, nested rules and the ampersand combinator:

.l-container.example.s-active .button {
    @height: 42px;
    background-color: #00ccff;
    display: block;
    line-height: @height;
    .lt-ie8 & {
        height: @height;
    }
}

Occurrences of @height will be replaced with 42px in the compiled CSS. The ampersand in the nested selector will be replaced by the parent selector. This will compile to exactly the same as the previous example, but with a lot less redundant typing.

That’s all well and good for one-off bug fixes, but what about recurring fixes that need to be applied on a case-by-case basis? That’s where the power of parametric mixins comes in handy.

Here’s an example of a mixin we can use to support transparency in old IE syntax and standard syntax. Note that because IE’s filter property does not use standard CSS syntax, it can throw off the LESS parser, so we use a leading tilde (essentially the LESS equivalent of eval) and string interpolation to render the rule:

.opacity(@amount) {
    opacity: @amount;
    .lt-ie9 & {
        @ieop: @amount * 100;
        filter: ~"alpha(opacity=@{ieop})";
    }
}

.example { .opacity(0.5); }

Which will compile to:

.example { opacity: 0.5; }
.lt-ie9 .example { filter: alpha(opacity=50); }

Here’s another example for supporting inline-block in IE7 and below:

.inline-block() {
    display: inline-block;
    .lt-ie8 & {
        display: inline;
        zoom: 1;
    }
}

.example { .inline-block(); }

Compiled:

.example { display: inline-block; }
.lt-ie8 .example {
    display: inline;
    zoom: 1;
}

Like The Force, nested rules can be used for good or for evil. When working with this sort of shorthand it can get a little too easy to overuse mixins or forget to combine selectors to insure your compiled CSS is still fairly lean. Refer to this entry for more on that very topic.

Surf by Osmosis, a 10K Web App

This week I submitted an entry to 10K Apart, a contest sponsored by the fine folks at MIX and An Event Apart challenging web designers and developers to craft an HTML5-based application under 10 kilobytes in total file size (minus a few forgiven resources like jQuery and Typekit). Entries must be compatible with Firefox, either Safari or Chrome, and the Internet Explorer 9 Developer Preview, but thankfully not IE8 or below.

My entry, titled Surf by Osmosis, shows you the latest top content from Digg, Google News, Twitter and YouTube in as little as a minute, allowing you to absorb today’s trends quickly so you can get on with your life. You can view and comment on my entry on its 10K Apart page.

I took this contest as an opportunity to tackle a few challenges I hadn’t yet mastered, specifically:

  • Quickly fetching feeds. I already do a lot of JavaScript feed-fetching on Portwiture and TweetPlus, but this one had to get the lead out.
  • Time-sensitive events. For some reason, intervals and timeouts have always felt unintuitive for me to develop.
  • Drawing with the canvas element.
Originally I struggled with normalizing the way data was retrieved from the four disparate services, until I realized I could use the speedy and versatile Google AJAX Feed API to grab all of them. This minimized my reliance on outside APIs while leveraging Google’s relative lack of down-time to achieve a speedier experience.

Time-sensitive events turned out to be much less frightening than I thought they would be, at least until I combined them with the initially perplexing canvas drawing methods. Thankfully, the Mozilla Developer Community offers an amazingly helpful animated clock demo I was able to reference and simplify.

Surf by Osmosis went through a few design iterations before I settled on the current look. Unlike most of my projects, I didn’t start in a sketchbook or Photoshop. Due to the technical constraints, I felt my usual design tools would only invite more complexity, and thus more file size.

The original layout was inspired by the simplicity of my friend and colleague Chris Kalani, but the open, fluid composition was more complex to style and animate. Additionally, the lack of a container made the transition between each step feel too jarring and dramatic.

The second iteration was at one time considered “finished.” The fixed container made transitions more predictable and defined a focal point for the viewer, and the multi-layered look of it gave me plenty of opportunities to play with CSS3 gradients and shadows. Much to my dismay, the verbose CSS3 gradient syntax (duplicated for both Mozilla and Webkit compatibility) coupled with the extra logic needed to craft a dimensional animated clock pushed the file size a few kilobytes over the limit, forcing me to simplify.

As is often the case, these technical limitations pushed me to focus my design. In lieu of fancy-shmancy effects, I was now forced to rely on color and typography (specifically FF Cocon Web Pro) to inject Osmosis with personality, and I firmly believe that the end product is better for it. Lesson learned!

Voting appears to be closed as of today. I’m honored to have received an average rating of 4.06 (out of 5) stars with a total of 396 votes, my sincerest thanks to everyone who voted. I’ve already received many wonderful suggestions for how I could expand the application once the contest has ended. If you’d like to see Surf by Osmosis revised and built upon, please let me know.

If you’re curious, my favorite competing entries are probably the addictive canvas game Sinuous and the dead-simple-yet-attractive Inspired By.

HTML5 and CSS3 for the sake of tomfoolery

One of the biggest disappointments I continually encounter when teaching web design is losing students to rich media plugins, most commonly Flash. These closed, proprietary sirens singing talented designers and developers out to sea rob the Semantic Web of some truly creative minds.

Students often look at the Web and see a minefield of limitations. Several times I’ve approached students with stellar HTML/CSS/JavaScript-based work to ask about their career plans, only to hear “I’d rather pursue Flash work.” No matter how many times I offer tomorrow, many students are only interested in now.

I evangelize the Semantic Web clearly and passionately in my lectures, but arguments of principal, search engine optimization and accessibility often flounder in view of visually-engaging, rich web media. There is a fine line between designer and artist; in order to appeal to these minds, we must impress them on a more visceral level.

Given time, I think HTML5 and CSS3 are up to the task. My arsenal of compelling examples has been growing exponentially.

Mouse over the DVD cases when viewing For A Beautiful Web in Safari 4 and you’ll encounter some gorgeous and purposeful rotation-based animation that degrades gracefully for less-abled browsers.

In Mac OS X Snow Leopard, Guillermo Esteves has recreated the Star Wars Episode IV marquee for Webkit users (perspective and all).

Firefox 3.6 introduces support for the File API, making drag-and-drop file selection possible (thereby trumping Flash’s previously-superior selection capability).

Webkit users who opt-in to bleeding edge features can now experience YouTube and Vimeo sans Flash players using only HTML5′s built-in media support. The result is stunningly indistinguishable from Flash video playback.

These examples may appear to be small victories, but their importance cannot be overstated. We are watching the capabilities of HTML and CSS progress more rapidly (and with farther-reaching effect) than their rich media cousins. In a Web where the capabilities of Flash and HTML are roughly equivalent (or perhaps even lopsided), the choice will be abundantly clear.

Address all audiences via the Semantic Web, or keep playing in your sandbox. Which sounds more fulfilling to you?