web-dev-qa-db-ja.com

ページの読み込み時にCSSキーフレームアニメーションが実行されるのを防ぐ方法は?

コンテンツをアニメーション化する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で何かを理解する必要がありますか?

http://jsfiddle.net/d0yhve8y/

39
Eduárdó

解決策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-非表示のアニメーションを再生

これを回避する別の方法は、最初に要素を非表示にし、非表示のときにアニメーションが再生されることを確認してから、表示することです。これの欠点は、タイミングがわずかにずれている可能性があり、あまりにも早く見えるようになり、またホバーがすぐに利用できないことです。

これには、アニメーションの長さを待機してから#contentを表示するJavascriptが必要です。つまり、初期opacity0に設定して、ロード時に表示されず、キーフレームからvisibilityも削除する必要があることを意味します-これらは何もしません:

// 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-トランジションを使用

あなたのシナリオでは、代わりにkeyframesをtransitionに置き換えることによってのみこのCSSを作成できます。したがって、opacity:0で始まり、ホバーだけが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%);
}
<div id="container">
    <div id="content"></div>
</div>
17
Rhumborl

私は常にプリロードクラスをアニメーション時間値0のbodyに設定し、それはかなりうまく機能しています。バックトランジションがいくつかあるので、それらへのロードアニメーションも削除する必要があります。アニメーション時間を一時的に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);
58
Tominator

この純粋なCSSを行う方法はありますか?

はい、絶対に:フォークを参照してください http://jsfiddle.net/5r32Lsme/2/ JSは本当に必要ありません。

ホバーイベント後にのみ実行することを希望します。

そのため、CSSがホバーイベントではない場合に何が起こるかをCSSに伝える必要があります-あなたの例では:

#container:not(:hover) #content {
  visibility: hidden;
  transition: visibility 0.01s 1s;
}    

ただし、注意すべき点が2つあります。

1)上記の遷移遅延は、アニメーションの継続時間と一致する必要があります

2)アニメーションのonLoadアニメーションを非表示にするために使用するプロパティは使用できません。アニメーションでvisibilityが必要な場合は、最初のようにアニメーションを非表示にします。

#container:not(:hover) #content {
  top: -8000px;
  transition: top 0.01s 1s;
}    

補足:

ネイティブのCSSプロパティをプレフィックスの後に配置することをお勧めします。

-webkit-animation-fill-mode: forwards;
animation-fill-mode: forwards;

そして今、ネイティブtransformがあります

-webkit-transform: translateY(0);
transform: translateY(0);
3
sebilasse

これは純粋なCSSではありませんが、おそらく私がしたように誰かがこのスレッドを偶然見つけるでしょう:

In React ComponentDidMount()で一時クラスを次のように設定することでこれを解決しました。

componentDidMount = () => {
    document.getElementById("myContainer").className =
        "myContainer pageload";
};

そして、CSSで:

.myContainer.pageload {
    animation: none;
}

.myContainer.pageload * {
    animation: none;
}

よくわからない場合は、上記の「*」(n.b。スペース)は、要素のすべての子孫にも適用されることを意味します。スペースはすべての子孫を意味し、アスタリスクはすべてのタイプの要素を参照するワイルドカード演算子です。

1
ClownBaby

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>
0
Guilherme P.

必要になるまで実行されない(表示される)回転アニメーション
以下の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;
}

上から下まで:

  1. 回転を作成します。これには2つあります... 1つは下矢印用、もう1つは上矢印用です。 2つの矢印が必要なのは、回転後に元の状態に戻るためです。したがって、下矢印は開始して下に回転し、上矢印は下から開始して上に回転します。
  2. 小さな矢印を作成します。これは:: beforeの単純な実装です
  3. アニメーションをラベルに配置します。アニメーションの継続時間が1ミリ秒であることを除いて、特別なものはありません。
  4. マウスはアニメーション速度を駆動します。マウスを要素の上に置くと、アニメーションの持続時間は滑らかに見えるように十分な時間に設定されます。

私のサイトで作業中

0
user1126454