Slide show with lazy loading, srcset, associated captions: time wasted parsing image formats

46 Views Asked by At

I have constructed a basic website to showcase my photographs. This is an improvement on an earlier attempt built via the native iWeb editor on an old iMac. That attempt displayed the images at low resolution and used a separate verbose webpage for each image. I am trying to simplify the structure and improve image quality. Each image is 1500x1000 px max, with an srcset including versions at 800x533 and 320x213 px. Each image also has two labels. Images are grouped in themes, one html page per theme, with an associated folder of images. The format is the same for all themes, so one css file serves for all. The (non-commercial) site is already live at www.allmyeye.co.uk but impossibly slow.

I will attach a cut-down version of one html page, with just three images, and the CSS file. (Please be kind, I am a total newbie at HTML, JS and CSS.) My intention with the "container" class is to allow flexi formatting; and with the "square" class to allow portrait and landscape images with the same proportions (3:2 or 2:3) to fit on the screen at the same physical size. This latter is particularly important to me.

My first problem was that because each theme can be up to 40 images, they all tried to load in parallel, causing very slow page loading. I overcame this by setting loading="lazy" for all but the first image, and that does seem to result in images being loaded sequentially. However, page loading is still very slow. As far as I can tell, the browser parses the format for all images in turn, even though it doesn't load all the image files at that point.

I don't want reduce image quality, because that was the whole point of this revision. I'm looking for a way to load only the first two images (one on display, the next loaded in readiness), and then add the next in the queue, with its associated captions, when direction arrows (on-screen or keyboard) are pressed. I'd like the device to decide just once on the format (i.e. the size of the "square" class relative to screen dimensions) and thus on which size of image to request from the server.

I'd be really grateful for any ideas or better solutions. I'm trying to avoid the use of a lazy-load library because (or if) that imposes any restrictions on the formatting of images, which I have already solved to my satisfaction.

Thanks in anticipation.

    <!DOCTYPE html>
    <html lang=“en”>
    
    <head>
    
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta charset="UTF-8">
    
    <title>This theme</title>
    <link rel="stylesheet" href="example.css">
    </head>
    
    <body>
    
    <div class="dropdown">
      <button class="dropbtn">&#9776</button>
      <div class="dropdown-content">
        <a href="theme1.html">Theme1</a>
        <a href="theme2.html">Theme2</a>
        <a href="theme3.html">Theme3</a>
        <a href="theme4.html">Theme4</a>
        <a href="theme5.html">Theme5</a>
    </div>
    </div>
    
    <span><header>Website name<small>- author</small></header></span>
    <br><br>
    
    <div class="container">
        
      <div class="square">
        
        <a class="prev" onclick="plusSlides(-1)">&#10094;</a>
        <a class="next" onclick="plusSlides(1)">&#10095;</a> 
      
        <div class="mySlides">
          <div>
            <img src="example1-sm.png"
              srcset="example1-sm.png 320w, example1-med.png 800w, example1-lg.png 1500w">
            <div class="text">
              <span style="float:left"> This theme: 1 / 3</span>
              <span style="float: right">Caption1</span>
            </div>
            <div style="clear: both;"></div>
          </div>
        </div>
            
        <div class="mySlides">
          <div>
            <img loading="lazy" src="example2-sm.png"
              srcset="example2-sm.png 320w, example2-med.png 800w, example2-lg.png 1500w">
            <div class="text">
              <span style="float:left"> This theme: 2 / 3</span>
              <span style="float: right">Caption2</span>
            </div>
            <div style="clear: both;"></div>
          </div>
        </div>
            
        <div class="mySlides">
          <div>
            <img loading="lazy" src="example3-sm.png" 
              srcset="example3-sm.png 320w, example3-med.png 800w, example3-lg.png 1500w">
            <div class="text">
              <span style="float:left"> This theme: 3 / 3</span>
              <span style="float: right">Caption3</span>
            </div>
            <div style="clear: both;"></div>
          </div>
        </div>
      </div> 
    </div>
    
    
    <script>
    
      window.addEventListener(
        "keydown",
        (event) => {
          switch (event.code) {
            case "ArrowLeft":
              plusSlides(-1);
              break;
            case "ArrowRight":
            plusSlides(1);
              break;
          }
        },
        true
      );
    
      let slideIndex = 1;
      showSlides(slideIndex);
    
      function plusSlides(n) {
        showSlides(slideIndex += n);
      }
    
      function currentSlide(n) {
        showSlides(slideIndex = n);
      }
    
      function showSlides(n) {
        let i;
        let slides = document.getElementsByClassName("mySlides");
        if (n > slides.length) {slideIndex = 1}    
        if (n < 1) {slideIndex = slides.length}
        for (i = 0; i < slides.length; i++) {
          slides[i].style.display = "none";  
        }
        slides[slideIndex-1].style.display = "block";
      }
    </script>
    
    </body>
    </html> 
    * {box-sizing:content-box}
    
    body {
      font-size: calc(15px + 0.390625vw);
    }
      
    header { 
      display: block;
      text-align:left;
      color:  grey;
      font-family: Helvetica, Arial, sans-serif;
      font-size: 1.5vh;
      padding-left: 1.0vh;
      padding-top: 1.0vh;
    }
      
    .container {
      position: relative;
      max-width: 100vw;
      max-height: 95vmin;
      margin-left: 0%;
      margin-right:0%;
      padding: 0%;
      align-items: center;
      justify-content: center;
    }
    
    .square {
      display: flex;
      flex-direction: column;
      position: relative;
      margin: auto;
      padding: 0%;
      align-items: center;
      justify-content: center;
      width: 90vmin;
      height:90vmin;
    }
    
    img {
      width: auto;
      height: auto;
      max-width: 90vmin;
      max-height:90vmin;
      image-rendering: high quality;
      outline: solid 0.075rem black;
      object-fit: contain;
    }
    
    /* Hide the images by default */
    .mySlides {
      display: none;
    }
    
    /* Next & previous buttons */
    .prev {
      cursor: pointer;
      position: absolute;
      bottom: 2%;
      left: 0%;
      width: auto;
      color: lightgrey;
      /* padding: 2vh; */
      font-weight: normal;
      font-size: 2.5vh;
      transition: 0.6s ease;
      user-select: none;
    }
    
    .next {
      cursor: pointer;
      position: absolute;
      bottom: 2%;
      right: 0%;
      width: auto;
      color: lightgrey;
      /* padding: 2vh; */
      font-weight: normal;
      font-size: 2.5vh;
      transition: 0.6s ease;
      user-select: none;
    }
    
    /* On hover, add a black background color with a little bit see-through */
    .prev:hover, .next:hover {
      background-color: rgba(0,0,0,0.8);
    }
    
    /* Counter and caption text */
    .text {
      color: lightgrey;
      font-family: Helvetica, Arial, sans-serif;
      font-size: 1.2vh;
      padding: 0;
      position: relative;
      bottom: 0.01vh;
      width: 100%;
    }
    
    /* The container needed to position the dropdown content */
    .dropdown {
      z-index: 2;
      position: absolute;
      top: 0;
      right: 0;
      text-align: center;
      padding: 1.5rem;
      transition: all 0.3s ease; /* Add transition for hover effects */
      color: grey; 
    }
    
    /* Show the dropdown menu on hover */
    .dropdown:hover .dropdown-content {
      display: block;
    }
    
    /* Change the background color of the dropdown button when the dropdown content is shown */
    .dropdown:hover .dropbtn {
      background-color: #94df97d1;
    }
    
    /* Dropdown Button */
    .dropbtn {
      background-color: white;
      color: grey;
      padding: 1vmin;
      font-family: sans-serif;
      font-size: 3vmax;
      border: none;
      cursor: pointer;
      transition: all 0.3s ease; /* Add transition for hover effects */
    }
    
    /* Dropdown Content (Hidden by Default) */
    .dropdown-content {
      display: none;
      position: absolute;
      background-color: #f1f1f1;
      font-family: sans-serif;
      font-size: 1.5vh;
      line-height: normal;
      right: 0;
      min-width: 12em;
      box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
      z-index: 2;
    }
    
    /* Links inside the dropdown */
    .dropdown-content a {
      color: grey;
      padding: 3vmin;
      text-decoration: none;
      display: block;
    }
    
    /* Change color of dropdown links on hover */
      .dropdown-content a:hover {
        background-color: #94df97d1;
        color: grey;
    }
    
    
0

There are 0 best solutions below