css3-animations1

Quick Tip: CSS3 Transition End Event

If you’re working with CSS3 transforms and transitions, you detect the completion of an animation with the vendorTransitionEnd event.

So in Chrome and Safari:

document.addEventListener('webkitTransitionEnd', function(e) {
    console.log(e);
}, false);

will log the event object to the console. Opera uses oTransitionEnd, and Firefox just uses transitionend (note the lack of camel case for this one).

If you have multiple animations on multiple elements, you need to be able to tell which element has finished animating, and at what time.  You could either bind your event listener to each element respectively (which might get a bit messy), or you could rely on event delegation. Bind your event to the document as above, and e.target will reference the dom element that just finished animating.  e.target.className and e.target.id are very handy!

portfolio-redesign

Portfolio Redesign

The redesign of my portfolio has finally gone live, I hope you like it! I wanted something a bit cleaner looking than the old site – I fiddled around for ages in Photoshop, but I’m a really harsh judge of my own work (I never feel like it’s good enough!) so I opted for a customised version of Classica instead.  Otherwise I’d never be finished!

There’s an easter egg on the homepage – it’s pretty good, so it’s almost a shame it’s hidden.  I think I might put it on it’s own page next week. (I should mention, it uses the HTML5 Canvas API, so it’s been disabled for anything that doesn’t support Canvas.  Get a better browser!)

In other news: I went to not one, but two of Remy (& Julieanne!) Sharp’s workshop’s recently – they were both part of the LeftLogic Big Workshop Tour.  The first was the HTML5 APIs one in Manchester, the second was the Node.JS last week in London.  They were both pretty awesome, and I met some really cool people, but I’m not going to write about them right now, because I couldn’t do them justice in this short blog post.  A workshop review is definitely on my to-do list.

Work on my jQuery liteAccordion plugin has slowed since it’s last release, but I have a lot of big plans for it when I finally get some free time (damn clients, paying my bills *grumble*)

Anyways, happy bank holiday!  If you have any feedback regarding the redesign (or the little surprise on the homepage) please let me know in the comments below.

Tschüss!

css3-gradient-masks

Images and CSS3 Gradients

Webkit has a range of css3 properties for working with alpha transparent masks (see webkit.org). Firefox doesn’t support these yet, but if you want to implement a basic linear or radial (non-alpha) gradient mask, you can fake it by blending a gradient with the background colour of your page.

Set your image as the background image of a div, and give the div a width and a height.

div {
    height: 384px;
    width: 283px;
    background: url('lich-king.jpg') no-repeat;
}

Duplicate the background property:

div {
    height: 384px;
    width: 283px;
    background: url('lich-king.jpg') no-repeat;
    background: url('lich-king.jpg') no-repeat;
}

Now paste a linear gradient property before the image value, with a comma after it (the order is important):

div {
    height: 384px;
    width: 283px;
    background: -webkit-gradient(linear,left bottom,left top,color-stop(0, rgba(27,223,72,1)),color-stop(1, rgba(27,223,72,0))), url('lich-king.jpg') no-repeat;
    background: -moz-linear-gradient(center bottom,rgba(27,223,72,1) 0%,rgba(27,223,72,0) 100%), url('lich-king.jpg') no-repeat;
}

See the green colour fading in? That’s the linear gradient we’ve created (inspect the element!). Pretty ugly, huh? Lets look at some practical examples:

Linear gradient blend (right to left)

div {
    height: 384px;
    width: 283px;
    background: -webkit-gradient(linear,right top,left top,color-stop(0, rgba(255,255,255,1)),color-stop(1, rgba(255,255,255,0))), url('lich-king.jpg') no-repeat;
    background: -moz-linear-gradient(right center,rgba(255,255,255,1) 0%,rgba(255,255,255,0) 100%), url('lich-king.jpg') no-repeat
}

Radial gradient blend

div {
    height: 384px;
    width: 283px;
    background: -webkit-gradient(radial, 50% 50%, 120, 50% 50%, 140, from(rgba(255,255,255,0)), to(rgba(255,255,255,1))), url('http://nicolahibbert.com/uploads/2010/09/lich-king.jpg') no-repeat
    background: -moz-radial-gradient(50% 50% 0deg, circle closest-side, rgba(255,255,255,0), rgba(255,255,255,0) 85%, rgba(255,255,255,1)), url('http://nicolahibbert.com/uploads/2010/09/lich-king.jpg') no-repeat;
}
form-styling-css3

Form Styling with CSS3

Today we’re going to continue developing our HTML5 contact form, using CSS.

Extract the inline CSS from the head of the form and paste it into a new document.  Name this new stylesheet style.css and make a reference to it in the head of the form HTML.  At the top of style.css, I’ve imported Eric Meyer’s stylesheet reset (named “reset.css”) and removed the star (*) selector that temporarily reset the margin and padding.  (NB: never use the start selector in production!)  Your stylesheet should now look like this:

@charset "utf-8";
@import "reset.css";

form { width: 460px; padding: 20px; color: #333333; font-family: Verdana, Geneva, sans-serif; font-size: 12px; margin: 0 auto }
fieldset { border: 0; padding: 10px; margin-bottom: 10px; background: #F6F6F6 }
legend { padding: 5px 10px }
label, span { float: left; clear: left; display: block; width: 180px; padding-right: 20px; text-align: right }
input, textarea, select { float: left; width: 200px }
.submit { width: 100px; float: right; margin-right: 33px }
select { width: 206px }
p { overflow: hidden; margin-bottom: 10px }
.contact-method label { clear: none; width: auto }
.contact-method input { float: none; width: 20px }

We’re just going to make a quick couple of changes before we start.

Firstly, add ‘height: 26px; line-height: 26px’ to the ‘label, span’ selector to vertically centre the text within the input labels.

Secondly, there’s a bit of a bug in IE concerning legends and fieldsets – IE bleeds the background colour of the fieldset behind the legend.  To recify this, we’re going to add a little bit more margin to the bottom of the fieldset, and position the legend absolutely within it.

Unfortunately, positioning the legends absolutely within a fieldset that has padding triggers a bug in Firefox.  This bug causes Firefox to calculate the legend’s position incorrectly, so to fix this, we’re going to remove the padding from the top of the fieldset, and add that padding to the first paragraph in the fieldset instead.  Add “padding-top: 0” to the fieldset attribute, and “p:first-of-type { padding-top: 25px }” underneath the fieldset style.  I rarely see :first-of-type used out in the wild, as :first-child can often be used in a similar context.  However, :first-of-type selects the element that is the first sibling of that type within it’s parent, rather than just selecting the first child.  Very useful!

Now that we’ve fixed that, we’ve broken IE again by removing the padding. Add the hack “padding-top: 25px9” to the fieldset selector and we should be good to go.

With these changes, your css should look like this:

form { width: 460px; padding: 20px; color: #333333; font-family: Verdana, Geneva, sans-serif; font-size: 12px; margin: 0 auto }
fieldset { position: relative; padding: 10px; padding-top: 0; padding-top: 25px9; margin-bottom: 30px; background: #F6F6F6 }
legend { padding: 6px 12px; position: absolute; left: 10px; top: -11px }
label, span { float: left; clear: left; display: block; width: 180px; padding-right: 20px; text-align: right; height: 26px; line-height: 26px }
input, textarea, select { float: left; width: 200px }
.submit { width: 100px; float: right; margin-right: 33px }
select { width: 206px }
p { overflow: hidden; margin-bottom: 10px }
p:first-of-type { padding-top: 25px }
.contact-method label { clear: none; width: auto }
.contact-method input { float: none; width: 20px }

Now that we have a base template for our form, we can start adding styles.

Border Radius

We’re going to add a rounded corner to the fieldsets, legends and submit button, add background and text colours to the legends, and change the style of the submit button. At the moment, we still have to use vendor prefixes for border-radius, so this style declaration usually consists of three lines:

#style {
    -webkit-border-radius: <value>;
    -moz-border-radius: <value>;
    border-radius: <value>;
}

Edit your css using the styles highlighted below.

form { width: 460px; padding: 20px; color: #333333; font-family: Verdana, Geneva, sans-serif; font-size: 12px; margin: 0 auto }
fieldset { position: relative; padding: 10px; padding-top: 0; padding-top: 25px9; margin-bottom: 30px; background: #F6F6F6; -webkit-border-radius: 8px; -moz-border-radius: 8px; border-radius: 8px }
legend { padding: 5px 10px; background-color: #4F709F; color: white; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px }
label, span { float: left; clear: left; display: block; width: 180px; padding-right: 20px; text-align: right; height: 26px; line-height: 26px }
input, textarea, select { float: left; width: 200px }
.submit { width: 100px; float: right; margin-right: 38px; border: 0; padding: 5px 10px; background: #4F709F; color: white; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px }
select { width: 202px }
p { overflow: hidden; margin-bottom: 10px }
p:first-of-type { padding-top: 25px }
.contact-method label { clear: none; width: auto }
.contact-method input { float: none; width: 20px }

The last fieldset on the form should look like this:

I think it’s easy to go overboard with border-radius, so we’ll leave that bit there for now.  Next up, background gradients.

Background Gradients

We have to use vendor prefixes to enable this to work in Firefox and Webkit.  Unlike border radius, each vendor uses a different syntax for their style declaration, so it can be a little confusing.  There are more properties associated with setting a background gradient style, but I’ve listed the most common ones below.

Firefox has linear gradient and radial gradient values…

#style {
    background-image: -moz-linear-gradient( [<point> || <angle>,]? <stop>, <stop> [, <stop>]* );
    background-image: -moz-radial-gradient( [<position> || <angle>,]? [<shape> || <size>,]? <stop>, <stop>[, <stop>]* )
}

…whereas Webkit allows you to specify whether the gradient is a linear or radial one within “-webkit-gradient”:

#style {
    background-image: -webkit-gradient(<type>, <point> [, <radius>]?, <point> [, <radius>]? [, <stop>]*)
}

Note that you can also specify these gradients within the “background” shorthand property.

For our form, we’ll be using a grey border on the input boxes, and a slight gradient on the fieldsets.

form { width: 460px; padding: 20px; color: #333333; font-family: Verdana, Geneva, sans-serif; font-size: 12px; margin: 0 auto }
fieldset { position: relative; padding: 10px; padding-top: 0; padding-top: 25px9; margin-bottom: 30px; background: #F6F6F6; -webkit-border-radius: 8px; -moz-border-radius: 8px; border-radius: 8px; background: -webkit-gradient(linear, left top, left bottom, from(#EEEEEE), to(#FFFFFF)); background: -moz-linear-gradient(center top, #EFEFEF, #FFFFFF 100%) }
legend { padding: 6px 12px; position: absolute; left: 10px; top: -36px; background-color: #4F709F; color: white; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px }
label, span { float: left; clear: left; display: block; width: 180px; padding-right: 20px; text-align: right; height: 26px; line-height: 26px }
input, textarea, select { float: left; width: 200px; border: 1px solid #d9d9d9 }
.submit { width: 100px; float: right; margin-right: 37px; border: 0; padding: 5px 10px; background: #4F709F; color: white; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px }
textarea { background: -webkit-gradient(linear, left top, left bottom, from(#FFFFFF), color-stop(1%, #EEEEEE), to(#FFFFFF)) }
select { width: 202px }
p { overflow: hidden; margin-bottom: 10px }
p:first-of-type { padding-top: 25px }
.contact-method label { clear: none; width: auto }
.contact-method input { float: none; width: 20px }

After these styles have been added, you should see something that looks like the image below.

Next we’re going to add a drop shadow to make the bottom corners of the fieldsets a little more prominent.

Box Shadow

Box shadow is similar to border-radius syntax-wise, you need to specify two vendor prefix properties and the official property as defined in the CSS3 spec.  Border-radius takes 3 lengths: the horizontal offset, the vertical offset, and the blur radius; and a colour.

#style {
    -webkit-box-shadow: <horz>, <vert>, <blur>, <color>;
    -moz-box-shadow: <horz>, <vert>, <blur>, <color>;
    box-shadow: <horz>, <vert>, <blur>, <color>;
}

We’re going to add a box shadow to the fieldsets, the legends, and the submit button, using the values highlighted below.  Notice that we’re also adding 4px margin to prevent the overflow: auto property on the parent paragraph tag from clipping the shadow on the bottom of the submit button.

form { width: 460px; padding: 20px; color: #333333; font-family: Verdana, Geneva, sans-serif; font-size: 12px; margin: 0 auto }
fieldset { position: relative; padding: 10px; padding-top: 0; padding-top: 25px9; margin-bottom: 30px; background: #F6F6F6; -webkit-border-radius: 8px; -moz-border-radius: 8px; border-radius: 8px; background: -webkit-gradient(linear, left top, left bottom, from(#EFEFEF), to(#FFFFFF)); background: -moz-linear-gradient(center top, #EFEFEF, #FFFFFF 100%); box-shadow: 3px 3px 10px #ccc; -moz-box-shadow: 3px 3px 10px #ccc; -webkit-box-shadow: 3px 3px 10px #ccc }
legend { padding: 6px 12px; position: absolute; left: 10px; top: -11px; background-color: #4F709F; color: white; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; box-shadow: 2px 2px 4px #888; -moz-box-shadow: 2px 2px 4px #888; -webkit-box-shadow: 2px 2px 4px #888 }
label, span { float: left; clear: left; display: block; width: 180px; padding-right: 20px; text-align: right; height: 26px; line-height: 26px }
input, textarea, select { float: left; width: 200px; border: 1px solid #d9d9d9 }
.submit { width: 100px; float: right; margin-right: 37px; border: 0; padding: 5px 10px; background: #4F709F; color: white; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; box-shadow: 2px 2px 4px #888; -moz-box-shadow: 2px 2px 4px #888; -webkit-box-shadow: 2px 2px 4px #888; margin-bottom: 4px }
textarea { background: -webkit-gradient(linear, left top, left bottom, from(#FFFFFF), color-stop(1%, #EEEEEE), to(#FFFFFF)) }
select { width: 202px }
p { overflow: hidden; margin-bottom: 10px }
p:first-of-type { padding-top: 25px }
.contact-method label { clear: none; width: auto }
.contact-method input { float: none; width: 20px }

Very Useful Tip: You can also use rgba values with box shadow, achieving an effect similar to the one I described in my CSS3 Alpha Transparent Gradients post.

Text Shadow

Next we’ll add a bit of text shadow on the legends and submit button to make them stand out a little more.  The text shadow property is pretty much the same as box shadow.  It takes 3 values and a colour, that is, the x value of the shadow, the y value of the shadow, the blur radius, and a colour.  However, this time we don’t have to use vendor prefixes, as native property is supported in all current browsers.

#style {
    text-shadow: <horz>, <vert>, <blur>, <color>;
}

Add the highlighted lines below to your css.

form { width: 460px; padding: 20px; color: #333333; font-family: Verdana, Geneva, sans-serif; font-size: 12px; margin: 0 auto }
fieldset { position: relative; padding: 10px; padding-top: 0; padding-top: 25px9; margin-bottom: 30px; background: #F6F6F6; -webkit-border-radius: 8px; -moz-border-radius: 8px; border-radius: 8px; background: -webkit-gradient(linear, left top, left bottom, from(#EFEFEF), to(#FFFFFF)); background: -moz-linear-gradient(center top, #EFEFEF, #FFFFFF 100%); box-shadow: 3px 3px 10px #ccc; -moz-box-shadow: 3px 3px 10px #ccc; -webkit-box-shadow: 3px 3px 10px #ccc }
legend { padding: 6px 12px; position: absolute; left: 10px; top: -11px; background-color: #4F709F; color: white; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; box-shadow: 2px 2px 4px #888; -moz-box-shadow: 2px 2px 4px #888; -webkit-box-shadow: 2px 2px 4px #888; text-shadow: 1px 1px 1px #333 }
label, span { float: left; clear: left; display: block; width: 180px; padding-right: 20px; text-align: right; height: 26px; line-height: 26px }
input, textarea, select { float: left; width: 200px; border: 1px solid #d9d9d9 }
.submit { width: 100px; float: right; margin-right: 37px; border: 0; padding: 5px 10px; background: #4F709F; color: white; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; box-shadow: 2px 2px 4px #888; -moz-box-shadow: 2px 2px 4px #888; -webkit-box-shadow: 2px 2px 4px #888; margin-bottom: 4px; text-shadow: 1px 1px 1px #333 }
textarea { background: -webkit-gradient(linear, left top, left bottom, from(#FFFFFF), color-stop(1%, #EEEEEE), to(#FFFFFF)) }
input:focus, textarea:focus, select:focus { background: white; border-color: #666 }
select { width: 202px }
p { overflow: hidden; margin-bottom: 10px }
p:first-of-type { padding-top: 25px }
.contact-method label { clear: none; width: auto }
.contact-method input { float: none; width: 20px }

Focus Highlighting

We’re going to add one last style, to make the input boxes more prominent when they’re in focus…

nput:focus, textarea:focus, select:focus { border-color: #666 }

…and one last tweak, to make the input boxes a little bigger.

input, textarea, select { padding: 3px; float: left; width: 200px; border: 1px solid #d9d9d9 }
select { width: 208px }

The final CSS should look like this:

form { width: 460px; padding: 20px; color: #333333; font-family: Verdana, Geneva, sans-serif; font-size: 12px; margin: 0 auto }
fieldset { position: relative; padding: 10px; padding-top: 0; margin-bottom: 30px; background: #F6F6F6; -webkit-border-radius: 8px; -moz-border-radius: 8px; border-radius: 8px; background: -webkit-gradient(linear, left top, left bottom, from(#EFEFEF), to(#FFFFFF)); background: -moz-linear-gradient(center top, #EFEFEF, #FFFFFF 100%); box-shadow: 3px 3px 10px #ccc; -moz-box-shadow: 3px 3px 10px #ccc; -webkit-box-shadow: 3px 3px 10px #ccc }
legend { padding: 6px 12px; position: absolute; left: 10px; top: -11px; background-color: #4F709F; color: white; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; box-shadow: 2px 2px 4px #888; -moz-box-shadow: 2px 2px 4px #888; -webkit-box-shadow: 2px 2px 4px #888; text-shadow: 1px 1px 1px #333 }
label, span { float: left; clear: left; display: block; width: 180px; padding-right: 20px; text-align: right; height: 26px; line-height: 26px }
input, textarea, select { padding: 3px; float: left; width: 200px; border: 1px solid #d9d9d9 }
.submit { width: 100px; float: right; margin-right: 37px; border: 0; padding: 5px 10px; background: #4F709F; color: white; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; box-shadow: 2px 2px 4px #888; -moz-box-shadow: 2px 2px 4px #888; -webkit-box-shadow: 2px 2px 4px #888; margin-bottom: 4px; text-shadow: 1px 1px 1px #333 }
textarea { background: -webkit-gradient(linear, left top, left bottom, from(#FFFFFF), color-stop(1%, #EEEEEE), to(#FFFFFF)) }
input:focus, textarea:focus, select:focus { background: white; border-color: #666 }
select { width: 208px }
p { overflow: hidden; margin-bottom: 10px }
p:first-of-type { padding-top: 25px }
.contact-method label { clear: none; width: auto }
.contact-method input { float: none; width: 20px }

View Demo

In the next tutorial, I’ll show you how to test for browser support of the new input types.

css3-alpha-transparent

CSS3 Alpha Transparent Gradients

In CSS3 you can create a gradient background with multiple color stops.  But did you know that you could throw alpha transparency into the mix? This is an example of the CSS used to create a blue-green linear gradient:

.gradient {
    background: #4C95AF;  /* for IE */
    background:
        -moz-linear-gradient(  /* for firefox */
            center bottom,
            rgb(76,149,175) 5%,
            rgb(183,185,52) 95%
        );
    background: -webkit-gradient(  /* for chrome and safari */
        linear,
        left bottom,
        left top,
        color-stop(0.05, rgb(76,149,175)),
        color-stop(0.95, rgb(183,185,52))
    );

}

This will result in:

The colour stops are defined using the rgb format. Watch what happens when we add alpha to the end of the color stop declarations.

.gradient {
    background: #4C95AF;
    background:
        -moz-linear-gradient(
            center bottom,
            rgba(76,149,175,0.1) 5%,
            rgba(183,185,52,0.9) 95%
        );
    background: -webkit-gradient(
        linear,
        left bottom,
        left top,
        color-stop(0.05, rgba(76,149,175,0.1)),
        color-stop(0.95, rgba(183,185,52,0.9))
    );
}

You can inspect these divs with a developer tool, they’re not images!

This opens up a whole new dimension of transparency in your designs. Imagine what you could do with a few more colour stops, changing the angle of the gradient, or using a radial gradient instead of a linear one! Please note: this technique is not supported in Internet Explorer or Opera. It is possible to use Microsoft’s filter mechanism to create a transparent gradient, but it’s not recommended (more information). A more practical solution would be to create a fallback based on 24 bit PNGs, and then convert the images into data URIs to negate the need for an extra http request.

Enjoy!