Activate your free membership today | Log-in

Friday, August 28th, 2009

Creating a querySelector for IE that runs at “native speed”

Category: Browsers, CSS

Hello Ajaxians, my name is Paul Young and I am the co-founder of Skybound Software. We're the company behind Stylizer, which is a real-time CSS editing tool. We're taking a pretty radical approach to CSS editing, and as such, a lot of what I do is "web technology research", which is looking for better ways of doing things with a web browser, ultimately so that Stylizer can automate more of the web development process. This has allowed me the chance to discover a few things that have had significant impact on a web developer's workflow, as was the case with State Scope Image Replacement.

In conducting some research for a future version of Stylizer I found a way to create a querySelector method for IE 7 and lower. querySelector is a very useful feature of newer web browsers. It takes a CSS selector as string parameter and returns an array containing the HTML elements that match the selector. Unfortunately it doesn't work in IE 7 and lower... until now :)

My querySelector technique works in IE7 back to IE4 (although I only tested it back to version 6). It's only 327 characters minified, and runs ultra-fast because it doesn't parse strings or traverse the DOM. Keep in mind though that it's using the CSS selector engine built into the browser, which means no funky CSS 3 selector features will work, as they weren't implemented old versions of IE.

In order to explain how it works, I'll need to first cover something else I discovered: Single Execution CSS Expressions (SECEs). These are an enormously powerful technique that unfortunately has been made impossible in IE8. We're using these extensively in the built-in CSS reset feature in Stylizer to eradicate bugs and to add critical but missing features in IE 6 and 7.

About CSS Expressions

The problem with IE's CSS expressions feature is that because they're recalculated hundreds of times per second, they're notoriously slow. Fortunately, I've found a way to ensure they're only executed once per matched element. Examine the code below:

CSS:
  1.  
  2. DIV { -singlex: expression(this.singlex ? 0 : (function(t) { alert(t.tagName); t.singlex = 0; } )(this)); }
  3.  

There are 3 things you need to know to understand how this works:

  • CSS expressions are executed regardless of whether the CSS property name is valid. So "-singlex" is just an arbitrary name.
  • CSS expressions are executed on every matched element. So in the case above, on every div on the page.
  • Inside a CSS expression, the "this" keyword refers to the current matched HTML element.
  • The code above checks to see if the matched element has a property called "singlex". If it does, it just returns 0. Otherwise, it executes an inline function, passing it a reference to the matched element. Inside that function, we can perform whatever processing we want. At the end, we set a flag on the element to ensure that the function won't be executed again.

This is how you can do complex processing inside a CSS expression without having to worry about a performance hit. The function only executes on the first execution of the expression, and then on every subsequent execution, 0 is returned instantly. The performance cost of running an if test and returning 0 is negligible, even if you're doing it thousands of times per second. If you paste that CSS into a page with 3 div elements on it, in IE it will alert "DIV" 3 times.

The things you can do with SECE's are basically limited only by your imagination. Here is an example of using one to fake the CSS content property in IE 7 and lower:

CSS:
  1.  
  2. /* Newer browsers */ DIV:after { content: "Generated content!"; } /* IE 7 and lower */ DIV { -singlex: expression(this.singlex ? 0 : (function(t) { t.innerHTML += "Generated content!"; this.singlex = 0; } )(this)); }
  3.  

You can use SECEs to fake all sorts of things like generated content, min-width and min-height, CSS counters, CSS outlines, and more. But most importantly, you can...

Create a querySelector method with Single Execution CSS Expressions!

Creating a querySelector method is just a matter of dynamically adding a SECE to a page that copies a reference to each matched HTML element into a globally accessible array, and then returning that array. Examine the code below:

JAVASCRIPT:
  1.  
  2. /*@cc_on if (!document.querySelector) document.querySelector = function(selector) { // Add a new style sheet to the page var head = document.documentElement.firstChild; var styleTag = document.createElement("STYLE"); head.appendChild(styleTag); // Create a globally accessible element array document.__qsResult = []; // Create the SECE that copies all matched // elements to document.__qsResult. styleTag.styleSheet.cssText = selector + "{qs: expression(this.__qs?0:(function(t){document.__qsResult.push(t);t.__qs=0;})(this));}"; // Reflow the page. Without this, the SECE won't execute. window.scrollBy(0, 0); // Clean up and return head.removeChild(styleTag); return document.__qsResult; } @*/
  3.  

There you have it! The function is wrapped in a conditional compilation comment to make sure only IE 7 and lower can see it. Here is a minified version for convenience:

JAVASCRIPT:
  1.  
  2. /*@cc_on if(!document.querySelector)document.querySelector=function(s){d=document;h=d.documentElement.firstChild;t=d.createElement("STYLE");h.appendChild(t);d.__q=[];t.styleSheet.cssText=s+"{x:expression(this.__q?0:(function(t){document.__q.push(t);t.__q=0;})(this));}";window.scrollBy(0, 0);h.removeChild(t);return d.__q;}@*/
  3.  

I hope you can make use of SECEs and this querySelector method. Maybe it even has a place in jQuery? I don't know. (John Resig, are you reading? :)

UPDATE

After thinking this through a little further, I realized that you don't need to use a SECE at all for this, just a CSS expression added with JavaScript will do. Also, one of the commenters (Jordan1) pointed out that the code wouldn't return elements that had already been queried once. I've posted an update to the code below that should rectify the issue:

JAVASCRIPT:
  1.  
  2. /*@cc_on if (!document.querySelector)
  3.         document.querySelector = function(selector)
  4.         {
  5.             var head = document.documentElement.firstChild;
  6.             var styleTag = document.createElement("STYLE");
  7.             head.appendChild(styleTag);
  8.             document.__qsResult = [];
  9.            
  10.             styleTag.styleSheet.cssText = selector + "{x:expression(document.__qsResult.push(this))}";
  11.             window.scrollBy(0, 0);
  12.             head.removeChild(styleTag);
  13.            
  14.             var result = [];
  15.             for (var i in document.__qsResult)
  16.                 result.push(document.__qsResult[i]);
  17.             return result;
  18.         }
  19.     @*/
  20.  

NOTE: Fancy writing a guest post for Ajaxian? Got some tips on content that we haven't covered? Please email us, or tweet me :)

Posted by Dion Almaer at 6:13 am
32 Comments

++++-
4.3 rating from 43 votes

Sunday, August 23rd, 2009

CSS 3 Flexible Box Model

Category: CSS

Alex Russell has been having a really interesting discussion with some standards folks about what is wrong on the Web right now, and it narrowed down to discuss CSS variables as a case study (it aint perfect, but get DRY and ship it!)

Alex tells it how it is, but people forget that he does this as he is passionate about the Web, and that he does also give credit and positive outlook IF it is due!

His latest post shows this as he talked about CSS 3 progress and specifically the flexible box model that Mozilla and WebKit have had forevaaaaaah:

David Baron (of Mozilla fame) is editing a long-overdue but totally awesome Flexible Box spec, aka: “hbox and vbox”. Both Gecko and WebKit-derived browsers (read: everything that’s not IE) supports hbox and vbox today, but using it can be a bit tedious. Should you be working on an app that can ignore IE (say, for a mobile phone), this should help make box layouts a bit easier to get started with:

CSS:
  1.  
  2. /* hbox and vbox classes */
  3.  
  4. .hbox {
  5.         display: -webkit-box;
  6.         -webkit-box-orient: horizontal;
  7.         -webkit-box-align: stretch;
  8.  
  9.         display: -moz-box;
  10.         -moz-box-orient: horizontal;
  11.         -moz-box-align: stretch;
  12.  
  13.         display: box;
  14.         box-orient: horizontal;
  15.         box-align: stretch;
  16. }
  17.  
  18. .hbox> * {
  19.         -webkit-box-flex: 0;
  20.         -moz-box-flex: 0;
  21.         box-flex: 0;
  22.         display: block;
  23. }
  24.  
  25. .vbox {
  26.         display: -webkit-box;
  27.         -webkit-box-orient: vertical;
  28.         -webkit-box-align: stretch;
  29.  
  30.         display: -moz-box;
  31.         -moz-box-orient: vertical;
  32.         -moz-box-align: stretch;
  33.  
  34.         display: box;
  35.         box-orient: vertical;
  36.         box-align: stretch;
  37. }
  38.  
  39. .vbox> * {
  40.         -webkit-box-flex: 0;
  41.         -moz-box-flex: 0;
  42.         box-flex: 0;
  43.         display: block;
  44. }
  45.  
  46. .spacer {
  47.         -webkit-box-flex: 1;
  48.         -moz-box-flex: 1;
  49.         box-flex: 1;
  50. }
  51.  
  52. .reverse {
  53.         -webkit-box-direction: reverse;
  54.         -moz-box-direction: reverse;
  55.         box-direction: reverse;
  56. }
  57.  
  58. .boxFlex0 {
  59.         -webkit-box-flex: 0;
  60.         -moz-box-flex: 0;
  61.         box-flex: 0;
  62. }
  63.  
  64. .boxFlex1, .boxFlex {
  65.         -webkit-box-flex: 1;
  66.         -moz-box-flex: 1;
  67.         box-flex: 1;
  68. }
  69.  
  70. .boxFlex2 {
  71.         -webkit-box-flex: 2;
  72.         -moz-box-flex: 2;
  73.         box-flex: 2;
  74. }
  75.  
  76. .boxGroup1 {
  77.         -webkit-box-flex-group: 1;
  78.         -moz-box-flex-group: 1;
  79.         box-flex-group: 1;
  80. }
  81.  
  82. .boxGroup2 {
  83.         -webkit-box-flex-group: 2;
  84.         -moz-box-flex-group: 2;
  85.         box-flex-group: 2;
  86. }
  87.  
  88. .start {
  89.         -webkit-box-pack: start;
  90.         -moz-box-pack: start;
  91.         box-pack: start;
  92. }
  93.  
  94. .end {
  95.         -webkit-box-pack: end;
  96.         -moz-box-pack: end;
  97.         box-pack: end;
  98. }
  99.  
  100. .center {
  101.         -webkit-box-pack: center;
  102.         -moz-box-pack: center;
  103.         box-pack: center;
  104. }
  105.  

With this core baseline CSS you can then do great things such as easily vertically align (duh!)

HTML:
  1.  
  2. <div class="hbox center">
  3.     <div class="vbox center">
  4.         <div>...</div>
  5.         <div>...</div>
  6.     </div>
  7. </div>
  8.  

and smart grouping:

HTML:
  1.  
  2. <form action="handler.cgi" method="POST" class="hbox">
  3.         <div class="vbox">
  4.                 <label>First Name (required):</label>
  5.                 <label>Last Name:</label>
  6.         </div>
  7.         <div class="vbox">
  8.                 <input type="text" name="first"/>
  9.                 <input type="text" name="last"/>
  10.                 <input type="submit"/>
  11.         </div>
  12. </form>
  13.  

The mighty Erik Arvidsson also reminds us of the CSS3 attr() support (already in Firefox, coming in WebKit too) that would enable us to wire up <div class=vbox flex=2>…</div>.

Although you may be thinking "this is great, but freaking IE means that I don't care about it." True. It would be awesome if someone took a shim that could grok this CSS (we built a CSS parser for Thunderhead) and make it work in IE etc. But until that day, or the day that IE implements it (heh) what can you do?

Write iPhone or Palm webOS or Android WebKit apps? You can use it right friggin now!

Posted by Dion Almaer at 6:22 am
10 Comments

++++-
4.2 rating from 21 votes

Tuesday, August 18th, 2009

CSS improvements, speed, and more with Firefox 3.6 alpha

Category: Browsers, CSS, Mozilla

Firefox 3.6 alpha releases have already arrived and there are already cool new features on the heals of the 3.5 release, as well as rapid speed improvements.

People have focused on the new CSS improvements (Acid3 now gets 94/100) such as the tweaked CSS gradient support:

CSS:
  1.  
  2. .heading {
  3.   background: #729FCF -moz-linear-gradient(left top, left bottom,
  4.     from(rgba(255, 255, 255, 0.45)), to(rgba(255, 255, 255, 0.50)),
  5.     color-stop(0.4, rgba(255, 255, 255, 0.25)),
  6.     color-stop(0.6, rgba(255, 255, 255, 0.0)),
  7.     color-stop(0.9, rgba(255, 255, 255, 0.10)));
  8.   color: white;
  9.   height: 40px;
  10. }
  11.  

We also get new background rules such as background-size and multiple backgrounds.

Read more 3.6 for developers info:

  • The reorder event is now sent to embedded frames and iframes when their document is loaded. See
    bug 420845.
  • The getBoxObjectFor() method has been removed, as it was non-standard and exposed even more non-standard stuff to the web. See
    bug 340571.  Also affects mootools which uses this call for Gecko detection.  See this mootools bug.
  • A new attribute has been created, mozScreenPixelsPerCSSPixel, for obtaining the amount of screen pixels per CSS pixel on nsIDOMWindowUtils . This can be used in conjunction with the new global properties, mozInnerScreenX and mozInnerScreenY, to compute screen coordinates. See

    bug 486200 and
    bug 507755.

  • When the page's URI's document fragment identifier (the part after the "#" (hash) character) changes, a new hashchange event is sent to the page. See window.onhashchange for more information.
  • Geolocation "address" support is now available enabling user-readable position information.  See

    bug 503942.

  • The attribute document.readyState is now supported. Gecko also supports document.onreadystatechange now.
  • Support for HTML 5's element.classList to allow easier handling of the class attribute.

Posted by Dion Almaer at 6:49 am
8 Comments

++++-
4.5 rating from 31 votes

Wednesday, July 29th, 2009

Chroma Hash: Interesting visualization of your password

Category: CSS, jQuery

Matt Thompson has created a fun little jQuery plugin called Chroma-Hash that "dynamically visualizes secure text-field values using ambient color bars":

Password entry can be frustrating, especially with long or difficult passwords. On a webpage, secure fields obscure your input with •'s, so others can't read it. Unfortunately, neither can you—you can't tell if you got your password right until you click "Log In".

Chroma-Hash displays a series of colored bars at the end of field inputs so you can instantly see if your password is right. Chroma-Hash takes an MD5 hash of your input and uses that to compute the colors in the visualization. The MD5 hash is non-reversible, so no one could know what your password just from the colors. Your password will display the same sequence each time, so you can learn to expect "blue, red, pink", for instance; if you instead see "green, purple, yellow", you'll know you typed it wrong.

Here is a snippet of the magic:

JAVASCRIPT:
  1.  
  2.               $(this).css({position:   'absolute',
  3.                            left:       position.left + width - 2,
  4.                            top:        position.top,
  5.                            height:     height + "px",
  6.                            width:      8 + "px",
  7.                            margin:     5 + "px",
  8.                            marginLeft: -8 * (i + 1) + "px"
  9.                           }
  10.                     );
  11.               });
  12.          
  13.               var id     = $(this).attr('id');
  14.               var md5    = hex_md5($(this).val());
  15.               var colors = md5.match(/([\dABCDEF]{6})/ig);
  16.               $(".chroma-hash").stop();
  17.  
  18.               chromaHashesForElement(this).each(function(i) {
  19.                 $(this).animate({backgroundColor:"#" + colors[i]});
  20.               });
  21.  

Posted by Dion Almaer at 5:35 pm
10 Comments

+++--
3.7 rating from 46 votes

Text rotation for all

Category: CSS, Tip

Jonathan Snook has posted a nice nugget on text rotation with CSS that takes a nice bit of markup like this:

HTML:
  1.  
  2. <div class="example-date">
  3.   <span class="day">31</span>
  4.   <span class="month">July</span>
  5.   <span class="year">2009</span>
  6. </div>
  7.  

and converts it to:

all via the CSS:

CSS:
  1.  
  2. -webkit-transform: rotate(-90deg);
  3. -moz-transform: rotate(-90deg);
  4. filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3);
  5.  

Yup, even IE.

Posted by Dion Almaer at 10:20 am
33 Comments

++++-
4.3 rating from 52 votes

Tuesday, July 28th, 2009

CSS Gradients for All!

Category: CSS

Weston Ruter has created a very cool library that enables CSS gradients on non-WebKit browsers (at least, a subset). Incredibly cool:

CSS Gradients via Canvas provides a subset of WebKit's CSS Gradients proposal for browsers that implement the HTML5 canvas element.

To use, just include css-gradients-via-canvas.js (12KB) anywhere on the page (see examples below). Unlike WebKit, this implementation does not currently allow gradients to be used for border images, list bullets, or generated content. The script employs document.querySelectorAll()—it has no external dependencies if this function is implemented; otherwise, it looks for the presence of jQuery, Prototype, or Sizzle to provide selector-querying functionality.

The implementation works in Firefox 2/3+ and Opera 9.64 (at least). Safari and Chrome have native support for CSS Gradients since they use WebKit, as already mentiond.

This implementation does not work in Internet Explorer since IE does not support Canvas, although IE8 does support the data: URI scheme, which is a prerequisite (see support detection method). When/if Gears's Canvas API fully implements the HTML5 canvas specification, then this implementation should be tweakable to work in IE8. In the mean time, rudimentary gradients may be achieved in IE by means of its non-standard gradient filter.

CSS Gradients via Canvas works by parsing all stylesheets upon page load (DOMContentLoaded), and searches for all instances of CSS gradients being used as background images. The source code for the external stylesheets is loaded via XMLHttpRequest—ensure that they are cached by serving them with a far-future Expires header to avoid extra HTTP traffic.

The CSS selector associated with the gradient background image property is used to query all elements on the page; for each of the selected elements, a canvas is created of the same size as the element's dimensions, and the specified gradients are drawn onto that canvas. Thereafter, the gradient image is retrieved via canvas.toDataURL() and this data is supplied as the background-image for the element.

An aside. I only just noticed the Gears Canvas API. It doesn't quite do what you think..... I always wanted to implement Canvas in Gears. It is also strange that Gears is so under the radar at Google these days. One blog post per year?. I guess all of the work is going into Chrome / WebKit itself.

Posted by Dion Almaer at 6:00 am
15 Comments

++---
2.9 rating from 24 votes

Thursday, July 23rd, 2009

Multiple font weights via CSS 3 and more font fun

Category: CSS

Ilia Draznin has been using CSS3 font face to fake font weights:

The way @font-face works is that whatever font attributes you specify for a @font-face rule, they don’t determine how the font looks but rather when it’s gonna get used. For example if you have the following two rules

CSS:
  1.  
  2. @font-face {
  3.     font-family: newfont;
  4.     src: local(Arial);
  5.     font-weight: 200;
  6. }
  7.  
  8. @font-face {
  9.     font-family: newfont;
  10.     src: local(Calibri);
  11.     font-weight: 300;
  12. }
  13.  

Then if you use the “newfont” font-family with weight 200 it’s going to use Arial, but if you use it with weight 300 it’s going to use Calibri. So we can take advantage of that, and since it uses @font-face we don’t even have to worry if the user’s computer has fonts or not.

We posted on TypeKit recently, and we have another playa Kernest in the "fix friggin type on the Web" game.

And for a final little nugget of font goodness, from @schill:

Typekit looks to include jQuery, loads CSS with base64-encoded data:font/otf URLs for @font-face. "Safer" than a plain open .TTF, I suppose.

Posted by Dion Almaer at 6:47 am
3 Comments

+++--
3.7 rating from 24 votes

Friday, July 17th, 2009

More on 3D CSS Transforms

Category: Browsers, CSS

Following up on the earlier coverage we are back with more info on 3D transforms. Simon Fraser has posted details on the WebKit blog.

He shows off a couple of cool examples:

The post goes into detail on the new CSS such as:

CSS:
  1.  
  2. translate3d(x, y, z), translateZ(z)
  3.  
  4. scale3d(sx, sy, sz), scaleZ(sz)
  5.  
  6. rotateX(angle), rotateY(angle), rotate3d(x, y, z, angle),
  7.  
  8. perspective(p)
  9. -webkit-transform: perspective(500px) rotateY(20deg);
  10.  
  11. matrix3d()
  12.  
  13. -webkit-transform-origin now accepts three values, allowing you to specify a z offset for the transform origin.
  14.  
  15. -webkit-perspective
  16.  
  17. -webkit-backface-visibility
  18.  

Jay Sparks has also been playing with these properties as he built a 3D draggable cube.

Posted by Dion Almaer at 5:39 am
5 Comments

+++++
5 rating from 18 votes

Thursday, July 16th, 2009

A new way to do layout; CSS Scripting Layout

Category: CSS, Chrome

CSS is great for styling, but can be agonizing for laying out applications. There have been attempts to do JavaScript powered layout, but what about adding more semantics to CSS itself?

Darrel Karisch has posted on just that, with his CSS Scripting Layout:

This document describes a new set of CSS properties and object specifications that together compose a powerful declarative means to describe complex arbitrary layout criteria that are both reusable and extensible. The new properties are Javascript expressions that are woven together in a constraint resolving system to perform a specified layout. Additionally, a set of global objects defined in the constraint resolution Javascript execution environment enable powerful operations to be expressed succinctly resulting in more readable and compact layout specifications.

CSS:
  1.  
  2. @layout-policy name
  3. {
  4.      container-script:”arbitrary Javascript”
  5.      container-width:”…”
  6.      container-height:”…”
  7.      rectangle-attributes:”Javascript Associative Array”
  8.      left:”arbitrary Javascript”
  9.      horizontal-center:”…”
  10.      right:”…”
  11.      width:”…”
  12.      top:”…”
  13.      vertical-center:”…”
  14.      bottom:”…”
  15.      height:”…”
  16. }
  17.  

An prototype implementation has been coded as a Chrome extension, and to get this:

you code CSS like this:

CSS:
  1.  
  2. @layout-policy pack_column {
  3. container-script: "\
  4. var margin=container.em(0.5);\
  5. ";
  6. rectangle-attributes: "{\
  7. 'topOffset':0\
  8. }";
  9. horizontal-center:"container.width/2";
  10. top: "rectangle.topOffset+margin\
  11. +(predecessor ? predecessor.bottom : 0)";
  12. container-height: "margin*(rectangles.length+1)\
  13. +rectangles.height.sum+rectangles.topOffset.sum";
  14. container-width: "2*margin+rectangles.width.max";
  15. }
  16. @layout-policy override {
  17. container-script: "\
  18. var margin=container.em(0.25)\
  19. ";
  20. horizontal-center:none;
  21. left:"margin";
  22. }
  23. @layout-policy pack_row {
  24. container-script: "\
  25. var margin=0;\
  26. ";
  27. vertical-center:"container.height/2";
  28. left:"margin+(predecessor ? predecessor.right : 0)";
  29. container-width:"margin*(rectangles.length+1)\
  30. +rectangles.width.sum";
  31. container-height:"2*margin+rectangles.height.max;";
  32. }
  33. .body {
  34.     layout-policy: 'pack_column';
  35.     position:relative;
  36.     border:1px black dashed;
  37.     padding:0px;
  38. }
  39. .container {
  40.     layout-policy: 'pack_row';
  41.     container-script: "margin=container.ex(2);"; /* apply a margin */
  42.     position:absolute;
  43.     border:1px black solid;
  44.     padding:0px;
  45. }
  46. .container1 {
  47.     layout-policy: 'pack_column override';
  48.     width:130px;
  49.     position:absolute;
  50.     border:1px black dotted;
  51.     margin:0px;
  52.     padding:0px;
  53. }
  54. .text {
  55.     position:absolute;
  56.     border:1px black dashed;
  57.     padding:0px;
  58. }
  59. .extension {
  60.     rectangle-attributes: "{\
  61. 'topOffset':'container.em(1)+margin'\
  62.     }";
  63.     width:200px;
  64.     padding:10px;
  65. }

Huh. What do you think?

Posted by Dion Almaer at 11:46 pm
31 Comments

+----
1.8 rating from 55 votes

Sunday, July 12th, 2009

3D CSS Effects with Safari on Snow Leopard

Category: CSS, Safari, Showcase

The iPhone has had these wicked cool 3D transforms hardware accelerated for awhile. We haven't seem them in desktop Safari though, until now.

Charles Ying shows us Snow Stack:

Oh, was there some Microsoft plugin launched last week? We don't need no stinkin' plugin!

Charles tells us more:

  • Larger images load in after 2 seconds for high quality zoomed images.
  • State changes are handled via CSS.
  • Reflections use CSS masks instead of a Canvas draw (standard box reflections don’t quite work yet).
  • Reflections sit on a scaleY(-1.0) coordinate system and are tracked independently, which is surprisingly easy.
  • This demo pushed a few performance limits and currently avoids drawing and animating a drop shadow and border.
  • On Leopard, animating transforms with a transform list need to have only 1 function to animate in hardware.
  • Some expensive CSS selectors are used, and haven’t been fixed yet. (in progress)
  • Almost all of this is hardware accelerated on Snow Leopard. About the only thing that isn’t is the networked image loading.
  • Key states are tracked manually (timers handle keyboard delay and repeats) so a smooth motion can be achieved when the keys are held down.
  • Cell sizes are chosen at initial window load time and don’t change on window resize, although the origin does. It’s rather slow, however, so I may end up changing that.
  • To give you a sense of the effort involved, this demo was written over 3 days, a few hours each evening.

All via @joehewitt:

Wow, Safari on Snow Leopard does hardware-acelerated CSS 3D transforms!

Posted by Dion Almaer at 4:43 pm
26 Comments

++++-
4.4 rating from 40 votes

Friday, June 26th, 2009

Fun with text-shadow

Category: CSS, Examples

Zach Johnson is at it again, this time giving us a fun Friday treat with CSS text shadow, all via:

JAVASCRIPT:
  1.  
  2. document.getElementById('text-shadow-box').onmousemove = function(e) {
  3.     var xm = e.clientX - 300;
  4.     var ym = e.clientY - 175;
  5.     var d = Math.sqrt(xm*xm + ym*ym);
  6.     text.style.textShadow = -xm + 'px ' + -ym + 'px ' + (d / 5 + 10) + 'px black';
  7.    
  8.     xm = e.clientX - 600;
  9.     ym = e.clientY - 450;
  10.     spot.style.backgroundPosition = xm + 'px ' + ym + 'px';
  11. }
  12.  

Posted by Dion Almaer at 11:26 am
14 Comments

+++--
3.9 rating from 36 votes

Tuesday, June 23rd, 2009

Sprite Me! Helping you sprite up, but maybe you shouldn’t?

Category: CSS, Performance

There have been many tools to help make image spriting easier, by packaging up your images into one large image and splitting it up again via CSS.

Steve Souders just showed off a new little tool he created, Sprite Me at the Velocity conference that kicked off today. He has made it easier to work with sprites by:

  • finds background images: SpriteMe generates a list of all background images in the page. Hovering over the its URL displays the image.
    Each of the DOM elements that use that image are also listed. [DONE]
  • groups images: It's hard to figure out which images can be sprited together, and how they should be laid out. For example, background images that repeat horizontally must fill the entire width of the sprite. Background images positioned left bottom must be at the right top of the sprite if their container might be bigger than the image. SpriteMe determines which images should be sprited together based on these constraints.[IN PROCESS]
  • creates sprites: SpriteMe generates the sprite for each grouping of images. This is done using open source tools, such as CSS Sprite Generator. [TBD]
  • updates CSS: The final tricky part of using sprites is changing the CSS. Sometimes the CSS is a rule in a stylesheet. Or it might be a rule in an inline style block. Or it might be specified in an element's style attribute. Because SpriteMe runs inside your web page, it can find the CSS that needs to be updated. It makes the changes in realtime, so you can visually check to confirm the sprites look right.You can export the modified CSS to integrate back into your code. [TBD]

Great, a simple new bookmarklet to work with Sprites. It is always a good idea to sprite up right? Not exactly.

Vlad Vuki?evi?, a leader in the Mozilla community (and brought us cool stuff like Canvas 3D!) has spoken up on the internals of the browser, which shows you the trade-offs for the spriting approach:

The biggest problem with CSS sprites is memory usage. Unless the sprite image is carefully constructed, you end up with incredible amounts of wasted space. My favourite example is from WHIT TV's web site, where this image is used as a sprite. Note that this is a 1299x15,000 PNG. It compresses quite well — the actual download size is around 26K — but browsers don't render compressed image data. When this image is downloaded and decompressed, it will use almost 75MB in memory (1299 * 15000 * 4). If the image didn't have any alpha transparency, this could be maybe optimized to 1299 * 15000 * 3, though often at the expense of rendering speed. Even then, we'd be talking about 55MB. The vast majority of this image is blank; there is nothing there, no useful content whatsoever. Just loading the main WHIT page will cause your browser's memory usage to go up by at least 75+MB, just due to that one image.

That's not the right tradeoff to make for a website.

What alternatives are there? None right now.... but they are hopefully on the way. Some folks have been talking about the idea of packaging up images in zip files, and then the browser can manage more than just the download process, but also only load up what it needs:

Many browsers have support for offline manifests already; it might be possible to extend that to allow downloading one file (like a jar/zip file) that contains a manifest of resources and equivalent URLs that are contained inside it.

Rob Sayre, also of Mozilla, broached the subject:

Sprites have the advantage of working right now, but maybe there should be a way to serve up a multipart response with your sprite images as well. That would cut down on CSS rule count and maintenance, but still group the images in one HTTP request. Authors are already giving up the advantages of separate resources in return for speed, so maybe this is worth doing.

You can (in theory… haha) get some of these advantages with HTTP pipelining, but a multipart response would allow the server optimize the response order as they do with sprites today.

Posted by Dion Almaer at 12:01 am
7 Comments

++++-
4.1 rating from 23 votes

Monday, June 22nd, 2009

Fun with 3D CSS and video

Category: CSS, Video

How about starting the week with something fun. Zach Johnson has been having fun with 3D effects via CSS such as his isocube above, which is brought to you with simple HTML (including a video tag for a playing video on the surface!) and some CSS like this:

CSS:
  1.  
  2. .face {
  3.     position: absolute;
  4.     width: 200px;
  5.     height: 200px;
  6.     overflow: hidden;
  7.     font-family: monospace;
  8.     font-size: 24px;
  9. }
  10.  
  11. .top {
  12.     top: 0;
  13.     left: 89px;
  14.     background: #fff;
  15.     color: #999;
  16.     -webkit-transform: rotate(-45deg) skew(15deg, 15deg);
  17.     -moz-transform: rotate(-45deg) skew(15deg, 15deg);
  18. }
  19.  
  20. .left {
  21.     top: 155px;
  22.     left: 0;
  23.     background: #999;
  24.     color: #333;
  25.     -webkit-transform: rotate(15deg) skew(15deg, 15deg);
  26.     -moz-transform: rotate(15deg) skew(15deg, 15deg);
  27. }
  28.  
  29. .right {
  30.     top: 155px;
  31.     left: 178px;
  32.     background: #ccc;
  33.     color: #666;
  34.     -webkit-transform: rotate(-15deg) skew(-15deg, -15deg);
  35.     -moz-transform: rotate(-15deg) skew(-15deg, -15deg);
  36. }
  37.  
  38. .shadow {
  39.     top: 310px;
  40.     left: -89px;
  41.     background: black;
  42.     opacity: 0.5;
  43.     -webkit-transform: rotate(-45deg) skew(15deg, 15deg);
  44.     -moz-transform: rotate(-45deg) skew(15deg, 15deg);
  45. }
  46.  

Chris Blizzard posted his Open Video Conf talk on connecting HTML5 video showcasing the great demos of Paul Rouget :)

Posted by Dion Almaer at 7:14 am
10 Comments

+++--
3.5 rating from 25 votes

Monday, June 15th, 2009

CSS3 breaking in the design community

Category: CSS

CSS3 properties can greatly improve your workflow, making some of the most time-consuming CSS tasks a breeze and allowing for better, cleaner and more lightweight markup. Some properties are still not widely supported, even by the most recent browsers, but that doesn’t mean we shouldn’t experiment with them or give visitors with modern browsers advanced features and CSS styling.

In this regard, keep in mind that educating our clients is both useful and necessary: websites don’t have to look exactly the same in every browser, and if a difference doesn’t negatively affect the aesthetics or usability of a website, it should be considered. If we continue to waste valuable time and money making every detail pixel-perfect (instead of adopting more flexible and future-oriented solutions), users won’t have an incentive to upgrade their browsers, in which case we would have to wait a long time before older browsers become legacy browsers and robust modern browsers become the standard.

The earlier we experiment with and adapt new CSS3 properties, the earlier they will be supported by popular browsers and the earlier we’ll be able to use them widely.

The words above are a conclusion in a piece in Smashing Magazine on taking your design to the next level with CSS3.

The post goes into details with case studies and examples for a huge set of enhancements available in modern browsers:

  • Selector improvement
  • RGBA and Opacity
  • Multi-Column Layout
  • Multiple Backgrounds
  • Word Wrap
  • Text Shadow
  • @font-face Attribute
  • Border Radius
  • Border Image
  • Box Shadow
  • Box Sizing
  • Media Queries
  • Speech

Take a walk through the article and play with the ideas. I really like Tim Van Damme's site!

Posted by Dion Almaer at 11:41 am
7 Comments

++++-
4.5 rating from 35 votes

Wednesday, June 10th, 2009

Styling buttons as links allowing you to POST away

Category: CSS, Examples

Have you ever wanted to just <a href="path" action="post">? Remember the hub-ub with the old Google Web Accelerator and how it started to crawl links to delete actions that were mistakenly using GET?

Natalie Downe has written up a piece on styling HTML buttons as links which means that you can somewhat get the same effect. It shows how you can use an inline span to get the hover effect, taking:

HTML:
  1.  
  2. <button type="submit" class="link"><span>Hello there I am a button</span></button>
  3.  

and styling it with:

CSS:
  1.  
  2. button {
  3.         overflow: visible;
  4.         width: auto;
  5. }
  6. button.link {
  7.         font-family: "Verdana" sans-serif;
  8.         font-size: 1em;
  9.         text-align: left;
  10.         color: blue;
  11.         background: none;
  12.         margin: 0;
  13.         padding: 0;
  14.         border: none;
  15.         cursor: pointer;
  16.        
  17.         -moz-user-select: text;
  18.  
  19.         /* override all your button styles here if there are any others */
  20. }
  21. button.link span {
  22.         text-decoration: underline;
  23. }
  24. button.link:hover span,
  25. button.link:focus span {
  26.         color: black;
  27. }
  28.  

You can see the simple example in action.

Posted by Dion Almaer at 3:15 am
16 Comments

++++-
4 rating from 14 votes

Tuesday, June 2nd, 2009

CSS Gradient Tool; Build the Apple Navigation Bar

Category: CSS, Utility

John Allsop has created a very cool CSS gradient exploration tool that lets you get the gradient you need, with the resulting sample and code right there.

You could use it to do what he did, and recreate the Apple navigation bar in pure CSS instead of using images.

John didn't stop there, and has already created tools for Box Shadows Shadows and Radial Gradients.

Posted by Dion Almaer at 8:25 am
6 Comments

+++--
3.5 rating from 20 votes

« Previous PageNext Page »