最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Guide scaling of an image according limits of parents - Stack Overflow

programmeradmin5浏览0评论

Currently I'm helping someone with a page and they needed to display some images of their work. At first I set up a little structure for the display of images to fall under a flex structure.

Now, what I'm trying to do is a transition of an image that when hovered it increases in scale and shows a little footer about the image. But when doing so I find the problem that the scale takes the center position of where the image is.

Thus, the images overflow to the top/bottom/you name it, something that I do not want. So, I was thinking of maybe just moving it to the center, but doing so would cut the transition leaving a glitchy effect onscreen since it is leaving behind the cursor.

Consequently, the last option I thought about is maybe forcing the scale up to adapt and move considering the padding of the parent div (ideally the main div, not body since there is a little nav on the top).

I have tried to think of ways of trying to implement this but I have no clue where to even start. I have seen methods of scaling child to a parent div like this, but that was not what I had in mind.

I just want to prevent the image and footer to overflow out; show the full image still and keeping the ratio. And being quite honest I do not know if choosing a grid set would help me more, since the example I showed, grid is used.

* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

.row {
  display: flex;
  align-items: center;
  justify-content: space-evenly;
}

.column {
  display: flex;
  flex-direction: column;
  align-items: center;
  align-content: center;
  justify-content: center;
}

.main {
  padding: 1rem;
}

.description {
  opacity: 0;
  padding: 0.3rem;
  padding-top: 0.2rem;
  visibility: hidden;
  overflow: auto;
  font-size: 0.5rem;
  transition: 0.3s ease-in-out;
}

img {
  width: 100%;
}

.zoom {
  transition: all 1s ease-in-out;
  background-color: white;
  width: 60%;
}

.zoom:hover {
  transform: scale(1.5);
  box-shadow: 0.2rem 0.2rem 0.5rem rgba(0, 0, 0, 0.5);
  z-index: 68;
}

.zoom:hover .description {
  visibility: visible;
  animation-name: descriptionName;
  animation-duration: 1.6s;
  animation-fill-mode: forwards;
}

@keyframes descriptionName {
  0% {
    opacity: 0;
  }

  100% {
    opacity: 1;
  }
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>

  <link rel="stylesheet" href="style.css">
</head>

<body>
  <div class="main">
    <div class="row">
      <div class="column">
        <div class="zoom">
          <img src=".jpg">
          <div class="description">
            <p>This is a label - year</p>
          </div>
        </div>
      </div>
      <div class="column">
        <div class="zoom">
          <img src=".jpg">
          <div class="description">
            <p>This is a label - year</p>
          </div>
        </div>
      </div>
    </div>
    <div class="row">
      <div class="column">
        <div class="zoom">
          <img src=".jpg">
          <div class="description">
            <p>This is a label - year</p>
          </div>
        </div>
      </div>
    </div>
  </div>
</body>

</html>

Currently I'm helping someone with a page and they needed to display some images of their work. At first I set up a little structure for the display of images to fall under a flex structure.

Now, what I'm trying to do is a transition of an image that when hovered it increases in scale and shows a little footer about the image. But when doing so I find the problem that the scale takes the center position of where the image is.

Thus, the images overflow to the top/bottom/you name it, something that I do not want. So, I was thinking of maybe just moving it to the center, but doing so would cut the transition leaving a glitchy effect onscreen since it is leaving behind the cursor.

Consequently, the last option I thought about is maybe forcing the scale up to adapt and move considering the padding of the parent div (ideally the main div, not body since there is a little nav on the top).

I have tried to think of ways of trying to implement this but I have no clue where to even start. I have seen methods of scaling child to a parent div like this, but that was not what I had in mind.

I just want to prevent the image and footer to overflow out; show the full image still and keeping the ratio. And being quite honest I do not know if choosing a grid set would help me more, since the example I showed, grid is used.

* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

.row {
  display: flex;
  align-items: center;
  justify-content: space-evenly;
}

.column {
  display: flex;
  flex-direction: column;
  align-items: center;
  align-content: center;
  justify-content: center;
}

.main {
  padding: 1rem;
}

.description {
  opacity: 0;
  padding: 0.3rem;
  padding-top: 0.2rem;
  visibility: hidden;
  overflow: auto;
  font-size: 0.5rem;
  transition: 0.3s ease-in-out;
}

img {
  width: 100%;
}

.zoom {
  transition: all 1s ease-in-out;
  background-color: white;
  width: 60%;
}

.zoom:hover {
  transform: scale(1.5);
  box-shadow: 0.2rem 0.2rem 0.5rem rgba(0, 0, 0, 0.5);
  z-index: 68;
}

.zoom:hover .description {
  visibility: visible;
  animation-name: descriptionName;
  animation-duration: 1.6s;
  animation-fill-mode: forwards;
}

@keyframes descriptionName {
  0% {
    opacity: 0;
  }

  100% {
    opacity: 1;
  }
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>

  <link rel="stylesheet" href="style.css">
</head>

<body>
  <div class="main">
    <div class="row">
      <div class="column">
        <div class="zoom">
          <img src="https://greenwings.co/wp-content/uploads/2018/09/blank-head-profile-pic-for-a-man.jpg">
          <div class="description">
            <p>This is a label - year</p>
          </div>
        </div>
      </div>
      <div class="column">
        <div class="zoom">
          <img src="https://greenwings.co/wp-content/uploads/2018/09/blank-head-profile-pic-for-a-man.jpg">
          <div class="description">
            <p>This is a label - year</p>
          </div>
        </div>
      </div>
    </div>
    <div class="row">
      <div class="column">
        <div class="zoom">
          <img src="https://greenwings.co/wp-content/uploads/2018/09/blank-head-profile-pic-for-a-man.jpg">
          <div class="description">
            <p>This is a label - year</p>
          </div>
        </div>
      </div>
    </div>
  </div>
</body>

</html>

Share edited Mar 11 at 7:14 DarkBee 15.5k8 gold badges72 silver badges118 bronze badges asked Mar 11 at 7:01 Th3W31rd0Th3W31rd0 1138 bronze badges 1
  • Does using transform-origin: top; resolve your issue? – yuanyxh Commented Mar 11 at 7:20
Add a comment  | 

3 Answers 3

Reset to default 1

You can set transform origin to fit the position you want to image to grow to (see the zoom-* classes):

* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

.row {
  display: flex;
  align-items: center;
  justify-content: space-evenly;
}

.column {
  display: flex;
  flex-direction: column;
  align-items: center;
  align-content: center;
  justify-content: center;
}

.main {
  padding: 1rem;
}

.description {
  opacity: 0;
  padding: 0.3rem;
  padding-top: 0.2rem;
  visibility: hidden;
  overflow: auto;
  font-size: 0.5rem;
  transition: 0.3s ease-in-out;
}

img {
  width: 100%;
}

.zoom {
  transition: all 1s ease-in-out;
  background-color: white;
  width: 60%;
}

.zoom-tl {
  transform-origin: top left;
}

.zoom-tr {
  transform-origin: top right;
}

.zoom-bc {
  transform-origin: bottom center;
}

.zoom:hover {
  transform: scale(1.5);
  box-shadow: 0.2rem 0.2rem 0.5rem rgba(0, 0, 0, 0.5);
  z-index: 68;
}

.zoom:hover .description {
  visibility: visible;
  animation-name: descriptionName;
  animation-duration: 1.6s;
  animation-fill-mode: forwards;
}

@keyframes descriptionName {
  0% {
    opacity: 0;
  }

  100% {
    opacity: 1;
  }
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>

  <link rel="stylesheet" href="style.css">
</head>

<body>
  <div class="main">
    <div class="row">
      <div class="column">
        <div class="zoom zoom-tl">
          <img src="https://greenwings.co/wp-content/uploads/2018/09/blank-head-profile-pic-for-a-man.jpg">
          <div class="description">
            <p>This is a label - year</p>
          </div>
        </div>
      </div>
      <div class="column">
        <div class="zoom zoom-tr">
          <img src="https://greenwings.co/wp-content/uploads/2018/09/blank-head-profile-pic-for-a-man.jpg">
          <div class="description">
            <p>This is a label - year</p>
          </div>
        </div>
      </div>
    </div>
    <div class="row">
      <div class="column">
        <div class="zoom zoom-bc">
          <img src="https://greenwings.co/wp-content/uploads/2018/09/blank-head-profile-pic-for-a-man.jpg">
          <div class="description">
            <p>This is a label - year</p>
          </div>
        </div>
      </div>
    </div>
  </div>
</body>

</html>

You can change the point from which transforms (such as scale) operate. By default they operate from the centre, but you can use transform-origin to specify a different position.

transform-origin: center bottom;

Run this snippet, hover over the images and observe the difference.

body {
  margin: 4em 3em;
  display: flex;
  gap: 3em;
  background: aliceblue;
}

img {
  width: 5em;
  transition: 200ms;
  box-shadow: 0 0 10px rgb(0 0 0 / 0.2);
}

img:hover {
  transform: scale(1.5);
}

.scale-from-bottom {
  transform-origin: center bottom;
}
<img src="https://picsum.photos/160">
<img src="https://picsum.photos/160" class="scale-from-bottom">

I've updated the code a bit code, the issues are fixed by using a few simple CSS tricks. Each image is wrapped in a .zoom container that has overflow: hidden;, so any part of the image that gets bigger doesn't stick out. The image scales up with a nice transition that makes it look smooth, and you can change where the scaling starts with transform-origin. For the text description to show up on hover, CSS changes its opacity and visibility, so the text only appears when you want it to, without messing up the layout. This keeps everything looking neat and in place. Try it out and let me know.

* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

.row {
  display: flex;
  align-items: center;
  justify-content: space-evenly;
}

.column {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.main {
  padding: 1rem;
}

.zoom {
  width: 60%;
  transition: all 0.3s ease-in-out; /* ADDED THIS!  */
  position: relative;
  overflow: hidden; /* ADDED THIS!  */
  background-color: white;
}

.zoom:hover img {
  transform: scale(1.2); /* ADDED THIS! */
  transform-origin: center center; /* ADDED THIS!  */
}

.img-container img {
  display: block;
  width: 100%;
}

.zoom .description {
  opacity: 0;
  visibility: hidden;
  position: absolute;
  bottom: 0;
  width: 100%;
  background-color: rgba(0, 0, 0, 0.7);
  color: white;
  text-align: center;
  transition: opacity 0.3s ease-in-out;
}

.zoom:hover .description {
  opacity: 1;
  visibility: visible;
}
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Hover Effect</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <div class="main">
    <div class="row">
      <div class="column">
        <div class="zoom">
          <img src="https://greenwings.co/wp-content/uploads/2018/09/blank-head-profile-pic-for-a-man.jpg">
          <div class="description">
            <p>This is a label - year</p>
          </div>
        </div>
      </div>
      <div class="column">
        <div class="zoom">
          <img src="https://greenwings.co/wp-content/uploads/2018/09/blank-head-profile-pic-for-a-man.jpg">
          <div class="description">
            <p>This is a label - year</p>
          </div>
        </div>
      </div>
    </div>
  </div>
</body>
</html>
发布评论

评论列表(0)

  1. 暂无评论