1

I have created a RoR based app/website where the client can upload their own background image to the cover page.

Everything works well with one image, but I would like the site to be responsive and allow my client the choice to upload 3 completely separate images that are displayed depending on the px width of the window.

Currently I have the following code (only showing relevant code), which works fine:

In covers_controller.rb:

class CoversController < ApplicationController

 #
 @covers = Cover.all
 @cover = Cover.find_by(:published => 'yes')
 #

end

In application.html.erb:

<body style="background-image: url(<%= @cover.image %>)">

I have however not succeeded in making the cover images responsive. I have tried the following...

Adding a css.erb file with the following code:

@media (max-width: 767px) {
  .cover-bg {
    background-image: url(<%= @cover.image %>)
  }
}

@media (min-width: 768px) {
  .cover-bg {
    background-image: url(<%= @cover.m-image %>)
  }

}

@media (min-width: 1200px) {
  .cover-bg {
    background-image: url(<%= @cover.lg-image %>)
  }

}

For the css.erb above I added two new images to the Model called m-image and lg-image (using paperclip), and added the .cover-bg class to the body tag on application.html.erb, but got a blank page.

UPDATE: here is the model. I realize that I did not add the new images to the Model. However, when first testing the idea of using css.erb, I used images from three different Models for the different @media css, and encountered the same problem:

class Cover < ActiveRecord::Base

      has_attached_file :image, 
        styles: { xlarge: "1600x1600>", large: "600x600>", medium: "300x300>", thumb: "100x100>" }

      validates_attachment_content_type :image,
        content_type: /\Aimage\/.*\z/

end

I hope there is a easy solution out there, but I have yet to find it. I also tried various application helper methods, but no luck thus far.

Timo
  • 7
  • 3

1 Answers1

1

Your .css.erb file won't work because you're calling instance-dependent objects, when in likelihood, this file will be precompiled - making it static.

how do you propose that application.css will be able to read @cover?

--

The reason why it worked when you used <body style="..."> is because when you have an inline style in the view, Rails has access to all the data for the instance information etc.

To fix the problem, you need to reference your media queries in a place where you'll have access to all the instance data, namely the view.

After looking at some resources, it's my opinion that you're best putting it into the <head> of the layout of your app:

#app/views/layouts/application.html.erb
<head>
   <%= if [[conditional for page]] %>
      <style>
         @media (max-width: 767px) {
            .cover-bg {
               background-image: url(<%= @cover.image.url %>)
            }
         }

         @media (min-width: 768px) {
           .cover-bg {
              background-image: url(<%= @cover.image.url(:medium) %>)
           }
         } 

        @media (min-width: 1200px) {
           .cover-bg {
             background-image: url(<%= @cover.image.url(:large) %>)
           }
        }
      </style>
   <% end %>
</head>
<body class="cover-bg">
...

This should give you the ability to assign the custom background image size.

--

Another thing you'll want to look at is background-size: cover:

#app/assets/stylesheets/application.css
.cover-bg {
   background-size: cover;
}

This would have to be accompanied by the inline "background-image" style, but if it was done correctly, would allow you to resize your screen and be impervious to the change of background size.


Update

Ruby on Rails applications are dynamic by nature -- they connect to a database etc.

Each time you send a request to a Rails application, there is a lot which happens on the server (you can read more about how it works with MVC):

enter image description here

In short, Rails basically acts like a drive-thru where you pull up, send your request/order, and then Rails comes back with the goods. The "goods" are rendered HTML code which your browser then outputs on the screen.

This rendered HTML - although will be interspersed with @instance_variables etc in the backend - will be static for the browser.

Your browser is nothing more than an engine to render HTML/CSS/JS. Rails "compiles" your data and sends back an HTML file so that Chrome / Firefox can output something useful on screen.

In other words, your <%= @instance_variable %> is ONLY available in the "backend" of the app (when your "order" is being processed). This means that if you're looking to make your application versatile, you have to make sure all backend data is available to the parts of the app which are returned to the browser each time.

As such, your CSS has a problem. By its nature, CSS is static. There is no reason to include it in the expensive process of repopulating with each request/order. Kind of like changing the design on the drive-thru bags each time. You do it once and then use them for several years (the bags are NOT personalized with professional print each time).

So they're kept static -- precompiled (minified) so that it can be downloaded once and then kept in the cache whilst the user browses.

If you need to make your CSS variable (IE it uses backend data), you can include it only if it's available before the files are precompiled. If you're trying to access instance variables, it has to be kept in the views/layout.

Community
  • 1
  • 1
Richard Peck
  • 76,116
  • 9
  • 93
  • 147
  • Thanks Rich, looks promising, will try it out. New to ruby so it's great to learn something new. So if I understand you correctly, any ruby code in a css file will be precompiled and hence static? ..more or less? I am actually alreday styling the image with a separate css class, I removed it from the example to keep the focus on the problem at hand. – Timo Dec 15 '15 at 10:00