Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
I am the chief technical officer at InVision App, Inc - a prototyping and collaboration platform for designers, built by designers. I also rock out in JavaScript and ColdFusion 24x7.
Meanwhile on Twitter
Loading latest tweet...
Ben Nadel at the jQuery Conference 2010 (Boston, MA) with:

Less CSS, Relative Paths, Nested Quotes, Url() Constructs, And Post-Processing

By Ben Nadel on
Tags: HTML / CSS

This is a really tiny post, but it's something that had our team baffled for weeks. We were using an older version of RetinaJS which defined an .at2x() mixin for inserting media-query rules for retina-sized images. Everything was working great until we upgraded our Less CSS compilers; then, everything started breaking in a really weird way. After a lot of digging, we discovered that Less CSS gets a little funky when you have nested quotes that contain relative paths inside of url() constructs.

To demonstrate, here is some Less CSS that isolates the problem:

  • // -- Working. -- //
  •  
  • h1 {
  • @single-quotes: "../../Meep.png" ;
  •  
  • background-image: url( @single-quotes ) ;
  • content: @single-quotes ;
  • }
  •  
  • h2 {
  • @single-quotes: '../../Meep.png' ;
  •  
  • background-image: url( @single-quotes ) ;
  • content: @single-quotes ;
  • }
  •  
  • // -- Breaking. -- //
  •  
  • h3 {
  • @nested-quotes: "'../../Meep.png'" ;
  •  
  • background-image: url( @nested-quotes ) ;
  • content: @nested-quotes ;
  • }
  •  
  • h4 {
  • @nested-quotes: '"../../Meep.png"' ;
  •  
  • background-image: url( @nested-quotes ) ;
  • content: @nested-quotes ;
  • }

Notice that the second set of CSS rules contain values that have nested quotes - double quotes within single quotes or single quotes within double quotes. Also notice that the image paths are all relative paths that go above the current file. When we compile this Less CSS with CodeKit 2 or LiveReload (the ones I happen to use), we get the following CSS:

  • h1 {
  • background-image: url("../../Meep.png");
  • content: "../../Meep.png";
  • }
  • h2 {
  • background-image: url('../../Meep.png');
  • content: '../../Meep.png';
  • }
  • h3 {
  • background-image: url("Meep.png'");
  • content: "'../../Meep.png'";
  • }
  • h4 {
  • background-image: url('Meep.png"');
  • content: '"../../Meep.png"';
  • }

Notice that the h3 and h4 paths are completely broken, but only when used in conjunction with the url() construct; the relative paths lose their dots and one of the quotes is stripped out (leaving the string value unevenly quoted). Based on what I can gather from this GitHub thread, it appears that Less CSS is trying to do some sort of post-processing on url() values (which I don't fully understand).

Ultimately, the problem had to do with the way the older version of RetinaJS was building the paths - it was accidentally nesting quotes. The newer version of RetinaJS gets around this by not quoting its input during the JavaScript source interpolation; of course, this breaks if you don't quote your URLs. But, that's OK - if you're one of those people that doesn't quote URL values, breaking code is what you get (he says from high up on his soap box).




Reader Comments

Post A Comment

You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Oops!
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.