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
3 Answers
Reset to default 1You 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>