Home > Enterprise >  Picture Tag doesn't resize properly on loading two sources (png and webp)
Picture Tag doesn't resize properly on loading two sources (png and webp)

Time:01-28

I'm building a website that has a 3D book:

preview

My main goal is to support a png and a webp image for all browsers. If I only load one image all is working fine:

.book-container {
    display: flex;
    align-items: center;
    justify-content: center;
    perspective: 600px;
  }
  
  @keyframes initAnimation {
    0% {
      transform: rotateY(0deg);
    }
    100% {
      transform: rotateY(-30deg);
    }
  }
  
  .book {
    width: 200px;
    height: 320px;
    position: relative;
    transform-style: preserve-3d;
    transform: rotateY(-30deg);
    transition: 1s ease;
    animation: 1s ease 0s 1 initAnimation;
  }
  
  .book:hover {
    transform: rotateY(0deg);
  }
  
  .book > :first-child {
    position: absolute;
    top: 0;
    left: 0;
    background-color: red;
    width: 200px;
    height: 320px;
    transform: translateZ(25px);
    background-color: #01060f;
    border-radius: 0 2px 2px 0;
    box-shadow: 5px 5px 20px #E5E4E2;
  }
  
  .book::before {
    position: absolute;
    content: ' ';
    background-color: blue;
    left: 0;
    top: 3px;
    width: 48px;
    height: 314px;
    transform: translateX(172px) rotateY(90deg);
    background: linear-gradient(90deg, 
      #fff 0%,
      #f9f9f9 5%,
      #fff 10%,
      #f9f9f9 15%,
      #fff 20%,
      #f9f9f9 25%,
      #fff 30%,
      #f9f9f9 35%,
      #fff 40%,
      #f9f9f9 45%,
      #fff 50%,
      #f9f9f9 55%,
      #fff 60%,
      #f9f9f9 65%,
      #fff 70%,
      #f9f9f9 75%,
      #fff 80%,
      #f9f9f9 85%,
      #fff 90%,
      #f9f9f9 95%,
      #fff 100%
      );
  }
  
  .book::after {
    position: absolute;
    top: 0;
    left: 0;
    content: ' ';
    width: 200px;
    height: 320px;
    transform: translateZ(-25px);
    background-color: #01060f;
    border-radius: 0 2px 2px 0;
    box-shadow: -10px 0 50px 10px #666;
  }
<a 
    
    href="#"
    target="_blank"
    rel="noreferrer noopener">
    <div >
      <img
        alt="My Cover"
        src="https://i.stack.imgur.com/1MPyO.png"
      />
    </div>
</a>

But when I add the picture element to support both, the image loses the resize:

preview2

.book-container {
  display: flex;
  align-items: center;
  justify-content: center;
  perspective: 600px;
}

@keyframes initAnimation {
  0% {
    transform: rotateY(0deg);
  }
  100% {
    transform: rotateY(-30deg);
  }
}

.book {
  width: 200px;
  height: 320px;
  position: relative;
  transform-style: preserve-3d;
  transform: rotateY(-30deg);
  transition: 1s ease;
  animation: 1s ease 0s 1 initAnimation;
}

.book:hover {
  transform: rotateY(0deg);
}

.book > :first-child {
  position: absolute;
  top: 0;
  left: 0;
  background-color: red;
  width: 200px;
  height: 320px;
  transform: translateZ(25px);
  background-color: #01060f;
  border-radius: 0 2px 2px 0;
  box-shadow: 5px 5px 20px #E5E4E2;
}

.book::before {
  position: absolute;
  content: ' ';
  background-color: blue;
  left: 0;
  top: 3px;
  width: 48px;
  height: 314px;
  transform: translateX(172px) rotateY(90deg);
  background: linear-gradient(90deg, 
    #fff 0%,
    #f9f9f9 5%,
    #fff 10%,
    #f9f9f9 15%,
    #fff 20%,
    #f9f9f9 25%,
    #fff 30%,
    #f9f9f9 35%,
    #fff 40%,
    #f9f9f9 45%,
    #fff 50%,
    #f9f9f9 55%,
    #fff 60%,
    #f9f9f9 65%,
    #fff 70%,
    #f9f9f9 75%,
    #fff 80%,
    #f9f9f9 85%,
    #fff 90%,
    #f9f9f9 95%,
    #fff 100%
  );
}

.book::after {
  position: absolute;
  top: 0;
  left: 0;
  content: ' ';
  width: 200px;
  height: 320px;
  transform: translateZ(-25px);
  background-color: #01060f;
  border-radius: 0 2px 2px 0;
  box-shadow: -10px 0 50px 10px #666;
}
<a 
        href="#"
        target="_blank"
        rel="noreferrer noopener">
    
        <div >
          <picture>
            <source srcset="https://i.ibb.co/grB6NbQ/THE-BOOK-cover-image.webp" type="image/webp">
            <source srcset="https://i.stack.imgur.com/1MPyO.png" type="image/png">

            <img                     
              alt="My Cover"
              src="https://i.stack.imgur.com/1MPyO.png"/>
          </picture>
        </div>
    </a>

Any idea what should I change? I guess the main issue is in this part of the code:

.book > :first-child {
    position: absolute;
    top: 0;
    left: 0;
    background-color: red;
    width: 200px;
    height: 320px;
    transform: translateZ(25px);
    background-color: #01060f;
    border-radius: 0 2px 2px 0;
    box-shadow: 5px 5px 20px #E5E4E2;
  }

Here is the full snippet if you want to check it:

https://jsfiddle.net/p01vac52/1/

But I'm not so sure, I didn't expect that the picture element will fully break it. Or do you think it's a better idea to change the source using JS?

CodePudding user response:

As commented,

The srcset attribute selects which image to load based on its size values and device specs, the picture / img elements will still need width/height values to scale the loaded image to the required size.

I added img { width: 100% } to make the image fit inside .book { width: 200px; height: 320px; }.

.book-container {
  display: flex;
  align-items: center;
  justify-content: center;
  perspective: 600px;
}

@keyframes initAnimation {
  0% {
    transform: rotateY(0deg);
  }
  100% {
    transform: rotateY(-30deg);
  }
}

.book {
  width: 200px;
  height: 320px;
  position: relative;
  transform-style: preserve-3d;
  transform: rotateY(-30deg);
  transition: 1s ease;
  animation: 1s ease 0s 1 initAnimation;
}

img {
  width: 100%;
}

.book:hover {
  transform: rotateY(0deg);
}

.book> :first-child {
  position: absolute;
  top: 0;
  left: 0;
  background-color: red;
  width: 200px;
  height: 320px;
  transform: translateZ(25px);
  background-color: #01060f;
  border-radius: 0 2px 2px 0;
  box-shadow: 5px 5px 20px #E5E4E2;
}

.book::before {
  position: absolute;
  content: ' ';
  background-color: blue;
  left: 0;
  top: 3px;
  width: 48px;
  height: 314px;
  transform: translateX(172px) rotateY(90deg);
  background: linear-gradient(90deg, #fff 0%, #f9f9f9 5%, #fff 10%, #f9f9f9 15%, #fff 20%, #f9f9f9 25%, #fff 30%, #f9f9f9 35%, #fff 40%, #f9f9f9 45%, #fff 50%, #f9f9f9 55%, #fff 60%, #f9f9f9 65%, #fff 70%, #f9f9f9 75%, #fff 80%, #f9f9f9 85%, #fff 90%, #f9f9f9 95%, #fff 100%);
}

.book::after {
  position: absolute;
  top: 0;
  left: 0;
  content: ' ';
  width: 200px;
  height: 320px;
  transform: translateZ(-25px);
  background-color: #01060f;
  border-radius: 0 2px 2px 0;
  box-shadow: -10px 0 50px 10px #666;
}
<a  href="#" target="_blank" rel="noreferrer noopener">
  <div >
    <picture>
      <source srcset="https://i.ibb.co/grB6NbQ/THE-BOOK-cover-image.webp" type="image/webp">
      <source srcset="https://i.stack.imgur.com/1MPyO.png" type="image/png">

      <img alt="My Cover" src="https://i.stack.imgur.com/1MPyO.png" />
    </picture>
  </div>
</a>

  • Related