Blogless: Blog of Design Less Better.

Validating opacity in CSS 2.1

Opacity-related CSS definitions are the bane of validating, standards-compliant AJAX components. But we can fix that.

Now more than ever, our clients want cool AJAX components for their sites. It seems like more often than not, we find ourselves creating whiz-bang image galleries, file upload forms, and a variety of other interactive components. These components can be tasteful and add much-needed fun to an otherwise run-of-the-mill interaction experience, so we like doing it.

One of the things we don’t like about it, however, is the ease with which web standards can be thrown out the window in the "getting it working" part of the component development. One of the most frustrating culprits is often the family of tags that are required to generate CSS-based opacity effects for interaction elements.

Now, I am generally against using Javascript to apply unsupported CSS definitions as a salvo against the mean red screen of the CSS validator. This is usually a bad idea because, among other reasons, it can fail to degrade gracefully if the user doesn’t have Javascript, and it provides a strategy to allow invalid CSS validate in cases where it really shouldn’t, it’s a little bit clunky when compared to other available methods, and frankly, introducing Javascript into the equation just to validate CSS rarely seems worth the trade-off. That said, in this situation, I think it’s legit because:

  1. The opacity definition(s), while being supported by all current major browsers and darn useful, isn’t included in the CSS 2.1 spec, despite apparently being part of the jetpack-esque CSS 3 spec (::someday::), and doesn’t validate.
  2. In the case of an AJAX component, you’re already requiring that your users have Javascript enabled, and hopefully you have a graceful exit strategy already in play if they don’t.
  3. Your only other choice to achieve the effect you want is to use something like Flash, which is certainly worse even than invalid CSS.

So let’s take a look at how to save your opacity effects and your valid CSS using some handy DOM scripting.

Example: SmoothGallery

I like Mootools. I like its speed, and its clever implementations, and of course, its tiny size. From now until something better comes out, when I write example AJAX, it’s going to use Mootools. It rules. End of plug.

Along with the Mootools framework, I have (several times) used customized versions of JonDesign SmoothGallery, a free Mootools-based AJAX image gallery. It is a very nice little component in many respects, but, being one of these it doesn’t validate, which makes it untenable as a final client solution, at least out of the box.

By brilliant deduction, you will have already gathered that the reason it doesn’t validate is because CSS 2.1 doesn’t support a handful of opacity-related tags that SmoothGallery uses. It is full of CSS definitions that look like this:

filter: alpha(opacity=n);
-moz-opacity: n;
-khtml-opacity: n;
opacity: n;

Which lead to something like this:

Results from the CSS Validator.
Opacity: Does not compute!

To fix this up nicely, I always go in and delete these CSS definitions, and then write a little Javascript function, using the good old Mootools selectors, to apply these events at runtime:

function applyOpacity()
{
    if ($E('a.right'))
    {
        $E('a.right').setStyle("filter:","alpha(opacity=20)");
        $E('a.right').setStyle("-moz-opacity","0.2");
        $E('a.right').setStyle("-khtml-opacity", "0.2");
        $E('a.right').setStyle("opacity", "0.2");
        $E('a.right').addEvent('mouseover', function(e) {
            $E('a.right').setStyle("filter:","alpha(opacity=100)");
            $E('a.right').setStyle("-moz-opacity","1.0");
            $E('a.right').setStyle("-khtml-opacity", "1.0");
            $E('a.right').setStyle("opacity", "1.0");
        });
        $E('a.right').addEvent('mouseout', function(e) {
            $E('a.right').setStyle("filter:","alpha(opacity=20)");
            $E('a.right').setStyle("-moz-opacity","0.2");
            $E('a.right').setStyle("-khtml-opacity", "0.2");
            $E('a.right').setStyle("opacity", "0.2");
        });
    }
}

You’ll note that in addition to setting the default opacity, we have to add some events to mouseover and mouseout. This is because Mootools (currently) doesn’t support CSS pseudoselectors, so we have to replace the .n:hover definitions in the CSS with Javascript events.

Now all we have to do is call this method on domready (or on window load in more old-skool cases):

	window.addEvent('domready',applyOpacity);

Here are the final opacity effects in action, at one of our client sites, Angel Guardians, Inc:

AJAX Slideshow at Angel Guardians, Inc.
Runtime-applied CSS opacity in an image slideshow. Look at the top left and top right corners.

And here’s the gin in your martini:

Results from the CSS Validator.
Opacity, computing!

Hopefully you can see how this abstracts to any situation in which CSS opacity is being used on elements in an AJAX component, and also to any Javascript framework. You can always use document.getElementsByClassName(’right’), or any other selector you
prefer, as well as window.onload = applyOpacity or your choice of any method of attaching a Javascript event.

Update (2008-05-24)

Due to some confusion regarding the application of this technique, I’ve created an example, which you can view online or download (12kb, zip).

These icons link to social bookmarking sites where readers can share and discover new web pages.
PaulMay 12, 2008
 

Comments on this post

1. At 11:32am on Thu, May 15th, Karen of Scottsdale wrote:

I’m using a WordPress plugin called Content Gallery, based on Smooth Gallery. I cleaned up the css as you suggested, but where do I write the javascript code? Using it here: http://www.kingdommediadesign.org/

Also, I get a 520 runtime error in IE. How did you avoid that?

 

2. At 12:03pm on Thu, May 15th, Paul wrote:

Karen,

You can put the applyOpacity function pretty much anywhere you want. I usually have a file of site-specific javascript functions which I include. So you have, in the head section of your HTML (probably in in your Wordpress theme’s header.php) and after the lines that include Mootools and the gallery source files:

<script type="text/javascript" src="http://me.com/js/myFunctions.js" />

Then you have a file called myFunctions.js which looks something like this:

function applyOpacity()
{
    /* Apply opacity styles and events to all required els */
}
window.addEvent('domready',applyOpacity);

Also, with SmoothGallery, you always have a function called startGallery somewhere. If you’re having trouble figuring out the correct place to apply the opacity effects (in the page load order of operations) you can always just add a call to the applyOpacity method to your startGallery function, which has to get added at domready in order for the gallery to work at all:

function startGallery() 
{
	var myGallery = new gallery($('myGallery'), {
		timed: false 
	});
	applyOpacity(); /* Right here. */
}

As far as your error, RFC 2616 doesn’t even define error 520! Try to implement the Javascript as I just described and see if you’re still having problems with IE. I’ve tested this on IE6 & 7 (as far back as Mootools supports) with no problems.

Hope that helps.

 

3. At 10:56am on Fri, May 16th, Karen of Scottsdale wrote:

Thanks for your suggestions, but they didn’t get rid of my error in IE.
The error I’m getting is:
Line:521
Char:4
Error: Type mismatch
Code:0
URL: http://www.kingdommediadesign.org/

 

4. At 1:49pm on Fri, May 16th, Paul wrote:

Karen,

Can you put up your code or a link to your code? As far as I can tell, your site isn’t even referencing a a javascript file that contains this method!

Incidentally, this makes me fairly sure that your IE error is being caused by one of your other javascripts.

 

5. At 3:43pm on Fri, May 16th, Karen of Scottsdale wrote:

My script files are here.

I took out the css codes causing errors. My runtime error only shows when the content gallery plug-in is active. No other scripts are used.

 

6. At 3:46pm on Fri, May 16th, Karen of Scottsdale wrote:

I’m not applying your script as listed above and the runtime error was there before I found your site. It seems to be a problem for others using smoothgallery.

 

7. At 7:23pm on Fri, May 23rd, K. wrote:

Hi. I have a similar problem, but since I don’t know JavaScript, Im having a hard time getting it to work.

Here’s my css code:

.opacity {
background-color: #ffffff; /* the background */
filter:alpha(opacity=20); /* Internet Explorer */
-moz-opacity:0.2; /* Mozilla 1.6 and below */
opacity: 0.2; /* newer Mozilla and CSS-3 */
}

What would the JavaScript file be like so that could work?

 

8. At 5:47pm on Sat, May 24th, Paul wrote:

K - I’ve created an example of this technique. You can view it online or just download the files (12kb, zip). Hopefully, this will clear everything up for you.

 

Post a comment

Name
Email
Url
Please feel free to use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>
Close this
E-mail It