We all know that CSS3 has emerged in past couple of years a lot, and everyone is talking about it. There are many new features and properties that are well implemented in modern browsers.

But lately there has been some buzz going around CSS4. CSS Working Group has published a first working draft over half a year ago with many new proposals. CSS4 isn’t going to replace CSS3, but the work on specifications will go on parallel with CSS3 Modules.

In this article I’ll go through some of the most interesting proposals for CSS4. There are many new concepts, including such as parent selector, UI states pseudo-classes, Logical Combinations and Namespaces.

This article is based on my presentation: “CSS3 – The Present and The Future” which contains a section Peek into CSS4.

Table of Contents

Parent Selector

This is the magical selector many developers have been craving for. Earlier there hasn’t been an option to select the parent of an element. In CSS4 this is possible.

Parent selector was earlier proposed to be declared by using “$” rule, eg. $fieldset input:focus. At the moment it is proposed that the rule is following:

fieldset! > input:focus {
  background-color:yellow;
}

If you’re interested in starting to use parent selector today, check jQuery-powered polyfill: cssParentSelector for it.

UI States pseudo-classes

UI states pseudo-classes are meant to target different states an element can have. These are defined in CSS Basic User Interface Module, which have been moved into CSS4 proposal. Some of them, like :enabled and :disabled are already specified in CSS3, while others, like :valid and :invalid are new pseudo-classes in CSS.

Here is the list of UI states pseudo-classes:

  • :enabled / :disabled
  • :checked
  • :indeterminate
  • :default
  • :valid / :invalid
  • :in-range / :out-of-range
  • :required / :optional
  • :read-only / :write-only

Most of them are self-explanatory, but you can read more detailed description from the draft.

Tree-Structural pseudo-classes

Tree-structural pseudo-classes (eg. :nth-child() and :nth-of-type()) has now two new pseudo-classes: :nth-match() and :nth-last-match().

What :nth-match() actually is? It’s very similar to the logic with :nth-child().

:nth-match(an+b of selector-list) notation represents an element that has a parent and has an+b-1 siblings that match the given selector-list before it in the document tree, for any zero or positive integer value of n.

In practice, :nth-match matches with the given selector-list while :nth-child matches with the given selectors children elements. This happens by including of keyword in selector. If you have the selector input:nth-match(even of :enabled), it will first match the subset of input elements that are enabled and then match the even elements from that subset.

Logical Combinators

Logical Combinations consists of two pseudo-classes: :matches() and :not(). The behavior of “Negation pseudo-class” :not() is most likely clear to you – eg. input:not(:disabled) matches with all the input elements that are not disabled. But :matches() might be a bit more strange:

Matches-Any pseudo-class

The :matches() pseudo-class is the standardised version of Mozilla’s :-moz-any() pseudo class. This is useful for when you need a number of similar selector strings, but change one part such as the pseudo-classes.

Instead of writing a:hover, a:focus, a:active, one can write a:matches(:hover, :focus, :active) for same result.

Reference Combinators

Reference combinators allow you to select elements that are referenced by ID by another element. This is better to be explained in practice:

The following example highlights an input element when its label is focused or hovered-over:

label:matches(:hover, :focus) /for/ input { /* association by "for" attribute */
    box-shadow: yellow 0 0 10px;
}

Media Queries Level 4

While writing this article, first draft of Media Queries Level 4 was published. Unfortunately I won’t be writing more about Media Queries in this article, I just suggest reading the draft :).

Namespaces

Namespaces are actually proposed in CSS(3) Namespaces Module, but it’s written pretty much the same time as first proposal of CSS4. And CSS4 proposal is heavily referring to the namespaces, so I feel this one is good to go through when speaking of CSS4.

CSS Namespaces has quite simple syntax. The @namespace declares a namespace prefix and associates it with a given namespace name, and “vertical bar” works as a selector delimiter. Consider following example:

@namespace "http://www.example.com";
@namespace foo "http://www.example.com/foo";

h1 { font-size: 42px; } /* Belongs in example.com */
|h1 { font-size: 36px; } /* Belongs eg. in example.com/bar */
*|h1 { font-size: 32px; } /* Belongs in both namespaces */
foo|h1 { font-size: 28px; } /* Belongs in example.com/foo */

New Properties for Borders

Some new properties for borders are introduced in CSS4. The most obvious one is border-corner-shape, which allows values curve | bevel | scoop | notch. In addition, there are updates on border-images.

For further reading, see CSS Backgrounds and Borders Module Level 4.

Resources

I have to admit that there is lot more in CSS4 Working Draft than it’s included in this article. Therefore I suggest you all to read following resources I’ve gathered about CSS4:

More than two years ago CSS Animations were represented in WebKit. Up until now, they’ve been supported only in Safari and Chrome.

Recently I noticed, when upgrading to Android 3.1 that it dramatically enhanced the performance of CSS Animations and Transitions. And only few days ago, Firefox 5 Beta was released which has decent support for keyframes, and also better performance for transitions. Therefore I decided to write a brief article about CSS Animations and using keyframes.

In this article we will go through what it takes to create keyframe animations. I’ll create a simple demonstration of an icon character which comes alive with a little help of keyframes.

Foreword

This article won’t help with the basics and all the details of CSS Keyframes. If you’re unfamiliar with keyframes, I strongly suggest reading Smashing Magazine’s article “An Introduction To CSS3 Keyframe Animations”.

If you’re also unfamiliar with CSS Transitions, you can also read my article “CSS3 Transitions – Are We There Yet?”.

It’s good to notice that there already exists tools for creating proper CSS Animations, like Animatable that are worth of checking. Especially, if you’re not that much of a fan writing endless keyframes rules and css declarations

Browser Support

I’ve tested this example with recent builds of Google Chrome, Firefox 5 Beta, iPhone 4 / iPad and Android 3.1 with Browser (Chrome) and Firefox Beta. So, if you’re viewing this article with any of those, then you’re good to go.

There are indications that also Opera will support CSS Animations in near future. Let’s see when that will be. However, Internet Explorer won’t be supporting CSS Animations – they’re not even supporting CSS Transitions yet.

The Icon

In this example we’ll build an icon with separate head, body and background. We’ll add some movement with keyframes to each object while trying to achieve as realistic result as possible without too much of an effort.

The character icon in demonstration is from Battleheart, developed by Mika Mobile.

The Head

Wizard's head We start by defining the behavior of an animation for the head. This is done by defining a keyframes rule called “breathe-head”.

@-webkit-keyframes breathe-head {
    0% {
        -webkit-transform: rotate(1deg) translate3d(0px, 0px, 0px);
    }
    40% {
        -webkit-transform: rotate(-3deg) translate3d(-2px, -1px, 0px);
    }

    100% {
        -webkit-transform: rotate(1deg) translate3d(0px, 0px, 0px);
    }
}

NOTE: I’m using property called translate3d for moving the head slightly backwards. It’s good to understand that only transformable properties (+ opacity) can be animated with hardware acceleration. Translate3d(0,0,0) is good to have to ensure hardware acceleration of animations even if it’s not needed for any other use. I’ve even encountered many situations where animation performance hasn’t been smooth eg. on iOS Web Applications until (over)usage of translate3d().

Twice the Fun!

For some (unknown) reason, it isn’t possible to add -moz-keyframes rule at the same declaration, so we need to declare keyframes rules again:

@-moz-keyframes breathe-head {
    0% {
        -moz-transform: rotate(1deg) translate(0px, 0px);
    }
    40% {
        -moz-transform: rotate(-3deg) translate(-2px, -1px);
    }

    100% {
        -moz-transform: rotate(1deg) translate(0px, 0px);
    }
}

I’m not using translate3d() since it seems Firefox only understands translate(). But it’s good enough for performance since it should be also hardware accelerated on Firefox.

The Body

Wizard's body Next, we’ll animate the body of the character. We don’t need any wildly bouncing animation since we’re operating with an (small) icon. Constant movement has to be subtle or otherwise it can start to irritate users:

@-webkit-keyframes breathe-body {
    0% {
        -webkit-transform: translate3d(0px,0px,0px);
    }

    40% {
        -webkit-transform: translate3d(0px,-3px,0px);
    }

    100% {
        -webkit-transform: translate3d(0px,0px,0px);
    }
}

And the same rules needs to be applied for -moz-keyframes like we did with the head.

The Background

Wizard's backgroundI wanted to add something more to a movement and decided to draw a subtle background “sun” which keeps rotating behind the character:

@-webkit-keyframes rotate-bg {
    0% {
        -webkit-transform: rotate(0deg);
    }
    100% {
        -webkit-transform: rotate(360deg);
    }
}

Rotating background is very straight-forwarded; we rotate it once per timeline we’ll define later on.

Keyframes are Done – What Next?

Now that we’ve defined keyframe rules, we must take them into use:

.character {
    -webkit-animation: breathe-body 3000ms infinite both ease-in-out;
    -moz-animation: breathe-body 3000ms infinite both ease-in-out;
}

.character .head {
    -webkit-animation: breathe-head 3000ms infinite both ease-in-out;
    -moz-animation: breathe-head 3000ms infinite both ease-in-out;
}

.rotating {
    -webkit-animation: rotate-bg 30s infinite linear;
    -moz-animation: rotate-bg 30s infinite linear;
}

I’m using short-hand declarations, and eg. for .character .head we declare: “Use breathe-head keyframe rules in a three seconds long loop which last infinite time and is animated with in-out easing equation”.

Value “both” stands for animation-fill-mode should define the status of first and last keyframe. But in my case I didn’t notice anything special when I trying other possible values “forwards” or “backwards” (this could be since both start and end keyframe has similar values).

The End Result

I needed to declare more CSS for getting things in correct place. But the example code above is practically the soul and heart of the animation. But here is the end result of an animated wizard icon:

 

 

How do you like it? It’s my first animation ever :).

Sometimes there is need to write browser-specific CSS declarations. Although every developer should put their best effort on creating structure and layout that doesn’t require any proprietary hacks, one may encounter situations where it’s impossible to proceed by the book.

My case was about font-size and letter-spacing on Opera (11.10). Opera was displaying selected font way too big to fit in allowed space and I needed a hack to fix this issue.

Opera 9 and below

This is pretty straight forward and well known hack:

html:first-child p
{
    font-size:12px;
}

The real issue, in my case, was how to target newer and modern Opera versions 10 and 11.

Opera 10 and above

The answer is in media queries. Earlier this was obvious hack while no other browsers supported media-queries properly. However, nowadays more and more browsers support it and therefore we need to tweak the conditions a little:

@media not all and (-webkit-min-device-pixel-ratio:0) {
    p {
        font-size:12px;
    }
}

I’ve validated this with Opera 10.5 and Opera 11. I also checked on Chrome 11, Chrome 12, Firefox 3.6, Firefox 4.0, Safari 5 and IE 8 that it doesn’t affect on them.

Edit: I haven’t tested this on Opera 9 or earlier, but according to other resources, this hack should work on those browsers too.

Conclusion

It’s still possible to write browser-specific hacks but it’s getting more and more complex all the time. In this case we’re using a hack that is actually targeted to WebKit browsers to get them excluded from the media query hack. However, there is no confidence that this hack would work on Opera 12 or next versions of Safari or Chrome would behave as expected.

And big thanks goes to an article CSS Hack or New CSS File for Problematic Browsers? and Is There Any Dedicated CSS Hacks For Safari or Opera?.