DEV Community

Cover image for Building an Image Gallery with Pure JavaScript
Lucas Andrade
Lucas Andrade

Posted on

Building an Image Gallery with Pure JavaScript

Hello there! πŸ‘‹

I'm Lucas, a Brazilian engineer, and this is Yet Another DEV Content nobody asked for (but I made it anyway πŸ˜‚). My goal with this blog is to talk about things related to the software development world and document personal projects I've worked on, while also honing recently acquired knowledge by sharing it. If you like it, follow me for more posts like this one!

Today we'll tackle a small JavaScript project called Image Gallery featured in one of MDN's JavaScript tutorials.

Please note that this is my solution to this challenge and probably not the best one you will find out there. Also note that the code is shown in this article in a manner that not always represent the final files. If you want to check the final code, a link to the Github repository as well as a link to the deployed app are provided in the Reference section at the end of the article.

The GIF below shows how the project should look like when we're finished. Let's build it!

final project gif


πŸ‘£ Step-by-step Breakdown

The MDN tutorial provides initial boilerplate code for this project and all five images that we're going to use.

We won't get into details on how the HTML was structured nor how it was styled since the goal here is to focus on the JavaScript part.

If you open the boilerplate index.html file, this is how it initially looks like:

project initial state

You can immediately notice that the thumbnail images are missing and the button has no functionality for now. So here's what we're going to do step-by-step:

  1. Declare array of image filenames and append them to the DOM (inside the thumb bar);
  2. Add a click event handler to each thumbnail image;
  3. Add a click event handler to the Darken/Lighten button.

1️⃣ Adding the thumbnail images to the DOM

We can do it by first declaring a constant array to hold the image filenames for us. This is a viable alternative because we know the number of images is low and static (five).

Then it is time to declare an object with an alt description for each image. This step is extra important to improve the accessibility of our app and is often overlooked. I chose to use the filenames as keys, so its easier to retrieve the value we want in the next steps.

We'll also need to store a reference to the thumb bar div HTML element, so we can append the images to it next. Fortunately this has been provided in the boilerplate code already as the thumbBar constant.

/** 
  File: "~/main.js"
  Showing: Only code related to step 1
*/

const thumbBar = document.querySelector('.thumb-bar');

/* Declaring the array of image filenames */
const imageFilenames = [
  'pic1.jpg',
  'pic2.jpg',
  'pic3.jpg',
  'pic4.jpg',
  'pic5.jpg',
];

/* Declaring the alternative text for each image file */
const altTexts = {
  'pic1.jpg': 'A closeup of an human eye',
  'pic2.jpg': 'An abstract pattern painting',
  'pic3.jpg': 'A lot of violet and white flowers',
  'pic4.jpg': 'An Egyptian painting in a wall',
  'pic5.jpg': 'A yellow butterfly in a leaf',
};
Enter fullscreen mode Exit fullscreen mode

Next, we'll loop through the array with the forEach method so we can append the images. The image elements will be created inside each iteration of the loop, the needed HTML attributes will be added and finally the element will be appended as a child of the thumb bar container div.

/** 
  File: "~/main.js"
  Showing: Only code related to step 1
*/

/* Looping through images */
imageFilenames.forEach((imageName) => {
  const newImage = document.createElement('img');
  newImage.setAttribute('src', `images/${imageName}`);
  newImage.setAttribute('alt', altTexts[imageName]);
  thumbBar.appendChild(newImage);
});
Enter fullscreen mode Exit fullscreen mode

With this we've finished the first step. Again, we won't dive into how it was styled. This is how it should like now:

A GIF showing the project after step one is finished


2️⃣ Add a click event handler to each thumbnail image

What we want to achieve next is to change the displayed image (the bigger one) whenever the user clicks any of the thumbnail images that we added. In order to achieve that, we will need reference to the displayed image element just like we did for the thumb bar container, but it was also already declared in the boilerplate code.

Let's create a function to handle the click event on the images. Any function passed as a callback to the addEventListener() method will automatically pass the event as an argument. The Event object has a target property that holds a reference to the HTML element that triggered the event. We will use the target element so we can know the new src and alt attributes of the clicked image, and change the attributes of the displayed image to equals the target image.

/** 
  File: "~/main.js"
  Showing: Only code related to step 2
*/

function handleImageClick({ target }) {
  displayedImage.setAttribute('src', target.getAttribute('src'));
  displayedImage.setAttribute('alt', target.getAttribute('alt'));
}

const displayedImage = document.querySelector('.displayed-img');

/* Looping through images */
imageFilenames.forEach((imageName) => {
  const newImage = document.createElement('img');
  newImage.setAttribute('src', `images/${imageName}`);
  newImage.setAttribute('alt', altTexts[imageName]);
  thumbBar.appendChild(newImage);
  img.addEventListener('click', handleImageClick);
});
Enter fullscreen mode Exit fullscreen mode

With this we have successfully achieved step 2 and are only missing the last part!

A GIF showing the project after step2 is completed


3️⃣ Add a click event handler to the Darken/Lighten button

To achieve what we want in the third and last step let's create a function to handle the click event on the button. This function should read the class name value of the button and take one of two actions depending on the result.

If the class is "dark", it means the user clicked the Darken button. When this happens the text content of the button should change to "Lighten", the overlay div background opacity should change to "0.5" and finally the class name should change to "light" so the action changes when the next click happens.

Else it means the class is "light". In this case the button text content should change to "Lighten", the overlay div opacity should change to "0" so it becomes invisible again and finally the class name should change to "dark" so the action changes when the next click happens.

/** 
  File: "~/main.js"
  Showing: Only code related to step 3
*/

/* Wiring up the Darken/Lighten button */
function handleButtonClick() {
  let currentClass = btn.getAttribute('class');
  if (currentClass === 'dark') {
    btn.textContent = 'Lighten';
    overlay.style.backgroundColor = 'rgba(0,0,0,0.5)';
    btn.setAttribute('class', 'light');
  } else {
    btn.textContent = 'Darken';
    overlay.style.backgroundColor = 'rgba(0,0,0,0)';
    btn.setAttribute('class', 'dark');
  }
}

btn.addEventListener('click', handleButtonClick);
Enter fullscreen mode Exit fullscreen mode

We're done! This is how the button functionality should look like now:

A gif of the project ready


If you've read this far, I hope the content has added something for you. If it didn't, remember: This is just another ordinary DEV content 😬.

πŸ€ See ya!

πŸ” References

Image gallery - Learn web development | MDN
Image gallery finished example
Github repository with the final code
Final app deployed on Github Actions

😁 Let's chat!

Github
Linkedin

Top comments (3)

Collapse
 
jonrandy profile image
Jon Randy πŸŽ–οΈ

Next step - remove all the JS. This could be done with only HTML + CSS

Collapse
 
corners2wall profile image
Corners 2 Wall

Sounds crazy, but it's really that

Collapse
 
jonrandy profile image
Jon Randy πŸŽ–οΈ

Not really... you're programmatically setting styles, and using event handlers. All that could be removed in favour of just CSS if you wanted