Premium developer support

If you are struggling with this library, we offer premium developer support plans. With a support plan, you can (privately) communicate with our team of developers and receive private help and attention for as long as you need.

Navigate the wild waters of event-driven style changes.

A lightweight polyfill adding support for JS event triggering and matching in stylesheets using standard CSS2 selectors.

Often events are registered using JavaScript for the sole purpose of updating styles. Especially with the advent of CSS animations and other CSS3 syruppy sweetness, simple style changes can hold huge impact for user experience. The goal of CuttySSark is to allow the front-end developer to write compliant CSS that interacts seamlessly with the JS event model. And it's just a weeny little JS file.

Cutty pretty much only does two things.

Registers events to apply a style block.

Allows remote triggering by one DOM element on another.

A quick first look

Let's take a little peek just to see what this crazy thing looks like. Click away at the fine boxes below.

#big

#little

#big[on~="click|toggle"] #little {
background: transparent;
}

This selector registers a click event on #big using Cutty's toggle option so that her child #little is given a transparent background. Thanks to the toggle option, the style is toggled on and off each click. What's great is that Cutty is not using JS to apply the style; it's simply making sure the selector #big[on~="click|toggle"] #little matches when it ought to.

Getting and using CuttySSark

You can download CuttySSark v1.0 right here or fork me on Github. The one dependency is jQuery 1.7+. Simply include both as such,

The syntax

The example above highlights the simplicity of Cutty. The syntax is pretty straightforward! You write standard CSS, but certain selectors have a new importance.

#cutty[on~="event|option"] .ssark {...}

The option is, well, optional. We'll go over those is a moment. As a side note, you can chain the on~= selectors to require that several events have taken place. For example, div[on~=click][on~=mouseout] will require that a div be clicked and the mouse leave it before the style is applied.

Events

An event can be any standard JS event name, sans the "on" prefix. Additionally, it may be a custom event fired by jQuery, or as you'll soon find, a custom event fired more explicitly by Cutty.

Options

1. toggle

The toggle option applies the style every other time the event is fired. Every time it's toggled off a second style can be applied by using off where the option parameter goes. So,#big[~on="click|toggle"] #little matches on first, third, fifth click, etc.#big[~on="click|off"] #little matches on second, fourth, sixth click, etc.

2. once

The once option guarantees the style will be applied only the first time the event is fired on a particular element.

3. clear

The clear option clears all other styles currently associated to the current element by Cutty.

4. state

The state option is similar to clear, but only clears other styles also registered with the state option.

5. default

Without any option parameter, e.g. img[on~=load], the corresponding style block is simply applied.

Remote event triggering

Cutty also allows an event fired on one element to trigger second event on some other elements.

selector1[on~="event1|trigger|event2(selector2)"] {}

When event1 is fired on an element matching selector1, event2 is triggered on all elements matching selector2. Chain this with media queries, and you're the juggernaut. Anybody want to integrate CuttySSark with Harvey?

Special (relative) selectors

There are a few special selectors that will match for selector2 relative to the element triggering the event. The selectors next, prev, and parent reference respectively the next sibling, previous sibling, and parent of the element matching selector1 which triggers the event. The next and prev selectors loop the siblings, so that the last sibling will select the first using next, and the first sibling will select the last using prev. Additionally, the self selector matches the element triggering the event.

Triggering "on page load"

There is a special event named cutty that is automatically triggered by the <body> element as soon as Cutty finishes processing stylesheets. So if you want to fire an event right away, you can do so with body[on~="cutty|trigger|someEvent(selector2)"].

Limitations and excluding stylesheets

One limitation of Cutty is that cross-origin linked style sheets cannot be read, so your browser will probably throw some sort of a security error if Cutty tries to touch one of them. Unfortunately that means that stylesheets hosted on a CDN are out as far as Cutty is concerned. We might be able to deal with this by enabling CORS and hacking Cutty a bit. In any case, to skip over a stylesheet, just include the data-cutty-bypass attribute on it and you'll be all set.

Demos

Handling <img/> loads and errors

Reload Page

Here's a simple, functional application of CuttySSark: using Cutty we can deal with images' styles when they load or error. Directly above is an image set to fade-in once it's fully loaded. And on the right (now looking quite empty, probably) there is a broken image set to fade-out when it errors. Of course, it may be more natural to just set the broken image to display: none, but hey, this is a demo!

Here's a nice first look at Cutty's capabilities. One upside here is that Cutty has allowed us also to write neat markup to acheive a flashy little effect. I don't even feel guilty! Here there are three sheets that rotate first to second to third, etc. The first two style blocks setup the style for when the page first loads, with only the first sheet displaying. Each sheet has a click and a show state. The click state makes the current sheet disappear and fires a show event on the next sheet. When the show event is fired on that sheet, it applies the style to display then animate it. The state option is used to make sure the click and hide styles never conflict with each other.

Infinite-pane lazy-loading carousel

◄►

This example fancies-up the previous demo by implementing relative selectors to allow for an arbitrary number of panes. Further, it has a more complicated event structure since the previous- and next-arrow controls must trigger the displaying and hiding of the proper panes. We also take advantage of the fact that an element with a CSS background image will not cause the browser to request the image if its parent has the style display: none. Which makes this carousel a lazy-loader!

In the first two style blocks we see that a pane will be visible exactly when it matches the display event. The third block says that when a hide event is triggered on a pane, it will clear any event-related styles (notably, it will clear any active display style). The fourth style block triggers the first pane to display as soon as Cutty has finished processing all stylesheets, using the special cutty event. Then we set up the events for hiding/displaying by the arrow controls. When the previous arrow is clicked it triggers an event called bubblePrev on the pane currently displaying. In turn, that event causes the pane to trigger hide on itself and display on its previous sibling, thus switching panes. The next-arrow control works similarly in the sixth block.

A slew of thoughts

CuttySSark is on the MIT license, so you can hack away at it!Here are some hacking possibilities.

More stateful options e.g. named states, using Cutty for drag events, integrating with Harvey, supporting element-level media queries, building in keyboard events per key, chaining relative selectors, making a public refresh method to reprocess stylesheets (say, when an element is added to the page), test performance, build-in animation events, explore use of the animationend event for chaining animations, read Tam o' Shanter again.

This project is free to use under the MIT License.Copyrights are property of their respective owners.