我有一个div,我在其中制作动画内容:
#container {
position: relative;
width: 100px;
height: 100px;
border-style: inset;
}
#content {
visibility: hidden;
-webkit-animation: animDown 1s ease;
position: absolute;
top: 100px;
width: 100%;
height: 100%;
background-color: lightgreen;
}
#container:hover #content {
-webkit-animation: animUp 1s ease;
animation-fill-mode: forwards;
-webkit-animation-fill-mode: forwards;
}
@-webkit-keyframes animUp {
0% {
-webkit-transform: translateY(0);
visibility: hidden;
opacity: 0;
}
100% {
-webkit-transform: translateY(-100%);
visibility: visible;
opacity: 1;
}
}
@-webkit-keyframes animDown {
0% {
-webkit-transform: translateY(-100%);
visibility: visible;
opacity: 1;
}
100% {
-webkit-transform: translateY(0);
visibility: hidden;
opacity: 0;
}
}
<div id="container">
<div id="content"></div>
</div>
将悬停内容幻灯片放入容器div中。
我的问题是,当我刷新页面时,页面加载#content
的animDown动画将会运行,我宁愿它只在悬停事件后运行。
有没有办法做这个纯CSS,或者我必须在JS中找出一些东西?
答案 0 :(得分:52)
我总是将preload类设置为body,动画时间值为0,并且工作得很好。我有一些后退过渡,所以我也必须删除加载动画。我通过将动画时间临时设置为0来解决此问题。您可以更改过渡以匹配您的过渡。
HTML
... <body class="preload">...
CSS将动画设置为0
body.preload *{
animation-duration: 0s !important;
-webkit-animation-duration: 0s !important;
transition:background-color 0s, opacity 0s, color 0s, width 0s, height 0s, padding 0s, margin 0s !important;}
JS会在一段时间后删除类,因此动画可以在正常时间内发生:)
setTimeout(function(){
document.body.className="";
},500);
答案 1 :(得分:17)
解决方案1 - 首次悬停时添加动画
可能最好的选择是在用户第一次悬停在container
上之前不要关闭动画。
这涉及监听mouseover
事件,然后在该点添加带动画的类,并删除事件监听器。这主要(潜在)的缺点是它依赖于Javascript。
;(function(){
var c = document.getElementById('container');
function addAnim() {
c.classList.add('animated')
// remove the listener, no longer needed
c.removeEventListener('mouseover', addAnim);
};
// listen to mouseover for the container
c.addEventListener('mouseover', addAnim);
})();
#container {
position:relative;
width:100px;
height:100px;
border-style:inset;
}
#content {
position:absolute;
top:100px;
width:100%;
height:100%;
background-color:lightgreen;
opacity:0;
}
/* This gets added on first mouseover */
#container.animated #content {
-webkit-animation:animDown 1s ease;
}
#container:hover #content {
-webkit-animation:animUp 1s ease;
animation-fill-mode:forwards;
-webkit-animation-fill-mode:forwards;
}
@-webkit-keyframes animUp {
0% {
-webkit-transform:translateY(0);
opacity:0;
}
100% {
-webkit-transform:translateY(-100%);
opacity:1;
}
}
@-webkit-keyframes animDown {
0% {
-webkit-transform:translateY(-100%);
opacity:1;
}
100% {
-webkit-transform:translateY(0);
opacity:0;
}
}
<div id="container">
<div id="content"></div>
</div>
解决方案2 - 隐藏动画
另一种方法是首先隐藏元素,确保动画在隐藏时播放,然后使其可见。这样做的缺点是时间可能会稍微偏离,并且过早显示,而且悬停也不会立即显示。
这需要一些等待动画长度的Javascript,然后才能使#content
可见。这意味着您还需要将初始opacity
设置为0
,以便它不会在加载时显示,也会从关键帧中删除visibility
- 这些都没有做任何事情:< / p>
// wait for the animation length, plus a bit, then make the element visible
window.setTimeout(function() {
document.getElementById('content').style.visibility = 'visible';
}, 1100);
#container {
position:relative;
width:100px;
height:100px;
border-style:inset;
}
#content {
visibility:hidden;
-webkit-animation:animDown 1s ease;
position:absolute;
top:100px;
width:100%;
height:100%;
background-color:lightgreen;
opacity:0;
}
#container:hover #content {
-webkit-animation:animUp 1s ease;
animation-fill-mode:forwards;
-webkit-animation-fill-mode:forwards;
}
@-webkit-keyframes animUp {
0% {
-webkit-transform:translateY(0);
opacity:0;
}
100% {
-webkit-transform:translateY(-100%);
opacity:1;
}
}
@-webkit-keyframes animDown {
0% {
-webkit-transform:translateY(-100%);
opacity:1;
}
100% {
-webkit-transform:translateY(0);
opacity:0;
}
}
<div id="container">
<div id="content"></div>
</div>
解决方案3 - 使用转场
在您的方案中,您只能通过将keyframe
替换为transition
来制作此CSS,因此它以opacity:0
开头,而且只有悬停在{{{ 1}}和opacity
:
transform
#container {
position:relative;
width:100px;
height:100px;
border-style:inset;
}
#content {
position:absolute;
top:100px;
width:100%;
height:100%;
background-color:lightgreen;
/* initial state - hidden */
opacity:0;
/* set properties to animate - applies to hover and revert */
transition:opacity 1s, transform 1s;
}
#container:hover #content {
/* Just set properties to change - no need to change visibility */
opacity:1;
-webkit-transform:translateY(-100%);
transform:translateY(-100%);
}
答案 2 :(得分:3)
有没有办法做这个纯CSS?
是的,绝对:看到前叉http://jsfiddle.net/5r32Lsme/2/ 真的没有必要使用JS。
我希望它只能在悬停事件之后运行。
所以你需要告诉CSS当它不是悬停事件时会发生什么 - 在你的例子中:
#container:not(:hover) #content {
visibility: hidden;
transition: visibility 0.01s 1s;
}
但有两点需要注意:
1)上面的转换延迟应与您的动画持续时间相匹配
2)您无法使用您在动画中隐藏动画onLoad的属性。 如果您确实需要动画中的可见性,请最初隐藏动画,例如
#container:not(:hover) #content {
top: -8000px;
transition: top 0.01s 1s;
}
旁注:
建议在前缀之后放置原生CSS属性,因此它应该是
-webkit-animation-fill-mode: forwards;
animation-fill-mode: forwards;
现在有一个原生转换
-webkit-transform: translateY(0);
transform: translateY(0);
答案 3 :(得分:1)
这不是纯CSS,但也许有人会像我一样偶然发现此线程:
在React中,我通过在ComponentDidMount()中设置一个临时类来解决了这个问题,
componentDidMount = () => {
document.getElementById("myContainer").className =
"myContainer pageload";
};
,然后在CSS中:
.myContainer.pageload {
animation: none;
}
.myContainer.pageload * {
animation: none;
}
如果您不熟悉上面的“ *”(即空格),则表示它也适用于该元素的所有后代。该空格表示所有后代,星号是通配符运算符,表示所有类型的元素。
答案 4 :(得分:0)
Rotation animation that (appears) not to run until needed.
下面的CSS允许显示菜单项的向上和向下箭头。
动画似乎不会在页面加载时运行,但确实如此。
@keyframes rotateDown {
from { transform: rotate(180deg); }
to { transform: rotate(0deg); }
}
@keyframes rotateUp {
from { transform: rotate(180deg); }
to { transform: rotate(0deg); }
}
div.menu input[type='checkbox'] + label.menu::before {
display :inline-block;
content : "▼";
color : #b78369;
opacity : 0.5;
font-size : 1.2em;
}
div.menu input[type='checkbox']:checked + label.menu::before {
display : inline-block;
content : "▲";
color : #b78369;
opacity : 0.5;
font-size : 1.2em;
}
div.menu input[type='checkbox'] + label.menu {
display : inline-block;
animation-name : rotateDown;
animation-duration : 1ms;
}
div.menu input[type='checkbox']:checked + label.menu {
display : inline-block;
animation-name : rotateUp;
animation-duration : 1ms;
}
div.menu input[type='checkbox'] + label.menu:hover {
animation-duration : 500ms;
}
div.menu input[type='checkbox']:checked + label.menu:hover {
animation-duration : 500ms;
}
从上到下:
答案 5 :(得分:0)
如果您要在2019年以后看这个,一个更好的解决方案是:
let div = document.querySelector('div')
document.addEventListener('DOMContentLoaded', () => {
// Adding timeout to simulate the loading of the page
setTimeout(() => {
div.classList.remove('prevent-animation')
}, 2000)
document.querySelector('button').addEventListener('click', () => {
if(div.classList.contains('after')) {
div.classList.remove('after')
} else {
div.classList.add('after')
}
})
})
div {
background-color: purple;
height: 150px;
width: 150px;
}
.animated-class {
animation: animationName 2000ms;
}
.animated-class.prevent-animation {
animation-duration: 0ms;
}
.animated-class.after {
animation: animation2 2000ms;
background-color: orange;
}
@keyframes animationName {
0% {
background-color: red;
}
50% {
background-color: blue;
}
100% {
background-color: purple;
}
}
@keyframes animation2 {
0% {
background-color: salmon;
}
50% {
background-color: green;
}
100% {
background-color: orange;
}
}
<div class="animated-class prevent-animation"></div>
<button id="btn">Toggle between animations</button>
答案 6 :(得分:-1)
以Tominator的答案为基础,在React中,您可以像这样将其应用于每个组件:
import React, { Component } from 'react'
export default class MyThing extends Component {
constructor(props) {
super(props);
this.state = {
preloadClassName: 'preload'
}
}
shouldComponentUpdate(nextProps, nextState) {
return nextState.preloadClassName !== this.state.preloadClassName;
}
componentDidUpdate() {
this.setState({ preloadClassName: null });
}
render() {
const { preloadClassName } = this.state;
return (
<div className={`animation-class ${preloadClassName}`}>
<p>Hello World!</p>
</div>
)
}
}
和CSS类:
.preload * {
-webkit-animation-duration: 0s !important;
animation-duration: 0s !important;
transition: background-color 0s, opacity 0s, color 0s, width 0s, height 0s, padding 0s, margin 0s !important;
}