Simple Image Gallery Using Gridsome
18 Jul 2020This portfolio site I'm building needs a gallery of lettering images. I haven't found a specific tutorial for this use case. After googling for a while I found this Stackoverflow answer, it's for Nuxt but I tought it might work for Gridsome too.
So I'm documenting the process and sharing it with others who might want to do similar thing. Note this is a simple implementation that utilizes Webpack feature instead of GraphQL.
In my case, I'll be making the gallery under /lettering
URL, so I'm making new file on /pages/Lettering.vue
. There's two part of this: the page itself, and gallery of images. I'll be putting the image on ./static/images/lettering/...
. It looks like this in directory structure: (other files ommited)
๐ฆproject-name
โโ๐src
โ โโ๐pages
โ โ โโ๐Lettering.vue
โ โโ...
โโ๐static
โ โโ๐images
โ โ โโ๐lettering
โ โ โ โโ (image files goes here)
โโ ...
I also introduce name template for the image files here: image-name_YY-MM-DD.jpg
. I'm doing this so I can sort the images by Date later. You can change the name template to your liking.
Here's what goes into actual page Lettering.vue
:
<template>
<Layout>
<h1 class="mb-4 text-4xl leading-none uppercase lg:text-6xl">Lettering</h1>
<div class="flex flex-wrap pb-20 -mx-3">
<div class="w-full sm:w-1/2 md:w-1/3 lg:w-1/4" v-for="(image, index) in sortedImages" :key="index">
<div class="px-3 my-3">
<div class="relative shadow-lg" style="padding-bottom: 100%">
<g-image class="absolute object-cover w-full h-full"
:src="image.pathLong" :title="`20${image.year}-${image.month}-${image.day}`"/>
</div>
</div>
</div>
</div>
</Layout>
</template>
<script>
export default {
metaInfo: {
title: 'Lettering'
},
data() {
return {
images: []
}
},
mounted() {
this.importAll(require.context('../../static/images/lettering/', true, /\.jpg$/))
},
computed: {
sortedImages() {
return this.images.sort((a, b) => (
new Date(`20${b.year}`, b.month, b.day) -
new Date(`20${a.year}`, a.month, a.day)
))
}
},
methods: {
importAll(r) {
r.keys().forEach(key => (this.images.push({
pathLong: r(key),
pathShort: key,
year: key.split('_').pop().replace('.jpg', '').split('-')[0],
month: key.split('_').pop().replace('.jpg', '').split('-')[1],
day: key.split('_').pop().replace('.jpg', '').split('-')[2],
})))
}
},
}
</script>
To import all the images, we are utilizing webpack require.context
inside the image directory. Then for each image, we put them into images
array as an object with few attributes: pathLong, year, month, day
. You can optimize or change the code to your liking, but for now it works okay.
I'm also using tailwind CSS here, with a minor rule breaking inline style for padding-bottom
trickery to get that square div
ratio.
Hope this helps! Thanks for reading.