Build a Lightbox Viewer - Build a Lightbox Viewer

Tell us what’s happening:

JavaScript code loads before DOM has finished loading even with defer in the tag.

This causes for instance const lightbox = document.querySelector(".lightbox"); to return null when console.log is called on lightbox.

I can only get my code to work properly in the lesson browser editor if I wrap all of my code in the script.js file in an DOMContentLoaded event. If I save the project files locally and open them in Chrome, the defer attribute works as intended.

Am I doing something wrong?

Your code so far

<!-- file: index.html -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Lightbox Viewer</title>
    <link rel="stylesheet" href="styles.css" />
    <script src="script.js" defer></script>
  </head>

  <body>
    <h1>Lightbox Viewer</h1>
    <div class="gallery">
      <img
        src="https://cdn.freecodecamp.org/curriculum/labs/stonehenge-thumbnail.jpg"
        alt=""
        class="gallery-item"
      />
      <img
        src="https://cdn.freecodecamp.org/curriculum/labs/storm-thumbnail.jpg"
        alt=""
        class="gallery-item"
      />
      <img
        src="https://cdn.freecodecamp.org/curriculum/labs/trees-thumbnail.jpg"
        alt=""
        class="gallery-item"
      />
    </div>
    <div class="lightbox">
      <button id="close-btn">&times;</button>
      <img src="" alt="" id="lightbox-image" />
    </div>
  </body>
</html>

/* file: styles.css */
* {
    box-sizing: border-box;
    padding: 0;
    margin: 0;
}

h1 {
    background-color: lightgrey;
    text-align: center;
    margin-top: 20%;
}

body {
    width: 100%;
}

.gallery {
    padding: 20px;
    display: grid;
    grid-template-columns: 30% 30% 30%;
    gap: 15px;
    justify-content: center;
}

.gallery img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    background-color: aliceblue;
    transform: scale(1);
    transition: transform 0.2s ease-in-out;
}

.gallery img:hover {
    transform: scale(1.1);
}

.lightbox {
    display: none;
    top: 0;
    left: 0;
    position: fixed;
    background-color: rgba(79, 79, 79, 0.963);
    width: 100%;
    height: 100%;
    align-items: center;
    justify-content: center;
}

#lightbox-image {
    width: 80%;
    height: 80%;
    object-fit: contain;
}

#close-btn {
    position: absolute;
    top: 10px;
    right: 10px;
    width: 30px;
    height: 30px;
    border-radius: 5px;
}
/* file: script.js */
document.addEventListener("DOMContentLoaded", function () {
  const gallery = document.querySelectorAll(".gallery-item");
  const lightbox = document.querySelector(".lightbox");
  const lightboxImage = document.getElementById("lightbox-image");
  const closeButton = document.getElementById("close-btn");

  gallery.forEach((pic) => {
    pic.addEventListener("click", (event) => {
      let clickedImgSrc = event.target.getAttribute("src");
      let updatedImgSrc = clickedImgSrc.replace("-thumbnail.jpg", ".jpg");
      lightboxImage.setAttribute("src", updatedImgSrc);
      lightbox.style.display = "flex";
    });
  });

  lightbox.addEventListener("click", () => {
    lightbox.style.display = "none";
  });

  closeButton.addEventListener("click", () => {
    lightbox.style.display = "none";
  });
});

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36

Challenge Information:

Build a Lightbox Viewer - Build a Lightbox Viewer

It’s not typical to include the script tag to link an external JS file inside the head element. It’s usually placed just before the closing body tag without defer.

Have you tried that?

Thank you for your reply!

Yes, this does solve the issue in the lesson editor and I’ve read on the forum that this is not covered in the curriculum so I will use this solution for future projects.