Thursday, March 30, 2006

IE CSS Expressions - Javascript Disabled

On my test machine, I have found that IE's proprietary CSS expressions do not work with JavaScript disabled. This is in conflict with a number of postings on the subject, including this one at Position Is Everything. Midway down the page, it says:

The upper limit is enforced by a max-width on #sizer, and IEwin is included
via an "expression" hidden in a Conditional Comment in the head. While this is a
script, the user cannot disable this type of CSS expression when disabling
JavaScript.



I'm thinking that this probably USED to be true, and has since been changed by a security patch. Does anyone know for sure?

Was this post helpful to you? If so, please consider making a small donation to keep this blog going.

Wednesday, March 29, 2006

Differences between Element.offsetWidth and CSS width property

I'm sure most CSS jockeys are probably already aware of this, but I'll make a note of it for posterity.

This information is specifically for IE6 in Strict mode. Other browsers differ in their implementation of the box model.

The width property in CSS and the offsetWidth property in JavaScript are two very different things. For example, if you set an element's width to 500px in CSS, the element's offsetWidth may not be 500, depending on the margins, borders, and padding you have applied to the element. Here's how it breaks down:

Element.offsetWidth = CSS width + total horizontal padding width + total horizontal border width

Example:

width:300px, border:5px solid green, padding:5px, margin:5px


In IE6 strict mode, the offsetWidth will return 320, rather than 300 as you might expect. Also, offsetWidth does not include the margin, so to get the actual width that the element takes up on the screen, you have to add the total horizontal margin to the offsetWidth.

Was this post helpful to you? If so, please consider making a small donation to keep this blog going.

Tuesday, March 28, 2006

Max-width in IE Using a CSS Expression

This post is a continuation of the "How Many Pixels in an EM?" series I have been working on, although now that I know exactly how to calculate the number of pixels in an em, I've moved on to refining other aspects of the expression itself, and so I've decided to move away from that title.

I contacted Svend Tofte himself regarding this work, and he took time away from his very busy schedule to give me some very valuable feedback (many thanks to Svend!). He pointed out to me that expressions that may work well in quirks mode can cause the browser to crash in strict mode, due to differences in the box model than can trigger infinite loops.

As I am no stranger to danger, I slapped a strict doctype on my test page and... voila... brought my mighty workstation to its knees. CTRL-ALT-DELETE did nothing. I actually had to manually switch off the box for the first time ever.

As soon as I could power back up, I removed all margins, padding, and borders from my test elements, loaded the page, and started resizing my browser like a madman. The divs scaled perfectly this time... No locked-up IE, no smoke coming off my CPU, just good old-fashioned max-width joy.

To make this long story short (or at least a reasonable length) I did some investigating and found that you have to factor in the total width of your margins, padding, and borders in order to use the expression safely in strict mode. Since you're testing the offsetWidth and then setting the CSS width property, you have to compensate for the differences between the two. Otherwise, it is possible for the expression to enter an infinite loop where setting the width of the element causes the parent element to change its size, which again fires the expression, and so on.

Without further adieu, here is the expression in all its hairy glory:

width:expression((this.parentElement.offsetWidth - (parseInt(this.parentElement.currentStyle.paddingLeft)+parseInt(this.parentElement.currentStyle.paddingRight)+parseInt(this.parentElement.currentStyle.borderLeftWidth)+parseInt(this.parentElement.currentStyle.borderRightWidth)))
> ( Math.round((30*(screen.deviceXDPI?screen.deviceXDPI:96)/72)*parseInt(document.body.currentStyle.fontSize)) + (parseInt(this.currentStyle.marginLeft)+parseInt(this.currentStyle.marginRight)+parseInt(this.currentStyle.paddingLeft)+parseInt(this.currentStyle.paddingRight)+parseInt(this.currentStyle.borderLeftWidth)+parseInt(this.currentStyle.borderRightWidth)))
? "30em":"auto");
Quite a beast, no? Pretty it's not, but it works really well in strict mode, in IE 5, 5.5, and 6. With any combination of margins, borders, and padding you care to throw at it, and at any screen resolution. Don't believe me? Take a look at my test page.

There are two places where you have to specify the desired max-width. Just replace the number 30 with the number of your choosing. You can also replace "auto" with another value, but I would be very careful when doing so. If that value should somehow evaluate to greater than your max-width value, I would expect to start seeing flames shooting out of your USB ports. ;) (ok, so maybe I'm being dramatic).

I'll be testing variations on this expression in the near future, so stop back and check out my progress. Also, please check out the test page and let me know how it works for you!

Was this post helpful to you? If so, please consider making a small donation to keep this blog going.

Bump Mapping in Flash 8

This is just awesome. Ralph Hauwert at http://www.unitzeroone.com/ is doing some great stuff in the "you mean you can do that in Flash?!!" department. I'm curious to see how these techniques become utilized in real-world artwork, as opposed to the laboratory.

Was this post helpful to you? If so, please consider making a small donation to keep this blog going.

Technique: Google Analytics for Dynamic Pages

I'm evaluating Google Analytics, and I'm fairly impressed so far. Not bad, for free stuff!

The first question that I had after reading the installation notes was "How do I track different states of a dynamic page?". For example, it is quite common to use Panel controls in ASP.Net to show different steps in a multi-step form, rather than having a separate page for each step. Since the Analytics urchinTracker Javascript is embedded once on each unique page, I was concerned that different states of a dynamic page would be untrackable.

Fortunately, this is not the case. You can call the urchinTracker JavaScript call from each state of your dynamic page, and simply pass it a made-up page name:

urchinTracker("checkout.html")
urchinTracker("confirm.html")
urchinTracker("success.html")

These "virtual" pages can be used by Analytics the same purposes as a real page. See the Google Analytics help info for more. Pretty cool!

Was this post helpful to you? If so, please consider making a small donation to keep this blog going.

Monday, March 27, 2006

Transferring large files the easy way....?

I used to use Dropload, and I still hear it being recommended all the time. However, I can't remember my account info, so I can't log in. I have hit the "I forgot my password" link several times and never had my account info emailed to me. I have tried to sign up for a new account several times and never succeeded. Their FAQ's failed me, and the trouble ticket I opened was never responded to by their customer service people.

So now, I am a satisfied user of www.yousendit.com. It says what it does, it does what it says. No account necessary, which I think is a smart move on the part of their IT people. No account management means less work for them, and no login hassle for me.

Lessons learned? If you have a service that requires customer support, be prepared to provide it, or you'll drop your customers like some kind of... well... load.

Was this post helpful to you? If so, please consider making a small donation to keep this blog going.

Flash Player 8: Right features, wrong time?

There was a time, not so long ago, when I used to frequently think things like "If only Flash had blur built in!!" and "Oh, for a Flash Player with Photoshop-style blend modes!". I personally requested the latter feature for 3 major versions of the Flash Player. I spent hours trying to discover ways of achieving those effects through other means, beating my head against the keyboard until F, G, H, and J were imprinted permanently on my forehead. I stayed up until 4 A.M. far too often. And, I figured out some cool stuff... all of which is, since the release of Flash Player 8, completely and utterly irrelevant.

We all got used to being a bit confined. An entire aesthetic developed around the constraints of the Flash Player, typified by 2D design, heavy strokes, flat colors, simple gradients. This aesthetic hit the big-time with the iPod ads, and a slew of others. I didn't like the style at first, but it grew on me, or I grew with it, and it eventually took over. Now everything that I used to think was awesome looks dated and trite. This is a natural part of evolving as an artist, but when I realize a shift has taken place in the design world, I begin to wonder what's next.

Flash 8 promised such a shift. I anticipated its arrival with a great deal of panting and salivation... But now that it has arrived, I am unexpectedly at a loss for inspiration. Now that I can easily layer alpha-channeled video over my whirling, swirling "vortex of infinity" background, why would I bother? It was so much cooler when it was hard to do.

I came across an article last evening that I think explains part of the let-down. In it, Cecelia Holland writes about her experience teaching inmates at a maximum security prison. She describes how one imate would spend hours building beautifully detailed sculptures out of foil gum wrappers, the only viable medium he had available. Another inmate was an amazing novelist: until he was released from prison, from which point he was never again able to write with the same passion or skill.

The point of it all is that old adage: necessity is the mother of invention. The inmates in Pelican Bay State Prison made beautiful art, but only because it was their only means of expression. Now that I am out of the prison of old Flash, what will I do with new Flash? Maybe I can violate my parole and get sentenced to life developing for Flash Lite.

Or maybe I can take these new tools and apply them to my craft as a mature artist rather than as someone who is merely pushing the limits of their medium. I used to try to discover every cool new trick I could so that my designs would be unique, or so that I could feel like I was at the top of my game. I'm still going to do that, but now I think it will be less of an end unto itself. Flash 8 has levelled the playing field. Now, we all have pretty much the same toolset, regardless of our ability to hack the Flash Player. So, what's next? I think the future of Flash design is less about gimmicks and more about plain old artistic merit. And that's a life sentence I can live with.

Was this post helpful to you? If so, please consider making a small donation to keep this blog going.

Friday, March 17, 2006

How Many Pixels in an EM? Part 2

Yesterday, I blogged about a formula I came up with for determining the number of pixels in an em. Jan commented that perhaps this approach isn't such a good idea, because it might break when someone changes the font-size of their OS. This is actually not the case: changing the font-size in your OS doesn't change the pixel size of a point or an em.

However, Jan's comment prompted me to dig a little deeper. Can the size of an em change based on the screen resolution? Turns out, it does. At least according to this article, which I can only assume is correct given my lack of different displays to test it on. About mid-way down the page, in a lovely yellow block, is the following critical information:

Pixels per em is a crucial concept. As much as any other single factor
(such as ex-height), it determines the legibility of characters on screen at a nominal point size. The higher the ppem, the better defined are the characters' features, and the more and larger decrements are possible before hitting the legibility floor. If the ppem of the base size is low, fewer and smaller steps are
possible.

Pixels-per-em refers to the number of screen pixels required to render the em of a font at a size given in points.

A point is 1/72". On a system displaying 72 pixels per logical inch (Mac OS standard ppi), 1 point equals 1 pixel. On a system displaying 96 or 120 ppi (standard Windows settings), 1 point equals 1.333 or 1.667 pixels, respectively. The formula for ppem is a(b/72), where a is the font size, and b is the logical resolution figure.

For example, 12 points at 72 ppi (the legacy Mac OS browser default) or 9 points at 96ppi have a ppem value of 12. Twelve points at 96ppi (the legacy Windows browser default), or 16 points at 72ppi both have a ppem of 16. Twelve points at 90ppi have 15ppem, and 12 points at 120 ppi (Windows "large fonts") have 20ppem.


Nice. This both proves my formula, and puts a monkey wrench in it. If someone has changed their display resolution from the Windows default 96ppi, the formula is no longer accurate.

All is not lost. Since we're dealing with an IE-only expression to begin with, we can take advantage of an IE-only JavaScript property, screen.deviceXDPI. Our expression becomes:

width:expression( document.body.clientWidth >
(30*(screen.deviceXDPI/72))* parseInt(document.body.currentStyle.fontSize)?
"30em": "auto" );

This expression would yield a max-width of 30em. Naturally, it couldn't be this easy... Now, the expression no longer works in IE 5 or IE 5.5 because they don't support our new best friend, the deviceXDPI property. Well, I don't have too much of a problem with that. Out of the 5% or so of my visitors who have IE5 or IE5.5, how many of those would also have changed their display DPI? I think not many. But, just so the expression degrades well, let's test for the existence of the deviceXDPI property and adjust accordingly:

width:expression(document.body.clientWidth >
(30*((screen.deviceXDPI?screen.deviceXDPI:96)/72))*
parseInt(document.body.currentStyle.fontSize)? "30em": "auto" );

In this (increasingly long) expression, if screen.deviceXDPI is undefined, the default value of 96ppi is used. That oughtta do it. Comments?

Was this post helpful to you? If so, please consider making a small donation to keep this blog going.

Thursday, March 16, 2006

How Many Pixels in an EM?

In the interest of creating CSS-only layouts, it often makes sense to emulate CSS properties that IE doesn't support by using IE-only expressions. An example is the work of Svend Tofte in emulating max-width, which I reference quite often even though it is now 2 years old. I recently created a min-width expression based on this. Here is Svend's expression for max-width:

width:expression( document.body.clientWidth > (500/12) *
parseInt(document.body.currentStyle.fontSize)? "30em": "auto" );


Quite nice, but requires a bit of experimentation to get it to work right. In Svend's words:

Basically, with document.body.clientWidth, we get how wide the browser
window is. Using parseInt(document.body.currentStyle.fontSize), we get the font
size in pt's, that the user has currently set. I experimented, and at 12pts (the
normal size), the browser window gets wider then 30em's, at more or less 500
pixels. Of course, it's then a small matter, of calculating backwards, in the
scale, and see, if that if the default font size is 14pt (larger), then 30em's
will be exceeded at 583 pixels (roughly). The sad thing is, that you will need
to find the magic number, for whatever width you want for your letters. For
30ems, 500 pixels is the magic number.


Just as a reference for myself, I began tabulating the width of a 1em-wide div at various font sizes. In other words, I took screen captures and measured them in Photoshop.


body{
font-size: 500pt;
}

div{
background-color:black;
width:1em;
}

This yields a div that is 667 pixels wide.

Then I realized that if I graphed the pixel width of the div versus the font size in ems, a nice curve emerged, which meant to me that there must be a common factor. So, I took the pixel width of the largest measurement and divided it by the pt size of the font:

667px/500pt = 1.334

A little bit of algebra yields the formulae:

px per em = 1.334 * pts

and

px = ems*1.334*pts

I tested this out in IE and Firefox with serif, sans-serif, and monospaced font families, and it holds true regardless of font size. Applying it to Svend's original expression gives me the following max-width expression (where the desired max-width = 30em):

width:expression( document.body.clientWidth > (30*1.334)*
parseInt(document.body.currentStyle.fontSize)? "30em": "auto" );

Hope you like it... Please comment if you find it doesn't work for you!

Was this post helpful to you? If so, please consider making a small donation to keep this blog going.

My First Time

This is the inaugural post for my first-ever blog, TL on PL. PL stands for "presentation layer" technologies, specifically Flash, CSS & HTML. I'm sure I'll also write occasionally about Photoshop, Illustrator and other graphics and animation tools. I do a ton of research on these subjects in my career as a web designer/developer and I needed a permanent place to log my discoveries. As I come across useful tidbits of information, I'll post them here where they won't become casualties of my numerous Windows reinstallations.

I would also like to compile a comprehensive list of Flash Player quirks: stuff that you only find out about by chance, bugs that maybe only exist in specific minor versions. The kind that keep you up until 4 AM before you figure out that you weren't doing anything wrong. Until I can get Macr/Adobe to give me a copy of their bug database (hint hint) I'll have to do this a very little bit at a time.

Naturally, I'll also be creating a custom template for this blog... I just know I won't be able to handle using someone else's design for very long. So, look for that to change fairly soon.

Hopefully, this blog will be helpful to someone else looking for answers, and not bore them to death in the process.

Was this post helpful to you? If so, please consider making a small donation to keep this blog going.