If you have URLs that are relative to the server root then CSS aggregation will break these URLs.

For example, in your theme CSS you can reference a background image like this:
background-image: url(/theme/images/Footer.gif);

Since the URL starts with a / it is relative to the server root.

When you enable CSS aggregation this is rewritten and becomes:
background-image: url(/sites/example.com/themes/example//theme/images/Footer.gif);

and results in a 404

URLs that start with / should not be rewritten.

A workaround is to use a relative URL in your CSS. Assumin the above images folder is in the theme folder then you can write:
background-image: url(images/Footer.gif);
and this gets rewritten properly to:
background-image: url(/sites/example.com/themes/example/images/Footer.gif);

Another workaround is to use the full URL, including protocol and server name:
background-image: url(http://example.com/theme/images/Footer.gif);

In this example /theme is a web server alias to /sites/example.com/themes/example, but there could be other cases when you want a URL to start with a /.

CommentFileSizeAuthor
#5 css-aggregation.patch823 bytesJorrit

Comments

mariuss’s picture

The code that rewrites the URLs in aggregated CSS files is in drupal_build_css_cache, in the includes/common.inc file:

          // Fix all paths within this CSS file, ignoring absolute paths.
          $data .= preg_replace('/url\(([\'"]?)(?![a-z]+:)/i', 'url(\1'. $path . '\2', $contents);

The regular expression avoids URLs starting with a protocol, (?![a-z]+:), but not URLs starting with /.

dvessel’s picture

Priority: Critical » Normal

I'd consider this a bug but in what situation would an absolute path be needed?

mariuss’s picture

Couple of examples:
- your site is installed at http://example.com/drupal/ and you want to use images from http://example.com/images/
- in order to avoid long paths like /sites/example.com/theme/mytheme/images/ in apache you have an alias called /theme that points to /sites/example.com/theme/mytheme/

But this is really besides the point. The fix is trivial:

          // Fix all paths within this CSS file, ignoring absolute paths.
          $data .= preg_replace('/url\(([\'"]?)(?![a-z]+:|\/)/i', 'url(\1'. $path . '\2', $contents);
Jorrit’s picture

That fix will turn
background: url('/static/bg_menu.gif') repeat-y;
into
background: url(/drupal5/sites/all/themes/travelhome/'/static/bg_menu.gif') repeat-y;

For me this works:
$data .= preg_replace('/url\(([\'"]?)(?![\'"]?(?:[a-z]+:|\/))/i', 'url(\1'. $path . '\2', $contents);

There is some repetition, but apparently preg is not greedy enough, it will not match the first ([\'"]?), even when there is a '.

(Tested with Drupal 5.6, PHP 5.2.5 on Gentoo for both absolute urls with / and http:// in front, and relative urls)

Jorrit’s picture

Version: 5.2 » 5.7
Status: Active » Needs review
StatusFileSize
new823 bytes

Perhaps it will only be fixed when someone provides a patch ...

drumm’s picture

Status: Needs review » Closed (duplicate)

http://drupal.org/node/113607 already more-throughly solved this in Drupal 6.x.

mariuss’s picture

Status: Closed (duplicate) » Needs review

If it was fixed in Drupal 6 then this cannot be a duplicate. Drupal 5 still has an issue.

damien tournoud’s picture

Status: Needs review » Closed (duplicate)

This will be solved by partially backporting #113607: Import @import commands when building CSS cache.