Entries Tagged 'front-end development' ↓

The two CSS Selector bugs in IE6

Internet Explorer 6's CSS selector support is a far cry from every other A-Grade browser. It doesn't handle attribute tags, adjacent or child selectors, or the :first-child psuedo-selector. And yes, it sucks. We deal with it.

But beyond selectors not being implemented, there are two BUGS when it comes to selectors in IE6:

The multiple class bug
When you define rules like:

p.disclosure.warning { text-align: center; color: red; }

Most browsers will apply this to any P tags with both the class disclosure and warning. IE6, however, will only apply this to P tags with the last class mentioned; in this case, P tags with the class warning. so IE6 pretends like you wrote:

p.warning { text-align: center; color: red; } /* no .disclosure */

Workarounds are typically not hard, but staying aware of this fact will save you time debugging.

The ID-class bug
When you define a block like:

#tooltip.red { background: white; color: red; }
#tooltip.yellow { background: black; color: red; }

IE will ignore the the second rule. So even if you have a

<div id="tooltip" class="yellow">I'm on a black background in yellow text!</div>

, IE will not apply the CSS styles you had defined for it. If you have laid our rules for the same ID but different classes, it will ignore all CSS rules defined after the first one. (Your red tooltip will be fine).

Solutions:

  • Don't let the #id.class combo be the last selector: Multiple selectors of this type #tooltip.yellow div will be fine.
  • Move the class to a parent container: div.yellow #tooltip will not mess up anything.
  • Make your classes be superspecific and dont use an ID in your selector: div.yellowtooltip. You'll have to repeat yourself with duplicate CSS definitions, but you can thank IE6 for making your day miserable, yet again. :)

Bookmarklet: Inject new css rules

I love doing as much CSS debugging as I can without hitting reload. (see also: my 'refresh css' bookmarklet)

newcssrule.PNGFirebug can get you a far way in playing with styles. You can edit current css rules and add new styles to a given element, but there is no way to add a brand new rule to the page. UNTIL NOW!!!

Drag this bad boy to your bookmark bar:

>>> newcssrule <<<

The code is obviously trivial, but it's a helpful button to have around sometimes. Plus you can then edit those rules in firebug immediately.

Update (2008.06.05): I should point out this code only works in Firefox (maybe Opera), but for full compatibility, understand the landscape at InstallStyles on Google Doctype.
And this code should get you started:

    function addCSS(newcss){
        if ($.browser.msie) {
            document.createStyleSheet().cssText = newcss;
        } else {
            var tag = document.createElement('style'); tag.type = 'text/css'; document.getElementsByTagName('head')[0].appendChild(tag); 
            tag[ $.browser.safari ? 'innerText' : 'innerHTML'] = newcss;    
        }
    }

Best practice: Poll instead of a setTimeout hack

Very often you'll have events happening asynchronously, but you need to wait until one has completed before you fire the second.
And you may not have the ability of attaching a callback function to the first.

In my less wise days I'd say "Lets just setTimeout it for a couple seconds..." but always felt really dirty about it.

A classier approach I've used lately is to poll for a change. Here I'm using the gmail greasemonkey API and waiting for it to load in before I start using it:

gmonkey.load("1.0");
 
// this is a self-executing anonymous function that uses setTimeout to call itself 
// at 50ms intervals until the isLoaded variable resolves as true.
 
(function(){
  if (gmonkey.isLoaded){
    // do stuff i want to do with the API
    gmonkey.get('1.0').addNavModule('notepad', '<iframe src="http://aaronboodman.com/halfnote/"></iframe>');
  } else {
    setTimeout(arguments.callee,50);
  }
})();

I found myself doing this a lot when loading in multiple external resources and playing with them.. So to generalize the code I wrote executeWhenLoaded():

// executeWhenLoaded() will be overloaded with as many arguments as i want to check for presence.
function executeWhenLoaded(func){  
 
  for (var i = 1; i<arguments.length; i++){ // for loop starts at 1 to skip the function argument.
    if (! window[ arguments[i] ]) {
      setTimeout(arguments.callee,50);      
      return;
    } 
  }
 
  func(); // only reaches here when for loop is satisfied.
}
 
// and in use:
 
executeWhenLoaded(function(){ 
    console.log(session.data);
},'session');   // session will return a value when the whatever preceding functionality is done.

executeWhenLoaded's first argument is the function to call, it can an unlimited number of arguments, which are all strings that reflect objects in the global namespace that have to be present in order to execute that function.

Update: In the comments, ProggerPete notes that this is not cross-browser compatible.. yet! In IE6, at least, the browser loses the original reference to the arguments object when it cycles through on the arguments.callee call. He offers a fix below.

what makes you sustainably happy?

i wonder about the personal fulfillment of:

  • doing what we think we should be doing
  • doing what we want to be doing
  • doing what we think makes us happy

because those three are certainly different..

How to quickly find a layer in a big PSD

psdlayers.PNGI'll often get PSDs from my visual designers with hundreds of layers. When I'm slicing it up, I'll need to find a specific layer. And much of the time, I don't instantly understand the layer architecture that was defined.

Using the "Auto Select layer" option on the move tool gets partway there, but it chokes on layer groups.

The quickest route possible: Alt-right-click
That will immediately select the layer of whatever you clicked on. (The move tool (V) must be active. This doesnt work while on other tools.)

(On Mac, this has an additional click: option-click. then the revealed menu has your layer currently selected. click it.)

How to iterate quickly when debugging CSS

firebugscreen.PNGFirebug is my tool of choice to fiddle with CSS. I'll edit the elements on the page, and then copy my changes back to the .css file. Then save.

If you're in a webapp, refreshing the page could take a while, so here's a great way to reload the freshest copies of the stylesheets. Drag this bookmarklet link to your toolbar:

>>> Refresh CSS <<<

Clicking it will modify any <link rel="stylesheet"> tags and append a timestamp at the end of each href attribute, thereby dropping the cache and grabbing a new one. It's quick and beautiful.