jQuery plugin to add a CSS class to last-child DOM elements

This has been bugging me for ages. IE < 9 does not support the CSS3 last-child pseudo class. I’ve created a _very_ simple jQuery plugin to add a CSS class “last-child” to the element that is the last child of a DOM element.

It performs this recursively, so it’ll apply the class to the last child of an element as well as to the last child of all it’s children…and so on and so forth.

It’ll perform this on each of the set of matched elements in a jQuery object. So you can have it traverse the whole, of your page by providing a jQuery object with the <body> element in it, or you can pick and choose DOM elements to apply the plugin to for efficiency. For instance, you might only need the "last-child" class to be applied to the last child of an unordered or ordered list:

    $('body').lastChild(); // Applies to all elements attached to the document.body
    $('ul, ol').lastChild(); // Applies to all elements in an unordered or ordered list

By default, the plugin applies the CSS class to a restricted set of DOM element types. You can specify the types of DOM elements to apply the class to by passing an options object to the function. In this way you can also specify the name of the CSS class that will be applied:

    $('ul, ol').lastChild({
        tags:['li'], // Only elements with the tag name 'li' will have the class applied to them
        cssClass:'ie-last-child' // The CSS class name will be 'ie-last-child'
    });

For super shorthand, you can simply pass a string to the lastChild function – which it presumes to be the CSS class you want to use:

    $('ul, ol').lastChild('ie-last-child');

You can download the plugin here.

Note, while I created this plugin to get around my IE problem, it is not built specifically for IE. If you only want IE to receive these classes, you’ll probably want to do something like:

    if($.browser.msie) {
        $('body').lastChild();
    }

…but obviously preferably using Modernizr:

    if($('.ie6, .ie7, .ie8').length) {
        $('body').lastChild();
    }

Enjoy!

Website design refresh

It has been nearly 3 years since I first launched the freestyle developments website and it was long overdue for a design and code refresh. Today I finally relaunched the site.

For me, the biggest change has been to move to a HTML5 doctype. The site now utilises many of the new HTML5 tags, such as header, footer, nav, section, article, aside and time as well as some of the new HTML5 forms attributes. Many thanks goes to @rem and @brucel for their fantastic HTML5 book, which I gleaned a lot of useful information from.

I’ve also given it a bit of a visual refresh, to use some CSS3 properties that I’m now regularly using on sites I build: drop shadows, rounded corners – that sort of eye candy. It means that my CSS no longer validates with no errors, but I’m hoping people in the know will be able to see past the vendor specific CSS property prefix errors e.g. “-moz-”, “-webkit-”.

I’ve gone for a Jello Mold layout to give me the flexibility of a fluid layout within parameters I control. I love fluid layouts, but their biggest enemy is widescreen displays, which makes reading text difficult due to the long line lengths, which is minus points for accessibility.

Assuming your default font size is 16px, my site is fluid between 700px and 1280px. Outside of these browser widths the site is rigid. It means that the site never gets so small that the content is unreadable, and never become so wide that the line width is a hindrance to legibility. Another nice thing about the Jello Mold is that between the max and min, the site re-sizes itself in an organic way, which really has to be experienced to be appreciated (give it a go now, go on).

I’ve also updated my CSS to use the YUI reset sylesheet. I don’t agree with absolutely everything that YUI are doing with their CSS stylesheets, but they have some really interesting ideas and valid points. Either way, it is nice to have part of my styles coming off a CDN and is a bit more up to date than the reset I used to use.

In accordance with my post on the EM unit and browser zoom, I’ve updated my stylesheets and removed all references to pixels in favor of EM’s like I have been doing with all my new website builds for a while now. I don’t set a font size for any of my pages html or body elements, allowing the user to choose the size of my website by setting their default font size for their browser, which is 16px for most browsers.

Anyway, I think that is all I have to say for now. Enjoy the new site and all the interesting tech that comes with it. If this all sounds good to you, and you’re looking for a freelancer like me. Get in touch.

Update: Hardware accelerated alternative to jQuery animate() top, left, width, height and opacity CSS properties for iPhone/iPad

Update to my post here – I’ve tweaked the script to use CSS3 transitions on Firefox 4+ and Opera 10.50+ as well as modern webkit based browsers such as Chrome and Safari.

The CSS3 transforms and transitions enhanced carousel can be found here:
freestyle-developments.co.uk/demo/public/portsurf/?css3

…and the normal carousel:
freestyle-developments.co.uk/demo/public/portsurf/

Source code for CSS3 transforms and transitions enhanced carousel

N.B. The normal carousel works in IE7 and IE9 beta, but not in IE8 (it seems IE8 can’t figure out the dimensions of DOM elements properly).

Hardware accelerated alternative to jQuery animate() top, left, width, height and opacity CSS properties for iPhone/iPad

I was recently asked to quote for a proof of concept HTML5 alternative to a flash carousel, specifically to run on iPad. I said I’d do it, but the agency later decided that others had tried to create a HTML5 version and had not been able to create a version that performed well enough for the client. From my point of view they were under the impression I couldn’t do any better. So naturally, I spent a few hours of my spare time proving this wrong, just for the fun of it.

Step 1 was to build a version of the carousel in HTML5. I chose to use the jQuery framework because…well, I felt like it. The fruits of my labour are here:

http://freestyle-developments.co.uk/demo/public/portsurf/

Now, you can view this on any browser. All that is happening is that there are a set of list items absolutely positioned in a container, when you click/touch an item on the left/right jQuery animates the top, left, width, height and opacity CSS values for each item.

Fantastic, but, it feels really sluggish on iPad and iPhone 4. Go on, try it out.

Fair enough, they are resource constrained devices. What to do though? I’ve already used all the tricks I could think of fast loops, select operation caching etc. etc. So what now?

Luckily, in iOS, transitions and animations of the -webkit-transform and opacity properties are performance-enhanced. Sweet! These correspond exactly to the two CSS properties I’m trying to manipulate for each item in my carousel. Implementation was a simple case of swapping out the jQuery animate function, for the css function. Passing in the webkit transition, webkit transform and opacity values in its place.

For example:

items[itemIndex - 3].css({
	opacity:1,
	'-webkit-transform':'translate3d(' + carousel.itemPosition.medium.left.x 
            + 'px, ' + carousel.itemPosition.medium.left.y + 'px, 0) scale(0.5)',
	'-webkit-transition':'opacity 0.4s linear, -webkit-transform 0.4s linear'
});

The webkit transition property is saying “transition these CSS properties from what they were previously to their new values, using these transition parameters (0.4s linear)”. The webkit transform property is saying “move this element to the following coordinates, and scale it by a factor of 0.5″.

Check out the hardware accelerated version on your iPad/iPhone and compare it with the other:

http://freestyle-developments.co.uk/demo/public/portsurf/?ha=1 (Note: webkit only)

Here is a video demonstrating the performance differences those of you without iPads.