Reputation: 1364
It's maybe an easy question but after some research I didn't find any valid solution.
I use carrierwave to generate multiple versions of an uploaded image. Each image has a specific size for different screen sizes. For example (in my uploader) I have
version :xl
for screens larger than 1200px.
How can I use rails to display specific image according to client screen size ?
I know there is gem responsive-images but I can't use size.
The subject of responsive images is for the moment quite vast and nobody seems to have the same answer, especially with javascript and html5. How about rails (even if it's server side) ?
Upvotes: 2
Views: 3057
Reputation: 1364
Well, I really wanted to do it in a more rails way. I ended up using ajax :
Fire ajax at load page :
# assets/javascript/cards/index.js
// fire loading image
$.ajax({
url: document.URL,
data: {
w: window.innerWidth
}
});
In controller, respond to ajax :
# controllers/cards_controller.rb
render 'cards/images/loadimage' if request.xhr?
Then load your images
# cards/images/loadimage.js.erb
<% w = params[:w].to_i %>
document.getElementById('banner-container').innerHTML = "<%= j image_tag @card.banner_type_url(w), class: 'banner' %>";
document.getElementById('logo-container').innerHTML = "<%= j image_tag @card.logo_type(w), class: 'logo' %>";
I made in my model a method to return right image given screen width (and based on carrierwave version) :
# models/card.rb
# returns banner type based on width (w)
def banner_type_url(w)
return self.banner.s.url || banner_default('s') if(w <= 768)
return self.banner.m.url || banner_default('m') if(w <= 992)
return self.banner.l.url || banner_default('l') if(w <= 1200)
return self.banner.xl.url || banner_default('xl') if(w <= 1920)
return self.banner.full.url || banner_default('full')
end
def banner_default(s)
"card/banner/#{s}_default-banner.jpg"
end
Upvotes: 1
Reputation: 12580
Here are a couple of ways:
Load the page with all the paths to various image sizes stored as data attributes, grab the screen width with js, then stick an image tag with the correct path where you want it. Code might look like (not tested, and I've been using coffeescript, so probably missing details):
# ruby command line
$ @image.mobile_asset_url
=> "path/to/mobile/image"
$ @image.desktop_asset_url
=> "path/to/desktop/image"
# html.erb
<img src="" class="placeholder" data-mobile-url=<%[email protected]_asset_url%> data-desktop-url=<%[email protected]_asset_url%>></div>
# javascript
el = $('.placeholder')
data = el.data();
width = $(window).width();
mobile_breakpoint = 480;
if (width <= mobile_breakpoint) {
url = data.mobileUrl;
} else {
url = data.desktopUrl;
}
el.attr('src', url)
Do a server side test not for screen width, but browser type with a gem like browser, and load smaller images for mobile specific browsers like iOS8. Logic like this might go best in a decorator. I'm more fluent with Ruby, so an example might look like (this code not tested):
# user_decorator.rb, from the Draper gem
class UserDecorator
def profile_url
if mobile_browser?
"path/to/small/image"
else
"path/to/large/image"
end
end
private
def mobile_browser?
browser.ios || browser.android || ...
end
end
Upvotes: 5