Download & Extend

css aggragation breaks urls in theme css file

Project:Drupal core
Version:5.7
Component:base system
Category:bug report
Priority:normal
Assigned:Unassigned
Status:closed (duplicate)

Issue Summary

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 /.

Comments

#1

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

<?php
         
// 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 /.

#2

Priority:critical» normal

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

#3

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:

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

#4

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)

#5

Version:5.2» 5.7
Status:active» needs review

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

AttachmentSizeStatusTest resultOperations
css-aggregation.patch823 bytesIgnored: Check issue status.NoneNone

#6

Status:needs review» closed (duplicate)

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

#7

Status:closed (duplicate)» needs review

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

#8

Status:needs review» closed (duplicate)

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