英文:
How can I make a child element grow and shrink with animation on hover using CSS?
问题
我有一个问题,当我悬停在.wrapper__shopcart元素上时,它的子元素.wrapper__shopcart-modal会以动画方式显示:
@keyframes Growth {
from {
transform: scale(0);
opacity: 0;
}
to {
transform: scale(1);
opacity: 1;
}
}
当悬停结束时,我希望它以动画方式消失:
@keyframes Shrink {
from {
transform: scale(1);
opacity: 1;
}
to {
transform: scale(0);
opacity: 0;
}
}
但是我不知道该如何实现。我希望有一个高效的CSS方法来解决这个问题。
英文:
i have a problem, when i hover on .wrapper__shopcart element its child element .wrapper__shopcart-modal will show up with animation:
@keyframes Growth{
from{
transform: scale(0);
opacity: 0;
}
to {
transform: scale(1);
opacity: 1;
}
}
and when the hover is over i want it to disappear with the animation:
@keyframes Shrink{
from {
transform: scale(1);
opacity: 1;
}
to {
transform: scale(0);
opacity: 0;
}
}
but I don't know how.
I wish an efficient css method for this problem
答案1
得分: 1
如果您希望在鼠标悬停时发生这种效果,您需要使用transition
而不是关键帧动画。请参考下面的示例。
另外请注意,当它缩小到scale(0)
时,您实际上不能再“悬停”在任何地方,所以如果您移动鼠标,动画可能看起来会很奇怪。
示例 #1
#container {
display: flex;
}
.grow-shrink {
background: #EEE;
border: 1px solid lightblue;
padding: 10px 15px;
opacity: 1;
transform: scale(1);
/* 告诉此元素在某些属性更改时要动画化哪些属性
我们说当任何属性更改时都会动画化,持续时间为0.3秒 */
transition: all 0.3s;
}
.grow-shrink:hover {
transform: scale(0);
opacity: 0;
}
<div id="container">
<div class="grow-shrink">one</div>
<div class="grow-shrink">two</div>
<div class="grow-shrink">three</div>
<div class="grow-shrink">four</div>
<div class="grow-shrink">five</div>
</div>
这里有一种避免这种颤抖动画的方法。每个元素都有一个包装元素。我们悬停在包装元素上,然后只缩小内部元素。
示例 #2
#container {
display: flex;
}
.grow-shrink-wrapper .grow-shrink {
background: #EEE;
border: 1px solid lightblue;
padding: 10px 15px;
opacity: 1;
transform: scale(1);
/* 告诉此元素在某些属性更改时要动画化哪些属性
我们说当任何属性更改时都会动画化,持续时间为0.3秒 */
transition: all 0.3s;
}
.grow-shrink-wrapper:hover .grow-shrink {
transform: scale(0);
opacity: 0;
}
<div id="container">
<div class="grow-shrink-wrapper">
<div class="grow-shrink">one</div>
</div>
<div class="grow-shrink-wrapper">
<div class="grow-shrink">two</div>
</div>
<div class="grow-shrink-wrapper">
<div class="grow-shrink">three</div>
</div>
<div class="grow-shrink-wrapper">
<div class="grow-shrink">four</div>
</div>
<div class="grow-shrink-wrapper">
<div class="grow-shrink">five</div>
</div>
</div>
这是一个第三个示例,根据下面的注释切换了起始和结束状态。
示例 #3
#container {
display: flex;
border: 1px solid red;
}
.grow-shrink-wrapper .grow-shrink {
background: #EEE;
border: 1px solid lightblue;
padding: 10px 15px;
opacity: 0;
transform: scale(0);
/* 告诉此元素在某些属性更改时要动画化哪些属性
我们说当任何属性更改时都会动画化,持续时间为0.3秒 */
transition: all 0.3s;
}
.grow-shrink-wrapper:hover .grow-shrink {
transform: scale(1);
opacity: 1;
}
<div id="container">
<div class="grow-shrink-wrapper">
<div class="grow-shrink">one</div>
</div>
<div class="grow-shrink-wrapper">
<div class="grow-shrink">two</div>
</div>
<div class="grow-shrink-wrapper">
<div class="grow-shrink">three</div>
</div>
<div class="grow-shrink-wrapper">
<div class="grow-shrink">four</div>
</div>
<div class="grow-shrink-wrapper">
<div class="grow-shrink">five</div>
</div>
</div>
英文:
If you want this to happen on hover you need to use a transition
, not a keyframe animation. See the below example.
Also keep in mind that when it shrinks down to scale(0)
that you really cannot "hover" over nothing any more so that animations might look odd if you move your mouse around.
Example #1
<!-- begin snippet: js hide: true console: true babel: false -->
<!-- language: lang-css -->
#container {
display: flex;
}
.grow-shrink {
background: #EEE;
border: 1px solid lightblue;
padding: 10px 15px;
opacity: 1;
transform: scale(1);
/*Tell this element which properties to animate if something changes
We are saying all properties will animate when changed for 0.3 seconds*/
transition: all 0.3s;
}
.grow-shrink:hover {
transform: scale(0);
opacity: 0;
}
<!-- language: lang-html -->
<div id="container">
<div class="grow-shrink">one</div>
<div class="grow-shrink">two</div>
<div class="grow-shrink">three</div>
<div class="grow-shrink">four</div>
<div class="grow-shrink">five</div>
</div>
<!-- end snippet -->
Here's a way around that jerky animation though. Each element has a wrapping element. We hover over that one and only scale down the inner one.
Example #2
<!-- begin snippet: js hide: true console: true babel: false -->
<!-- language: lang-css -->
#container {
display: flex;
}
.grow-shrink-wrapper .grow-shrink {
background: #EEE;
border: 1px solid lightblue;
padding: 10px 15px;
opacity: 1;
transform: scale(1);
/*Tell this element which properties to animate if something changes
We are saying all properties will animate when changed for 0.3 seconds*/
transition: all 0.3s;
}
.grow-shrink-wrapper:hover .grow-shrink {
transform: scale(0);
opacity: 0;
}
<!-- language: lang-html -->
<div id="container">
<div class="grow-shrink-wrapper">
<div class="grow-shrink">one</div>
</div>
<div class="grow-shrink-wrapper">
<div class="grow-shrink">two</div>
</div>
<div class="grow-shrink-wrapper">
<div class="grow-shrink">three</div>
</div>
<div class="grow-shrink-wrapper">
<div class="grow-shrink">four</div>
</div>
<div class="grow-shrink-wrapper">
<div class="grow-shrink">five</div>
</div>
</div>
<!-- end snippet -->
Example #3
And here's a 3rd example that switches the starting and ending states based on comments below.
<!-- begin snippet: js hide: true console: true babel: false -->
<!-- language: lang-css -->
#container {
display: flex;
border: 1px solid red;
}
.grow-shrink-wrapper .grow-shrink {
background: #EEE;
border: 1px solid lightblue;
padding: 10px 15px;
opacity: 0;
transform: scale(0);
/*Tell this element which properties to animate if something changes
We are saying all properties will animate when changed for 0.3 seconds*/
transition: all 0.3s;
}
.grow-shrink-wrapper:hover .grow-shrink {
transform: scale(1);
opacity: 1;
}
<!-- language: lang-html -->
<div id="container">
<div class="grow-shrink-wrapper">
<div class="grow-shrink">one</div>
</div>
<div class="grow-shrink-wrapper">
<div class="grow-shrink">two</div>
</div>
<div class="grow-shrink-wrapper">
<div class="grow-shrink">three</div>
</div>
<div class="grow-shrink-wrapper">
<div class="grow-shrink">four</div>
</div>
<div class="grow-shrink-wrapper">
<div class="grow-shrink">five</div>
</div>
</div>
<!-- end snippet -->
答案2
得分: 0
@keyframes
是一组明确的指令,在页面加载后执行,animation
属性规定了特定的时序和频率。因此,你需要一小段JavaScript代码来阻止默认状态动画在页面加载时运行(即缩小部分)(参见示例A)。
transitions
只规定了时序,因此不会在页面加载时执行任何动画。它是由与其绑定的样式实际更改来触发的,因此不需要JavaScript(参见示例B)。
英文:
@keyframes
are explicit set of instructions which will be executed once the page loads, and the animation
properties dictates specific timing and frequency. So you'll need a small amount of JavaScript to prevent the default state animation from running on page-load (the shrinking part) (see Example A).
transitions
just dictates timing so it doesn't start executing any animation on page-load. It's triggered by an actual change of the style(s) it's bound to so JavaScript isn't needed (see Example B).
Example A
<!-- begin snippet: js hide: true console: true babel: false -->
<!-- language: lang-js -->
setTimeout(() => document.querySelector(".modal").style.visibility = "visible", 1200);
<!-- language: lang-css -->
@keyframes shrink {
from {
transform: scale(1.0);
opacity: 1.0;
}
to {
transform: scale(0.0);
opacity: 0.0;
}
}
@keyframes grow {
from {
transform: scale(0.0);
opacity: 0.0;
}
to {
transform: scale(1.0);
opacity: 1.0;
}
}
:root {
font: 2ch/1.15 "Segoe UI";
}
.box {
list-style: none;
position: relative /* Make it's borders to which absolute elements
will reference their positions from */;
width: 50vw;
margin: 20px auto;
padding: 10vw;
background: #fff;
cursor: pointer;
}
.icon {
position: absolute /* Position itself to the top left corner of .box */;
top: 0;
left: 0;
width: 35vw;
background: #fff;
}
.icon figcaption {
font-weight: 900;
font-size: 1.15rem;
font-variant: small-caps;
letter-spacing: 1.5px;
text-align: center;
}
.icon img {
object-fit: contain;
object-position: center;
width: 100%;
}
.modal {
position: absolute /* Position itself to the top left corner of .box */;
top: 0;
left: 0;
z-index: 1 /* Position itself "over" .icon */;
width: 60vw;
padding: 8px;
border-radius: 8px;
background: lightblue;
transform-origin: center /* It will start and end it's animation witin
it's "center" */;
animation: shrink 0.7s ease-in-out /* [name of keyframes]
[duration] [timing function] */;
box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;
visibility: hidden /* Needs to be invisible at page-load so that
the shrink animation isn't initially seen. */;
opacity: 0.0 /* Stay invisible until either .box is hovered over */;
pointer-events: none /* Any clicking or hovering will be ignored */;
}
.box:hover .modal {
animation: grow 0.7s ease-in-out forwards /* [name of keyframes]
[duration] [timing function] [fill mode]
Hovering over .box will trigger .modal to grow.
If .box is no longer hovered over, .modal will
revert back to default (shrink to nothing) */;
}
.modal thead th:first-of-type,
.modal td,
.modal tfoot th {
padding: 2.5px 5px;
text-align: left;
}
.modal tbody td:nth-child(n+2) {
text-align: center;
}
.modal tr td:last-of-type {
text-align: right;
}
.modal tfoot tr:last-of-type td {
font-weight: 900;
}
.modal tbody tr:last-of-type td {
padding-bottom: 6px;
border-bottom: 1px solid black;
}
<!-- language: lang-html -->
<!--
.box contains .icon and .modal which both position themselves in
relation to the borders of .box.
-->
<menu class="box">
<!--
.icon is always visible so it can serve as a visual cue to the user.
-->
<figure class="icon">
<figcaption>Shopping Cart</figcaption>
<img src="https://i.ibb.co/NF2RWXB/cart.png">
</figure>
<!--
By default .modal is microscopic. Once .box is hovered over .modal
grow to full size. It will maintain full size until .box is no longer hovered over.
-->
<table class="modal">
<thead>
<tr>
<th>Item</th>
<th>Each</th>
<th>Qty</th>
<th>Price</th>
</tr>
</thead>
<tbody>
<tr>
<td>Sweater</td>
<td>32.99</td>
<td>2</td>
<td>65.98</td>
</tr>
<tr>
<td>Shoes</td>
<td>89.99</td>
<td>1</td>
<td>89.99</td>
</tr>
<tr>
<td>T-shirt</td>
<td>12.99</td>
<td>5</td>
<td>64.95</td>
</tr>
</tbody>
<tfoot>
<tr>
<th colspan="3">Sub-total</th>
<td>240.25</td>
<tr>
<th colspan="3">Tax 8.75%</th>
<td>19.33</td>
</tr>
<tr>
<th colspan="3">Grand Total</th>
<td>259.58</td>
</tr>
</tfoot>
</table>
</menu>
<!-- end snippet -->
Example B
<!-- begin snippet: js hide: true console: true babel: false -->
<!-- language: lang-css -->
:root {
font: 2ch/1.15 "Segoe UI";
}
.box {
list-style: none;
position: relative /* Make it's borders to which absolute elements
will reference their positions from */;
width: 50vw;
margin: 20px auto;
padding: 10vw;
background: #fff;
cursor: pointer;
}
.icon {
position: absolute /* Position itself to the top left corner of .box */;
top: 0;
left: 0;
width: 35vw;
background: #fff;
}
.icon figcaption {
font-weight: 900;
font-size: 1.15rem;
font-variant: small-caps;
letter-spacing: 1.5px;
text-align: center;
}
.icon img {
object-fit: contain;
object-position: center;
width: 100%;
}
.modal {
position: absolute /* Position itself to the top left corner of .box */;
top: 0;
left: 0;
z-index: 1 /* Position itself "over" .icon */;
width: 60vw;
padding: 8px;
border-radius: 8px;
background: lightblue;
transform: scale(0.0) /* It is microscopic by default */;
transform-origin: center /* It will start and end it's animation witin
it's "center" */;
transition: transform 0.7s ease-in-out /* [name of property]
[duration] [timing function] */;
box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;
}
.box:hover .modal,
.modal:hover {
transform: scale(1.0) /* Hovering over .box or .modal will trigger
.modal to grow. If neither of them are hovered over, .modal will
revert back to default (shrink to nothing) */;
}
.modal thead th:first-of-type,
.modal td,
.modal tfoot th {
padding: 2.5px 5px;
text-align: left;
}
.modal tbody td:nth-child(n+2) {
text-align: center;
}
.modal tr td:last-of-type {
text-align: right;
}
.modal tfoot tr:last-of-type td {
font-weight: 900;
}
.modal tbody tr:last-of-type td {
padding-bottom: 6px;
border-bottom: 1px solid black;
}
<!-- language: lang-html -->
<!--
.box contains .icon and .modal which both position themselves in
relation to the borders of .box.
-->
<menu class="box">
<!--
.icon is always visible so it can serve as a visual cue to the user.
-->
<figure class="icon">
<figcaption>Shopping Cart</figcaption>
<img src="https://i.ibb.co/NF2RWXB/cart.png">
</figure>
<!--
By default .modal is microscopic. Once .box is hovered over .modal
grow to full size. It will maintain full size until neither .box or .modal
is hovered over.
-->
<table class="modal">
<thead>
<tr>
<th>Item</th>
<th>Each</th>
<th>Qty</th>
<th>Price</th>
</tr>
</thead>
<tbody>
<tr>
<td>Sweater</td>
<td>32.99</td>
<td>2</td>
<td>65.98</td>
</tr>
<tr>
<td>Shoes</td>
<td>89.99</td>
<td>1</td>
<td>89.99</td>
</tr>
<tr>
<td>T-shirt</td>
<td>12.99</td>
<td>5</td>
<td>64.95</td>
</tr>
</tbody>
<tfoot>
<tr>
<th colspan="3">Sub-total</th>
<td>240.25</td>
<tr>
<th colspan="3">Tax 8.75%</th>
<td>19.33</td>
</tr>
<tr>
<th colspan="3">Grand Total</th>
<td>259.58</td>
</tr>
</tfoot>
</table>
</menu>
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论