Photo Gallery using Lightbox 2 in Rails 5

In this article, you will learn how to implement a photo gallery using Lightbox 2 in Rails 5. We will continue working on the album project that we discussed in the article File Upload using Refile Gem in Rails 5.

Initial Setup

  • Download lightbox 2.
  • Extract the zip file.
  • Copy the lightbox.css to app/vendor/assets/stylesheets directory.
  • Copy the lightbox.js to app/vendor/assets/javascripts directory.
  • Copy the images close.png, loading.gif, next.png and prev.png to app/assets/images folder.

You can use a package manager, Bower:

bower install lightbox2 --save

or NPM:

npm install lightbox2 --save

to install lightbox2.

Integrate Lightbox 2 with Rails 5

Let's hook Lightbox 2 Javascript to asset pipeline. Add

//= require lightbox

to app/assets/javascripts/application.js. It will now look like this:

//= require jquery
//= require jquery_ujs
//= require turbolinks  
//= require lightbox
//= require_tree .

Let's hook Lightbox 2 stylesheet to asset pipeline. Add

@import 'lightbox';

to app/assets/stylesheets/application.scss. It will now look like this:

 *= require_tree .
 *= require_self
 */

@import 'lightbox';

Note: The file extension must be .scss not css. Move the Javascript Include tag in layout file. The app/views/layouts/application.html.erb must have the javascript_include_tag just before body tag ends, otherwise the photo gallery will not work. The layout file looks like this:

<!DOCTYPE html>
<html>
  <head>
    <title>Album</title>
    <%= csrf_meta_tags %>
    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
  </head>
  <body>
    <div id="container">
      <% flash.each do |name, msg| %>
        <%= content_tag :div, msg, id: "flash_#{name}" %>
      <% end %>
      <%= yield %>
    </div>

    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>

  </body>
</html>

Rename the lightbox.css to lightbox.scss.erb. The css files needs to use asset pipeline helper image_path, to hook the images to asset pipeline. It will now look like this:

/* Preload images */
body:after {
  content: url(<%= image_path('close.png')%>) url(<%= image_path('loading.gif')%>) url(<%= image_path('prev.png')%>) url(<%= image_path('next.png')%>);
  display: none;
}

body.lb-disable-scrolling {
  overflow: hidden;
}

.lightboxOverlay {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 9999;
  background-color: black;
  filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80);
  opacity: 0.8;
  display: none;
}

.lightbox {
  position: absolute;
  left: 0;
  width: 100%;
  z-index: 10000;
  text-align: center;
  line-height: 0;
  font-weight: normal;
}

.lightbox .lb-image {
  display: block;
  height: auto;
  max-width: inherit;
  border-radius: 3px;
}

.lightbox a img {
  border: none;
}

.lb-outerContainer {
  position: relative;
  background-color: white;
  *zoom: 1;
  width: 250px;
  height: 250px;
  margin: 0 auto;
  border-radius: 4px;
}

.lb-outerContainer:after {
  content: "";
  display: table;
  clear: both;
}

.lb-container {
  padding: 4px;
}

.lb-loader {
  position: absolute;
  top: 43%;
  left: 0;
  height: 25%;
  width: 100%;
  text-align: center;
  line-height: 0;
}

.lb-cancel {
  display: block;
  width: 32px;
  height: 32px;
  margin: 0 auto;

  background: url(<%= image_path('loading.gif')%>) no-repeat;
}

.lb-nav {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  width: 100%;
  z-index: 10;
}

.lb-container > .nav {
  left: 0;
}

.lb-nav a {
  outline: none;
  background-image: url('data:image/gif;base64,R0lGODlhAQABAPAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==');
}

.lb-prev, .lb-next {
  height: 100%;
  cursor: pointer;
  display: block;
}

.lb-nav a.lb-prev {
  width: 34%;
  left: 0;
  float: left;
  background: url(<%= image_path('prev.png')%>) left 48% no-repeat;
  filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=0);
  opacity: 0;
  -webkit-transition: opacity 0.6s;
  -moz-transition: opacity 0.6s;
  -o-transition: opacity 0.6s;
  transition: opacity 0.6s;
}

.lb-nav a.lb-prev:hover {
  filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100);
  opacity: 1;
}

.lb-nav a.lb-next {
  width: 64%;
  right: 0;
  float: right;
  background: url(<%= image_path('next.png')%>) right 48% no-repeat;
  filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=0);
  opacity: 0;
  -webkit-transition: opacity 0.6s;
  -moz-transition: opacity 0.6s;
  -o-transition: opacity 0.6s;
  transition: opacity 0.6s;
}

.lb-nav a.lb-next:hover {
  filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100);
  opacity: 1;
}

.lb-dataContainer {
  margin: 0 auto;
  padding-top: 5px;
  *zoom: 1;
  width: 100%;
  -moz-border-radius-bottomleft: 4px;
  -webkit-border-bottom-left-radius: 4px;
  border-bottom-left-radius: 4px;
  -moz-border-radius-bottomright: 4px;
  -webkit-border-bottom-right-radius: 4px;
  border-bottom-right-radius: 4px;
}

.lb-dataContainer:after {
  content: "";
  display: table;
  clear: both;
}

.lb-data {
  padding: 0 4px;
  color: #ccc;
}

.lb-data .lb-details {
  width: 85%;
  float: left;
  text-align: left;
  line-height: 1.1em;
}

.lb-data .lb-caption {
  font-size: 13px;
  font-weight: bold;
  line-height: 1em;
}

.lb-data .lb-number {
  display: block;
  clear: left;
  padding-bottom: 1em;
  font-size: 12px;
  color: #999999;
}

.lb-data .lb-close {
  display: block;
  float: right;
  width: 30px;
  height: 30px;   
  background: url(<%= image_path('close.png')%>) top right no-repeat;
  text-align: right;
  outline: none;
  filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=70);
  opacity: 0.7;
  -webkit-transition: opacity 0.2s;
  -moz-transition: opacity 0.2s;
  -o-transition: opacity 0.2s;
  transition: opacity 0.2s;
}

.lb-data .lb-close:hover {
  cursor: pointer;
  filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100);
  opacity: 1;
}

Test the Configuration

Let's use the example code that ships with Lightbox 2 to verify our setup is working. Add the following code in app/views/photos/index.html.erb.

<h3>A Four Image Set</h3>
  <div>
      <a class="example-image-link" href="http://lokeshdhakar.com/projects/lightbox2/images/image-3.jpg" data-lightbox="example-set" data-title="Click the right half of the image to move forward."><img class="example-image" src="http://lokeshdhakar.com/projects/lightbox2/images/thumb-3.jpg" alt=""/></a>
      <a class="example-image-link" href="http://lokeshdhakar.com/projects/lightbox2/images/image-4.jpg" data-lightbox="example-set" data-title="Or press the right arrow on your keyboard."><img class="example-image" src="http://lokeshdhakar.com/projects/lightbox2/images/thumb-4.jpg" alt="" /></a>
      <a class="example-image-link" href="http://lokeshdhakar.com/projects/lightbox2/images/image-5.jpg" data-lightbox="example-set" data-title="The next image in the set is preloaded as you're viewing."><img class="example-image" src="http://lokeshdhakar.com/projects/lightbox2/images/thumb-5.jpg" alt="" /></a>
      <a class="example-image-link" href="http://lokeshdhakar.com/projects/lightbox2/images/image-6.jpg" data-lightbox="example-set" data-title="Click anywhere outside the image or the X to the right to close."><img class="example-image" src="http://lokeshdhakar.com/projects/lightbox2/images/thumb-6.jpg" alt="" /></a>
  </div>
</section>

Browse to http://localhost:3000/photos to view the lightbox photo gallery in action.

Photo Gallery of Album

We can now remove the hard coded images and use the uploaded images for the gallery like this:

<div>
  <% @photos.each do |photo| %>       
    <%= link_to(image_tag(attachment_url(photo, :image, :fit, 100, 100, format: 'jpg')), attachment_url(photo, :image, :fit, 500, 500, format: 'jpg'), data: { lightbox: "example-set", title: photo.name }) %>     
  <% end %>
</div>    

You will now be able to view the uploaded images of the album in a photo gallery. You can download the source code for this article from github.

Summary

In this article, you learned how to implement a photo gallery using Lightbox 2 Javascript library in Rails 5.


Related Articles

Watch this Article as Screencast

You can watch this as a screencast Photo Gallery using Lightbox 2 in Rails 5


Ace the Technical Interview

  • Easily find the gaps in your knowledge
  • Get customized lessons based on where you are
  • Take consistent action everyday
  • Builtin accountability to keep you on track
  • You will solve bigger problems over time
  • Get the job of your dreams

Take the 30 Day Coding Skills Challenge

Gain confidence to attend the interview

No spam ever. Unsubscribe anytime.