fguillen
fguillen

Reputation: 38792

Rails 3 assets & CSS relative URLS

I have several CSS files which make referece to images using relative paths like url( "../img/my_image.jpg" ).

Everything works in development but in production environment, as all the CSS files are packed in one file and the structure is lost, also the relatives paths are lost, and the images are not found.

Details of my structure

I have an assets structure like this:

/app
  /assets
    /plugins
      /my_plugin
        /img
          my_image.jpg
        /css
          my_css.css

(/my_plugin can be any plugin that is a groups of css, js and images files like Twitter Bootstrap any any other)

Into the /app/assets/plugins/my_plugin/my_css.css I have something like:

background-image: url("../img/my_image.jpg");

In the /app/assets/stylesheets/application.css:

*= require css/my_css.css

And finally in the head of my html file:

<%= stylesheet_link_tag "application" %>

What should I do to fix the issue?

Update

Mini application to reproduce the issue, in the README there are instruction to install and reproduce the issue.

Upvotes: 5

Views: 5170

Answers (2)

jdoe
jdoe

Reputation: 15771

I don't see a problem with concatenating CSS files. And you don't have to include your deeply nested CSS files manually: by default, application.css already does this in the line *= require_tree .

And images will repeat your app/assets/images structure. To deal with them correctly both in development and production environments you have the respective Guide. Check its section 2.2 Coding Links to Assets. There's explanation about coding paths to your image files:

CSS via ERb:

 url(<%= asset_path 'image.png' %>)

CSS via Sass:

 image-url("rails.png")

All these weird hex characters at the end of your precompiled images will be respected automatically.

UPD

I see you don't need the assets pipeline feature for your plugins at all. Your styles/scripts are already minified. You can move your plugins folder into your public folder (to become <APP_ROOT>/public/plugins/).

Then delete the following line from your application.css:

*= require bootstrap/css/bootstrap

Instead add the following lines to your template application.html.erb:

  <%= stylesheet_link_tag    "/plugins/bootstrap/css/bootstrap.min.css", :media => "all" %>
  <%= javascript_include_tag "/plugins/bootstrap/js/bootstrap.min.js" %>

Now you have to be able to switch between your themes easily by replacing your public/plugins/bootstrap's content.

UPD 2

Probably you have to explicitly tell Rails to precompile your plugin assets:

# /config/environments/production.rb
config.assets.precompile += %w( bootstrap/css/bootstrap.css )

Upvotes: 8

fguillen
fguillen

Reputation: 38792

I have been able to solve the issue moving my plugin assets to the /app/vendor/assets/plugins where I think is better place due they are not assets directly related to my application but infact vendor assets.

Then we have:

/app
  /vendor
    /assets
      /plugins
        /my_plugin
          /img
            my_image.jpg
          /css
            my_css.css

And we load the main css in another stylesheet_link_tag call like this:

<%= stylesheet_link_tag "my_plugin/css/my_css", :media => "all" %>

At this moment everything looks right but Rails complains about my_css.css is not compiled even if we run rake assets:precompile.

The solution is to tell Rails explicitly to compile this file:

# /config/environments/production.rb
config.assets.precompile += %w( my_plugin/css/my_css.css )

Now the rake assets:precompile will compile our plugin css and the production environment works properly even with relative urls.

Check the diff changes those have resolved the issue

Upvotes: 2

Related Questions