I’ve been having fun with CSS Transforms (supported by both Webkit/Safari/iPhone and Firefox) as well as the Webkit/iPhone only transform animations. The resulting framerates on the iPhone are hard to achieve any other way. I’ve even built an iPhone app called iBlipper with this tech.
This is not a major hack, but scratches an itch I’ve had for years to be able to code typographical animation with HTML and an augmented set of attributes — in this case: effect, duration, and start.
Peter Nederlof just released version 3 of whatever:hover, his library that makes sure that :hover works just fine for the IE browsers out there.
The new version is faster, better documented, uses a CSS trick with expressions in IE to trigger the hover events in IE and now has Ajax support! (this means that new items added to the DOM after loading will also be affected by whatever:hover.
How does it work?
All browsers provide some way to look at a stylesheet's rules using javascript, and dynamically insert new rules. Normally, IE returns "unknown" for anything it does not support, for instance; a "div p:first-child" would change into "div p:unknown", and a "p a[href]" would be returned as "UNKNOWN" altogether. Fortunately IE recognizes :hover as something it's familiar with, and leaves it alone.
IE also supports so called behaviors; both predefined functionality like dynamic content loading or persistent data storage, as well as custom behaviors that you can build into an .htc or .hta file. These behaviors are linked to html nodes via css, and "enhance" the nodes that are selected by a rule's selector with the given behavior.
Combining the above, it should be possible to create a bahavior that searches the styles for rules IE doens't support, and trick affected elements into applying the associated styles some other way. The steps involved in this are something like:
Search all stylesheets for :hover rules IE doesn't support,
Insert a new rule IE does support, like one with class names,
and finally, set up script events for switching class names.
This way, :hover, :active and :focus can be supported, and as a developer you don't have to do anything except including the behavior. Everything else runs on full automatic.
Unlike versions 1 and 2, version 3 also supports dynamically added html (ajax). The difference is that 1 and 2 actively searched for affected elements onload of the page (so; only once), whereas 3 uses expressions to let nodes do a callback themselves. Read the commented version for more details on this.
Matt Wilcox thinks that there are fundamental problems with CSS3 and he shared his thoughts. He starts by giving us some history of CSS and then gets into the meat:
Why the Cascade is no longer enough
HTML has been re-purposed to represent only the semantic properties of the page. Because CSS is only capable of cascading through the DOM, that means CSS can only be applied to elements that have semantic meaning. The trouble is that web-design today is more art than decoration. I’m not taking one wall and painting it green, I’m taking one canvas and painting a complete scene on it.
There are many times where a designer wants to create or manipulate a visual element for which there is no semantic hook.
Because CSS can not query, freely traverse, nor manipulate the DOM, we are forced to add non-semantic hooks to the HTML.
Because CSS can not query, freely traverse, nor manipulate the DOM, designs are dependent on the structure of the mark-up.
CSS’s fundamental weakness means that true separation of presentation from content is not achievable even today.
And then, What does CSS need to overcome these problems?
irst let me say what I think it really does not need. It does not need more ill thought out modules that provide half-baked solutions to explicitly defined problems and take a full decade to mature. We do not need the Working Group to study individual problem cases and propose a pre-packaged “solution” that either misses the point, is fundamentally wrong, or is inflexible (Advanced Layout Module, Marquee Module, display:table;, - I am looking at you). Here’s what we do need:
DOM traversal, reference, and injection on the same order provided by jQuery. There’s a damned good reason why designers are flocking to jQuery.
Programmatic variables, and basic Math
he crux of the issue is that W3C seem to try providing high-level “solutions” instead of low-level tools. It’s a limiting ideology. With the CSS3 WG strategy as it’s been over the last decade, they would have to look at all of the problem points I proposed above, and come up with a module to provide a solution to each. But by giving CSS an ability to traverse and manipulate the DOM, we designers can build out own solutions to all of them, and innumerable other issues we have right now, and in the future. Allow me to give an example; take the first “impossible” CSS challenge above, the unknown number of tabs that must fill a given width. It’s impossible - but the Multi Column Module does in fact allow the exact same functionality - you can specify a container of a given width and then specify a given number of columns (which you can change), and CSS will do the math internally to get the right widths! But I can’t use that module to achieve what I need with the tabs, despite it having the same basic function! Because they’ve provided a pre-packaged “solution” to a very specific problem instead of giving a more abstracted set of tools with which I could build my own solution.
All of the “impossible” CSS tasks set above can be solved by providing CSS an ability to inspect and modify the DOM, and use basic Math. And I can think of a dozen other impossible things that would rock if I had those tools in my CSS.
The CSS WG argue that CSS is meant to be simple, whilst missing the point that CSS is not meant to be anything. It’s a tool that must do a job, and the job has changed over time. CSS needs to keep up with requirements, and the best way to do that is provide adaptable tools rather than pre-packaged modules. There’s continual argument that maths, and dom traversal are too advanced for CSS, which is utter rubbish. I contest that if we are expected to understand selectors like nth-child : 4n+3; (explained in the CSS3 spec as "an element that has an+b-1 siblings before it") then we can cope very well with creating and assigning variables, a little flow logic, and doing some simple adding. If we can handle jQuery, we can handle that.
What do you think? How would you like to see CSS changed? Would you like to separate style from layout?
Jennifer Semter has published an article on CSS spriting, and a cross-browser technique that uses divs, anchors, and clipping to get the same effect as background image clipping. The reason for the new technique is due to the issues with the current approach:
You can’t attach alternate text to divs for accessibility purposes
Chris Wetherell (the chap who kicked off Google Reader in his apartment) has posted about Pegs a pattern for having one scrollbar but independent scrolling areas.
It is more than display: fixed in that it can be smart. If you visit the demo you will see it in action. After the first time, click around on the other items such as flipping between sizes of areas. You will see that different areas scroll depending on the config.
This is definitely something that people will be skeptical about. It feels weird. It isn't what we are used too. The demo app also is jumpy and acts a little strange, but it is interesting to play with these ideas.
Valerio Proietti has written a thoughtful post on why MooTools won't use Sizzle (and tries to argue why other libraries shouldn't).
He cites the advantages of having one code base that your project can tweak at will, and competition being a good thing to move things forward:
There are several reasons why a project like MooTools would never include a third party library like Sizzle in its codebase. First of all, we already have a very fast, very manageable and solid CSS selector engine in place. I worked on it a lot, I know how it works, and I know that if it ever needs a fix, every MooTools collaborator can just git it and fix it, right away. Every Mootools collaborator knows how MooTools works, what our code practices are, and how to submit either a patch (if they don’t have Git credentials), or patching the code themselves.
I don't expect every library will drop its own engine and plugin Sizzle right away. However, if done correctly, Sizzle can be an area of collaboration. If it becomes "John's Library" that is one thing, but you will note that there have already been patches from the Prototype folks and maybe others. Sizzle could be a playground for innovation itself.
I believe by collaborating on core items like the CSS engine everyone benefits. It wouldn't feel "less MooTools" as Valerio cites, because it is hidden. We see this across industries. People come together to work on infrastructure pieces, and then go off and offer value adds and different APIs and ways of looking at things. Right now our Ajax libraries are duplicating effort. Imagine if Sizzle doesn't become used by many engines in the future? Maybe it could be included in browsers, and optimized in some way. Who knows. Either way, I think it is a fine experiment that I am excited to see, and at the same time I value Valerio's thoughts, and that is why it is great that he has the choice to not use it :)
Voting has started in Dojo land to take in John Resig's Sizzle next-gem CSS selector engine.
This is incredibly exciting, as it shows how Ajax libraries are working together more and more. Instead of reinventing the wheel in different ways for each project, is it possible to find some core pieces that can be nicely shared? Of course, if our world was nicer and we could share code by linking in a nice way maybe this would happen more.
As I mentioned in my thanksgiving note, the work that the Ajax library developers do is hugely important and impactful, and having them work together can only be great news.
Take a look at this public email to the Dojo Foundation on the vote:
Overview
The Sizzle project is a JavaScript library for performing selections
across a DOM tree using CSS selectors. The library is designed to be
standalone (have no external dependencies), lightweight, fast, and
extensible. This culminates in a library that is perfectly suited for
integration into other libraries. While it's feasible that a developer
may use Sizzle directly the target audience for it is other library
authors.
All of the code for the project has been written by John Resig and is
released under an MIT license. There are some patches pending from
some other contributors (namely Prototype).
Right now the following libraries are adopting or are looking to adopt
Sizzle as their primary CSS selector engine:
It's likely that Sizzle will become the unified engine behind a
majority of the JavaScript libraries on the market (if not in numbers
then certainly in market share).
The project is owned by John Resig who will serve as BDFL/Project lead
if the project is accepted. There is no formal voting process, as of
yet, but it's likely that one will come about, considering the number of
projects using the codebase.
If the project is accepted to the foundation then all contributors to
the project will be required to have a CLA and follow the policies of
the Dojo foundation.
It's very likely that Sizzle will eventually expand into other areas
of JavaScript libraries (such as DOM manipulation and event binding).
That last line excites me too! It is interesting to see this happen in the Dojo Foundation. Remember, Dojo was founded out of toolkits coming together to aggregate forces. Kudos to everyone involved, and good luck!
Gareth Rushgrove has published some code for CSS Test, code that lets you get in there and test resulting CSS:
CSS is hard to test automatically. Their appear to be two potential approaches
which might have merit in solving this problem and and this sample code
represents one of them.
test_image.py
The basic idea here resolves around programatic comparison of images, some
based on screen shots and others generated dynamically from URLs. The
capability to analyse only a segment of a page has also been included.
The overhead introduced by the need to take screenshots of a site makes this
technique more useful for spotting regression issues in a live site than for
a test driven approach to writing CSS. Tools will be provided to make this
easier at a later date.
As this is currently a proof of concept in that it only supports testing in
webkit, and even then only on OS X. Support for other browsers relies on
other screen grab tools being integrated into the code.
This is not intended as a tool to check whether a finished website looks
identical to a set of photoshop images. It's intended to spot changes in
unexpected areas of a sites layout or design.
Here we plan on using Selenium to extract rendered DOM values like text-size
from a given web page and compare them against expected values. This could be useful both for regression testing and for assertion based test driven
development.
The sample code is written in Python but other implementations would be
straightforward. Much of the actual work is done via other commands; namely
webkit2png by Paul Hammond and the Imagemagik suite of tools.
Time for a bit of fun. The eternal battle of tables vs. CSS layouts continues. We geeks have had classics such as vi vs. emacs, and Star Wars vs. Star Trek.
John has changed his stance from "oh man that is ugly" to "it has merit". We sure do need help with layout. Can't we have JGoodies give us a decent layout manager for JavaScript?
John also discussed:
The new Element Traversal API and how his jQuery plugin uses the cleaner API and gives promising speed improvements: "With this addition .siblings() is 84% faster and .children() is 35% faster."
In Deadly Expandos he discusses the old bug that has the id to method madness of DOM0 stepping on functions to break your apps.
XHR is so 1997. Now it is time for some CSSHttpRequest action, a device that allows you to run cross domain Ajax requests thanks to a CSS hack:
Similar to JavaScript, this works because CSS is not subject to the same-origin policy that affects XMLHttpRequest. Like JSONP, CSSHttpRequest is limited to making GET requests. Unlike JSONP, untrusted third-party JavaScript cannot execute in the context of the calling page.
A request is invoked using the CSSHttpRequest.get(url, callback) function: