Search code examples
htmlcsshovercss-transforms

Resize image on hover but keep aspect ratio and inside screen


this is meant to work only on desktop.

The thing is, even though I have managed to zoom images on hover and maintain aspect ratio, I can't manage to make a smooth hovering experience.

The images bounding box (or parent divs) are bigger than the images so when the users scroll out of the image the zoom effect keeps working (logically) plus the images at the right of the screen, get out of view when hovering.

How can I keep the aspect ratio, keep the images on screen, keep the rest of the content in place and zoom only when the user is hovering the image (back to default when the user stop hovering the image).

.la-inversion {
  max-width: 100%;
}
.la-inversion__izquierda img {
  max-width: 100%;
}
.la-inversion__derecha__titulo {
  font-size: 3.5rem;
  margin-left: 2rem;
  margin-top: 2.5rem;
}
.la-inversion__derecha__subtitulo {
  margin-left: 2rem;
  margin-top: 1rem;
  width: 71.5%;
}
.la-inversion__derecha__imagenes {
  margin-top: 1rem;
  display: flex;
  justify-content: space-evenly;
  flex-direction: column;
}
.la-inversion__derecha__imagenes__derecha {
  display: flex;
  height: 90vw;
  justify-content: space-evenly;
}
.la-inversion__derecha__imagenes__derecha div {
  width: 45vw;
  height: 45vw;
  overflow: hidden;
  position: relative;
}
.la-inversion__derecha__imagenes__derecha div img {
  position: absolute;
  left: -1000%;
  right: -1000%;
  top: -1000%;
  bottom: -1000%;
  margin: auto;
  min-height: 100%;
  min-width: 100%;
  max-width: 150%;
  max-height: 150%;
}
.la-inversion__derecha__imagenes__derecha div:nth-child(2) {
  align-self: flex-end;
}
.la-inversion__derecha__imagenes__izquierda {
  display: flex;
  height: 90vw;
  justify-content: space-evenly;
}
.la-inversion__derecha__imagenes__izquierda div {
  height: 45vw;
  width: 45vw;
  overflow: hidden;
  position: relative;
}
.la-inversion__derecha__imagenes__izquierda div img {
  position: absolute;
  left: -1000%;
  right: -1000%;
  top: -1000%;
  bottom: -1000%;
  margin: auto;
  min-height: 100%;
  min-width: 100%;
  max-width: 150%;
  max-height: 150%;
}
.la-inversion__derecha__imagenes__izquierda div:nth-child(2) {
  align-self: flex-end;
}

  .img-scale-div{
    transition: .3s;
  }
  .img-scale-img{
    transition: .3s;
  }
@media only screen and (min-width: 769px) {

  .img-scale-div:hover {
    transform: scale(4, 4) translate(-2vw);
    z-index: 2;
    align-self: center;
    outline: groove;
  }
  .img-scale-div:hover > .img-scale-img {
    position: initial;
    margin: 0;
    min-height: 0;
    min-width: 0;
    max-width: 100%;
    max-height: 100%;
  }

.la-inversion {
    display: flex;
    -moz-column-gap: 7.5rem;
         column-gap: 7.5rem;
    width: calc( 100% - 9rem );
    justify-content: center;
    margin: 20rem auto 0;
  }
  .la-inversion__izquierda {
    flex: 2 0 0;
  }
  .la-inversion__derecha {
    flex: 1 0 0;
  }
  .la-inversion__derecha__subtitulo {
    margin-left: 0rem;
    width: auto;
    -moz-column-count: 2;
         column-count: 2;
    font-size: 16px;
    -moz-column-gap: 2rem;
         column-gap: 2rem;
    -moz-column-width: 234px;
         column-width: 234px;
  }
  .la-inversion__derecha__imagenes {
    flex-direction: row;
    -moz-column-gap: 1.5rem;
         column-gap: 1.5rem;
    margin-top: 4rem;
  }
  .la-inversion__derecha__imagenes__derecha {
    height: 236px;
    -moz-column-gap: 1.5rem;
         column-gap: 1.5rem;
  }
  .la-inversion__derecha__imagenes__derecha__titulo {
    font-size: 4.5rem;
    text-align: center;
    margin-left: 0;
  }
  .la-inversion__derecha__imagenes__derecha div {
    width: 118px;
    height: 118px;
  }
  .la-inversion__derecha__imagenes__izquierda {
    height: 236px;
    -moz-column-gap: 1.5rem;
         column-gap: 1.5rem;
  }
  .la-inversion__derecha__imagenes__izquierda div {
    width: 118px;
    height: 118px;
  }

}
<div class="la-inversion">

            <div class="la-inversion__izquierda">
                <img src="https://i.ibb.co/JktFp0J/imagen-vertical-inversion.png" alt="" >
            </div>

            <div class="la-inversion__derecha">
                <h2 class="la-inversion__derecha__titulo">1. La Inversión</h2>
                <p class="la-inversion__derecha__subtitulo">Rodeado de montañas, enclavado en un valle amplio con vegetación baja y autóctona que da la sensación de estar en plena estepa patagónica aunque en verdad nos encontramos dentro del bosque andino. <br><br>Suspendisse faucibus tincidunt pulvinar. Suspendisse quis tortor et sem lobortis auctor vehicula vitae libero. Aliquam nisl odio, sagittis.</p>
                <div class="la-inversion__derecha__imagenes">

                    <div class="la-inversion__derecha__imagenes__derecha">
                        <div class="img-scale-div"><img class="img-scale-img"  src="https://i.ibb.co/6R2XWkS/ba-o-vertical.jpg" alt="" srcset=""></div>
                        <div class="img-scale-div"><img class="img-scale-img"  src="https://i.ibb.co/Jj5yHgt/ba-o-horizontal.jpg" alt="" srcset=""></div>
                    
                    </div>

                    <div class="la-inversion__derecha__imagenes__izquierda">
                        <div class="img-scale-div"><img class="img-scale-img" src="https://i.ibb.co/SPpkq6Y/cocina-horizontal.jpg" alt="" srcset=""></div>
                        <div class="img-scale-div"><img class="img-scale-img" src="https://i.ibb.co/wMQzXxT/living-horizontal.jpg" alt="" srcset=""></div>
                    
                    </div>
                </div>
            </div>
        
        </div>


Solution

  • You need to get images natural sizes, for that you'll need a bit of javascript. Feel free to use dataset to get initial size values from images, I simply wrote them like I'd write css.

    const onScaleImage = (e) => {
       const image = e.target.closest('.img-scale-img');
       
      if (image) {
        if (e.type === 'mouseover') {
           image.style.height = `${image.naturalHeight}px`;
           image.style.width = `${image.naturalWidth}px`; 
        } else {
          image.style.height = '118px';
          image.style.width = '118px'; 
        }
      }
    }
    
    document.addEventListener('mouseover', onScaleImage)
    document.addEventListener('mouseout', onScaleImage)
    .la-inversion {
      max-width: 100%;
    }
    .la-inversion__izquierda img {
      max-width: 100%;
    }
    .la-inversion__derecha__titulo {
      font-size: 3.5rem;
      margin-left: 2rem;
      margin-top: 2.5rem;
    }
    .la-inversion__derecha__subtitulo {
      margin-left: 2rem;
      margin-top: 1rem;
      width: 71.5%;
    }
    .la-inversion__derecha__imagenes {
      margin-top: 1rem;
      display: flex;
      justify-content: space-evenly;
      flex-direction: column;
    }
    .la-inversion__derecha__imagenes__derecha {
      display: flex;
      justify-content: space-evenly;
    }
    .la-inversion__derecha__imagenes__derecha div {
      position: relative;
    }
    .la-inversion__derecha__imagenes__derecha div img {
          height: 100%;
        width: 100%;
        object-fit: cover;
        
      position: absolute;
      right: 0;
          top: 50%;
        transform: translateY(-50%);
    }
    .la-inversion__derecha__imagenes__derecha div:nth-child(2) {
      align-self: flex-end;
    }
    .la-inversion__derecha__imagenes__izquierda {
      display: flex;
      justify-content: space-evenly;
    }
    .la-inversion__derecha__imagenes__izquierda div {
      position: relative;
    }
    .la-inversion__derecha__imagenes__izquierda div img {
      height: 100%;
      width: 100%;
      object-fit: cover;
       position: absolute;
      right: 0;
          top: 50%;
        transform: translateY(-50%);
    }
    .la-inversion__derecha__imagenes__izquierda div:nth-child(2) {
      align-self: flex-end;
    }
    
      .img-scale-div{
        transition: .3s;
      }
      .img-scale-img{
        transition: .3s;
      }
    @media only screen and (min-width: 769px) {
    .la-inversion {
        display: flex;
        -moz-column-gap: 7.5rem;
             column-gap: 7.5rem;
        width: calc( 100% - 9rem );
        justify-content: center;
        margin: 20rem auto 0;
      }
      .la-inversion__izquierda {
        flex: 2 0 0;
      }
      .la-inversion__derecha {
        flex: 1 0 0;
      }
      .la-inversion__derecha__subtitulo {
        margin-left: 0rem;
        width: auto;
        -moz-column-count: 2;
             column-count: 2;
        font-size: 16px;
        -moz-column-gap: 2rem;
             column-gap: 2rem;
        -moz-column-width: 234px;
             column-width: 234px;
      }
      .la-inversion__derecha__imagenes {
        flex-direction: row;
        -moz-column-gap: 1.5rem;
             column-gap: 1.5rem;
        margin-top: 4rem;
      }
      .la-inversion__derecha__imagenes__derecha {
        height: 236px;
         display: flex;
        gap: 1.5rem;
      }
      .la-inversion__derecha__imagenes__derecha__titulo {
        font-size: 4.5rem;
        text-align: center;
        margin-left: 0;
      }
      .img-scale-img:hover {
            outline: groove;
      }
      .la-inversion__derecha__imagenes__derecha .img-scale-div {
        width: 118px;
        height: 118px;
      }
      .la-inversion__derecha__imagenes__izquierda {
          height: 236px;
        display: flex;
        gap: 1.5rem;
      }
      .la-inversion__derecha__imagenes__izquierda .img-scale-div {
        width: 118px;
        height: 118px;
      }
    
    }
    <div class="la-inversion">
    
                <div class="la-inversion__izquierda">
                    <img src="https://i.ibb.co/JktFp0J/imagen-vertical-inversion.png" alt="" >
                </div>
    
                <div class="la-inversion__derecha">
                    <h2 class="la-inversion__derecha__titulo">1. La Inversión</h2>
                    <p class="la-inversion__derecha__subtitulo">Rodeado de montañas, enclavado en un valle amplio con vegetación baja y autóctona que da la sensación de estar en plena estepa patagónica aunque en verdad nos encontramos dentro del bosque andino. <br><br>Suspendisse faucibus tincidunt pulvinar. Suspendisse quis tortor et sem lobortis auctor vehicula vitae libero. Aliquam nisl odio, sagittis.</p>
                    <div class="la-inversion__derecha__imagenes">
    
                        <div class="la-inversion__derecha__imagenes__derecha">
                            <div><div class="img-scale-div"><img class="img-scale-img"  src="https://i.ibb.co/6R2XWkS/ba-o-vertical.jpg" alt="" srcset=""></div></div>
                           <div> <div class="img-scale-div"><img class="img-scale-img"  src="https://i.ibb.co/Jj5yHgt/ba-o-horizontal.jpg" alt="" srcset=""></div></div>
                        
                        </div>
    
                        <div class="la-inversion__derecha__imagenes__izquierda">
                            <div><div class="img-scale-div"><img class="img-scale-img" src="https://i.ibb.co/SPpkq6Y/cocina-horizontal.jpg" alt="" srcset=""></div></div>
                            <div><div class="img-scale-div"><img class="img-scale-img" src="https://i.ibb.co/wMQzXxT/living-horizontal.jpg" alt="" srcset=""></div></div>
                        
                        </div>
                    </div>
                </div>
            
            </div>