Search code examples
htmlcssslideshow

html picture tag and list tag combined


I want to create a pure CSS3 slideshow more or less like this one:

Pure CSS Slideshow

My actual HTML already uses the <picture> tag to set specific images according to the display-port's orientation, portrait or landscape. The tutorial for the slideshow is using an <ul>, with several <li>elements to set the slideshow's pictures.

When i try to create that <ul> and <li> elements within my <picture>element, the browser can't find the image(s) anymore.

Here's part of my code:

HTML:

<div id="image">
  <picture>
    <source media="all and (orientation: portrait)" srcset="images/faust_portrait.jpg">
    <source media="all and (orientation: landscape)" srcset="images/faust_landscape.jpg">
    <img src="images/faust_1024.jpg" alt="faust">
  </picture>
</div>

CSS:

#image {
  width: 100%;
  height: auto;
  line-height: 0;
  animation-name: move;
  animation-duration: 1s;
  animation-timing-function: ease-in-out;
  animation-delay: 0.5s;
  animation-iteration-count: 2;
  animation-direction: alternate;
}

@keyframes move {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(100%);
  }
}

#image img {
  width: 100%;
}

So at the moment the corresponding picture is sliding out of the screen and back again, one time. I want to have maybe 5 pictures, all in 2 versions depending on the viewport's orientation) sliding continuously. It is some kind of header of the web page. Any suggestions on how to do that?


Solution

  • WHATWG's standard indicates that the content within a picture tag should be zero or more sources followed by an img tag (and optionally mixed with script-supporting elements). ol and ul tags are none of the listed types and therefore don't belong in a picture tag.

    Put the picture tag in an ol or ul tag instead; it is a list of pictures, not a picture of a list (though I cannot be 100% certain of that...), after all. This should resolve the issue of orientation dependent images.

    As for the slideshow part, you have linked a quite detailed tutorial. I'd say follow along, you should eventually get the desired result. In the tutorial a unique id is used for each picture, you could potentially replace these with the nth-child selector selecting 1 through 5, or whatever number of pictures you want.

    Keep in mind though that using this method of creating a show reel is not very flexible in the regard that when you wish to add/remove an image, you need to rework the timing of each image. Also don't forget that the final image has to return at the end to keep it looking smooth.

    By selecting "Full page" when running the snippit allows you to manipulate the client size (and thus orientation) by resizing the browser. Hope this helps.

    .showreel
    {
      /* Allow for absolute positionng of the child elements.*/
      position:relative;
      z-index:0;
      overflow:hidden;
    
      /* Treat "Landscape" as default.*/
      width:64px;
      height:32px;
    
      /* Remove annoying list-style formatting. */
      list-style:none;
      padding:0;
      margin:0;
    }
    /* Resize the showreel when in portait mode. */
    @media (orientation:portrait){.showreel { width:32px; height:64px;}}
    
    .showreel li
    {
      position:absolute;
      left:0; top:0;
    }
    
    /* Using the nth-child() selector instead of ids. */
    .showreel li:nth-child(1){animation: picture_1 3s linear infinite;}
    .showreel li:nth-child(2){animation: picture_2 3s linear infinite;}
    /* Repeat a number of time as necessary. */    
    
    /* Timings need to be tweaked for each new image in the reel. */
    @keyframes picture_1
    {
      0%{top:0; z-index:1;} /* Show first image 1/4 of the time.*/
      25% {top:0; z-index:1;} /* Keeps it in place for the time being.*/
      50% {top:-100%; z-index:0;} /* Move it out of sight, and the other in. */
      75% {top:100%; z-index:0;} /* Return from the bottom. */
      100% {top:0; z-index:1;} /* In view once again. */
    }
    @keyframes picture_2
    {
      0%  {top:100%; z-index:0;}
      25% {top:100%; z-index:0;}
      50% {top:0; z-index:1;}
      75% {top:0; z-index:1;}
      100%{top:-100%; z-index:0;}
    }
    <ul class="showreel">
      <li>
        <picture>
          <source media="all and (orientation:portait)" srcset="https://i.sstatic.net/h2Ojs.png" />
          <source media="all and (orientation:landscape)" srcset="https://i.sstatic.net/ZcG03.png" />
          <img src="https://i.sstatic.net/h2Ojs.png" alt="Crudely drawn picture depicting a landscape or portrait depending on orientation." />
        </picture>
      </li>
      <!-- Any number of other pictures in the showreel. -->
      <li>
        <!-- I'd advice to use different images, unlike this example. -->
        <picture>
          <source media="all and (orientation:portait)" srcset="https://i.sstatic.net/h2Ojs.png" />
          <source media="all and (orientation:landscape)" srcset="https://i.sstatic.net/ZcG03.png" />
          <img src="https://i.sstatic.net/h2Ojs.png" alt="Same picture as before." />
        </picture>
      </li>
    </ul>