Will Grav work for a gallery with hundreds of images?

Hi there,

I have been ‘on’ Wordpress since 1.0 :wink: and I feel like trying something new. I need a very very basic minimal site, just a couple of text pages and one gallery page. I want to display 3 high quality thumbs in a row and 3 rows on a page. Every photo can be opened in some kind of lightbox. It’s a photoblog (one photo every couple of days I suppose). Think of it as a selfhosted instagram kinda page.

Grave coder theme is exactly what I needed. Installing was easy but now the big challenge is the gallery. I coudn’t find a lot of gallery plugins. And as far as I know none that does pagination or offers a load more button. So two question: does anyone know it this is achievable for a new user without twig knowledge (but a fast learner), and I am not entirely sure if Grav i suitable for say 600 images.

Hope someone can give me some solid advice here and point me in the right direction :slight_smile:

I have done image galleries in Grav without using any plugins. It works well, but the images are processed by the server and the bigger they are, the more work the server needs to do to process them. Once the images are processed, they are cached on the server and they load fast but if you are doing a single page with 600 images, you are going to need a decent hosting provider. I have moved most sites to Digital Ocean droplets from Wirenine and the photo galleries load much qicker.

What I like about using Grav for this sort of thing is the flexibility. More often than not, I just need to dump a bunch of photos on a page so all the site admin needs to do is put them in the folder using the admin module and my twig template does all the work of putting them on the page. If I want to use Masonry, no problem. I can adjust the thumbnails to be anything all using twig and no plugins.

For example, here is some twig to make a masonry gallery. I am using the filename as a photo caption. I am sure this is not the best code in the world, but I am not the best coder.

                    <div class="grid js-masonry">
                    {% for image in page.media.images %}
                        {% set imgtitle = image.filename|replace({'.JPG':'','.jpg':'','_':' ','-':' '}) %}
                       <div class="grid-item text-center">
                         <a href="{{ image.cropResize(800,800).url }}" rel="lightbox">
                           <img src="{{ image.cropResize(200,400).url }}" alt="{{ page.title }} {{ imgtitle }}" style="padding:5px;" />
                         </a>
                            {% if page.header.show_captions %}
                                <p><small>{{ imgtitle }}</small></p>
                            {% endif %}
                       </div>
                    {% endfor %}
                    </div>

Thanks you very much for your elaborate response mikegcox. That sounds great actually! I am going to give it a go.

One thing: will this work with pagination as well?

Kind regards

ps I have been playing aronf for a couple of hors with Grav and I really like it! Much more flexible and feature rich than I thought

I don’t see why it wouln’t work with pagination. I haven’t done it, but I am sure with a little bit of twig it could be figured out.

Just a hint: Don’t forget Grav comes with a built in lightbox action already. That should simplify the coding stage. Keep in mind though that this just creates the disired HTML output for a lightbox - you still need a lightbox (js) to make it work (featherlight or sim).

Hi slarchter,

Thanks. I haven’t had time to give it a try to built a gallery but I will soon. I did however try to install featherlight in my Grav Coder theme but somehow it does’t work. It did work in defaukt theme. Featheright seems to load though. Weird.

I am really started to like Grav :slight_smile: I got featherlight working. I noticed my theme was using jquery slim, when I started using a full version it worked.

I also tried the twig you (Mike) provided above and got that working as well. I am missing masonry or preferably responsive grid presentation. I suppose I need some (Jquery) plugin for that? Could you please point me into the right direction?

Edit: I had a look at your code and googled a bit, found a jquery plugin (https://masonry.desandro.com), put it on the server and loaded it with custom.js plugin. And it actually worked :slight_smile: Not bad for someone who doesn’t know what he is doing :slight_smile:

Next step is pagination or infinite scroll or a load more button, if anyone has any idea how to achieve this using this jquery / twig I would be very happy to learn

Some of the demo’s of Masonry use infinite scroll and lazy loading of images. Maybe that’s already handled by that library?

A general approach when integrating some Javascript code is to first get it working with a simple static HTML page. Then add the JS and CSS as assets to your Twig base template and in the appropriate templates for processing or output of HTML.

Regarding pagination, there’s the official (meaning created by the Grav dev team) Grav Pagination Plugin.

1 Like

Thank you, that’s a some good advice! I will try your that approach. Easier to learn that way.

I have only one item on my to-do list and that is pagination (endless scroll is fine as well), and for the life of my I cannot figure out how to get this working.

@bleutzinn refered to the official plugin but does that work with media-items on a single blog item as well?

I am using @mikegcox twig which works great.

			<div class="grid js-masonry">
                {% for image in page.media.images|sort|reverse %}
                    {% set imgtitle = image.filename|replace({'.JPG':'','.jpg':'','_':' ','-':' '}) %}

                   <div class="grid-item text-center">
                     <a href="{{ image.resize(1920,1280).url }}" rel="lightbox">
                       <img src="{{ image.resize(600,400).quality(100).url }}" alt="{{ page.title }} {{ imgtitle }}" />
                     </a>
                        {% if page.header.show_captions %}
                            <p><small>{{ imgtitle }}</small></p>
                        {% endif %}
                   </div>
                {% endfor %}
                </div>

With this css

/* ---- grid ---- */

.grid {
  max-width: 960px;
}

/* clearfix */
.grid:after {
  content: '';
  display: block;
  clear: both;
}

/* ---- grid-item ---- */

.grid-item {
  width: 300px;
  height: 200px;
  float: left;
  /* vertical gutter */
  margin-bottom: 30px;
}

And this inline javascript

// init Masonry
var $grid = $('.grid').masonry({
  // options...
});

// layout Masonry after each image loads
$grid.imagesLoaded().progress( function() {
  $grid.masonry('layout');
});

$('.grid').masonry({
  itemSelector: '.grid-item',
  columnWidth: 300,
  gutter: 30
});

I tried infinite scroll with masonry but couldn’t get it to work in Grav -> https://codepen.io/desandro/pen/eRRQVo

If someone is willing to help me out here (and has the patience), I would greatly appreciate that.

In case someone is looking for a similar solution.

I went with Media Boxes (not free, not expensive either) and Fancybox instead of Desandro’s Masonry and featherlight and used @mikegcox twig as an example. So I ended up with this:

</header>
    <div class="page-content">
        {{ page.content }}
		<div id="grid">
			{% for image in page.media.images|sort|reverse %}
            {% set imgtitle = image.filename|replace({'.JPG':'','.jpg':'','_':' ','-':' '}) %}
			<div class="media-box category1">
			<div class="media-box-image">
				<div data-thumbnail="{{ image.resize(600,400).quality(100).url }}"></div>
				<div class="thumbnail-overlay">
				<i class="fa fa-plus mb-open-popup" data-src="{{ image.resize(1920,1280).url }}" data-title="{{ imgtitle }}"></i>
			</div>
				</div>
			</div>
			{% endfor %}
		</div>
	</div>

Apart from that it’s basically just loading all the js and css files in the template you need them and initialize with as many options you need.

    <script>
    
    $('#grid').mediaBoxes(); 
    
</script>

Very happy with the result! very happy with Grav!

1 Like

I would like to use your solution in a small project. (I bought the MediaBoxes Script)
But I can’t get it to work. grrr I’m almost desperate.
Can you please explain to a complete layman which changes I have to make in which document?
Thank you very much for that.

@adus First of all I am a layman myself, I just do it the trial and error way :slight_smile: What you could do is:

-Upload plugin files to for instance /user/plugins/mb/
-Enable short code assets plugin in Grav admin panels
-Create a new twig template, mine is called Gallery where i added this to the content section and upload in your theme folders

<div class="media-boxes-search">
		<span class="media-boxes-icon fa fa-search"></span> <input id="search" placeholder="Search by title" type="text"> <span class="media-boxes-clear fa fa-close"></span>
	</div>
	<div id="grid">
		{% for image in page.media.images|sort|reverse %} {% set imgtitle = image.filename|replace({'.JPG':'.','.jpg':'.','_':' ','-':' ','__':', '}) %}
		<div class="media-box snaps">
			<div class="media-box-title">
				"{{ imgtitle }}"
			</div>
			<div class="media-box-image">
				<div data-thumbnail="{{ image.resize(600,400).quality(100).url }}"></div>
				<div class="thumbnail-overlay">
					<i class="fa fa-plus mb-open-popup" data-src="{{ image.quality(100).url }}" data-title="{{ imgtitle }}"></i>
				</div>
			</div>
		</div>{% endfor %}
	</div>

-Back to admin
-Create a page
-Advanced -> Page Template -> Dropdown -> Gallery
-Back to content tab, put the following in the page body. Of course you could put this in your template as well but for starters this is fine, easily adjustable if something is wrong. not sure if anything has changed in the past year, so check all the assets and don’t just copy this

[assets=css]
/user/plugins/mb/components/Fancybox/jquery.fancybox.min.css
[/assets]
[assets=css]
/user/plugins/mb/css/mediaBoxes.css
[/assets]
[assets=js]
/user/plugins/mb/components/Isotope/jquery.isotope.min.js
[/assets]
[assets=js]
/user/plugins/mb/components/imagesLoaded/jquery.imagesLoaded.min.js
[/assets]
[assets=js]
/user/plugins/mb/components/Transit/jquery.transit.min.js
[/assets]
[assets=js]
/user/plugins/mb/components/jQuery Easing/jquery.easing.js
[/assets]
[assets=js]
/user/plugins/mb/components/Waypoints/waypoints.min.js
[/assets]
[assets=js]
/user/plugins/mb/components/Modernizr/modernizr.custom.min.js
[/assets]
[assets=js]
/user/plugins/mb/components/Fancybox/jquery.fancybox.min.js
[/assets]
[assets=js]
/user/plugins/mb/js/jquery.mediaBoxes.dropdown.js
[/assets]
[assets=js]
/user/plugins/mb/js/jquery.mediaBoxes.js
[/assets]

[assets=inlineJs]
    $('#grid').mediaBoxes({
        columnWidth: 'auto',
        columns: 3,
        boxesToLoadStart: 12,
        boxesToLoad: 9,
        search: '#search',
        searchTarget: '.media-box-title',
         }); 
[/assets]

The last bit are my preferences

Upload photos and have a look at your page

Ps of course these thumb sizes are ridiculous:

<div data-thumbnail="{{ image.resize(600,400).quality(100).url }}"></div>

But when I load these in say 340px div they look much crisper this way. And only a few people login to see my pictures anyway so who cares about loading time :wink:

And to conclude I was worried about the amount of pictures and data. But right now one gallery has 600 pictures and some 1200 MB and it’s loading crazy fast still

1 Like

@Japhy Many thanks for your quick and detailed instructions.
Now it’s my turn… I’ ll report when I made it and the gallery is running.