Comment empêcher l'animation d'images clés CSS de s'exécuter lors du chargement de la page?

J'ai un div dans lequel j'anime le contenu:

#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>

Sur hover contenu glisse dans le conteneur div. Mon problème est, quand j'actualise la page, et la page charge l'animation animDown de #content s'exécutera, et je préférerais qu'elle ne s'exécute qu'après un événement de survol.

Existe-t-il un moyen de faire ce CSS pur, ou je dois comprendre quelque chose dans JS?

Http://jsfiddle.net/d0yhve8y/

28
demandé sur T J 2015-01-14 11:51:15

4 réponses

Solution 1-Ajouter une animation sur le premier survol

La meilleure option est probablement de ne pas mettre l'animation jusqu'à ce que l'utilisateur ait survolé le container pour la première fois.

Cela implique d'écouter l'événement mouseover, puis d'ajouter une classe avec l'animation à ce stade, et de supprimer l'écouteur d'événement. Le principal inconvénient (potentiel) de ceci est qu'il repose sur 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>

Solution 2 - jouer animation cachée

Une autre façon de contourner ce problème est de masquer initialement l'élément, de s'assurer que l'animation joue pendant qu'elle est cachée, puis de la rendre visible. L'inconvénient de ceci est que le timing pourrait être légèrement désactivé et il est rendu visible trop tôt, et aussi le vol stationnaire n'est pas disponible tout de suite.

Cela nécessite du Javascript qui attend la longueur de l'animation et ne fait que rendre #content visible. Cela signifie que vous devez également définir le opacity initial à 0 ainsi il n'apparaît pas en charge et supprime également le visibility des images clés - celles-ci ne font rien de toute façon:

// 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>

Solution 3 - Utiliser les transitions

Dans votre scénario, vous pouvez faire ce CSS uniquement en remplaçant les keyframe s par un transition à la place, donc il commence par opacity:0 et juste le hover a un changement dans opacity et le 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>
13
répondu Rhumborl 2015-01-14 09:52:33

J'ai toujours mis la classe preload sur body avec la valeur de temps d'animation 0 et cela fonctionne assez bien. J'ai quelques transitions de retour, donc je dois aussi supprimer l'animation de charge. J'ai résolu cela en définissant temporairement le temps d'animation sur 0. Vous pouvez modifier les transitions pour correspondre à la vôtre.

HTML

... <body class="preload">...

CSS définit l'animation sur 0s

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 supprimera la classe après un certain délai afin que les animations puissent se produire en temps normal:)

setTimeout(function(){
    document.body.className="";
},500);
41
répondu Tominator 2016-07-10 21:29:03

Animation de Rotation qui (apparaît) ne pas exécuter jusqu'à ce que nécessaire.
Le CSS ci-dessous permet des flèches haut et bas pour afficher les éléments de menu. L'animation ne semble pas fonctionner au chargement de la page, mais c'est vraiment le cas.

@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;
}

De haut en bas:

  1. crée les rotations. Pour cela, il existe deux... un pour la flèche vers le bas et l'autre pour la flèche vers le haut. Deux flèches sont nécessaires, car, après la rotation, elles reviennent à leur état naturel. Ainsi, la flèche vers le bas démarre et tourne vers le bas, tandis que la flèche descend et tourne.
  2. créez les petites flèches. C'est une implémentation simple de:: before
  3. nous mettons l'animation sur l'étiquette. Il n'y a rien de spécial, là, sauf que la durée de l'animation est de 1ms.
  4. la souris pilote la vitesse d'animation . Lorsque la souris survole l'élément, la durée de l'animation est définie sur suffisamment de temps pour sembler lisse.

Travailler sur mon site

0
répondu user1126454 2018-04-25 23:11:20

Existe-t-il un moyen de faire ce CSS pur ?

Oui, absolument : Voir la fourche http://jsfiddle.net/5r32Lsme/2/ Il n'y a vraiment pas besoin de JS.

Et je préférerais qu'il ne s'exécute qu'après un événement de survol.

Vous devez donc dire à CSS ce qui se passe quand ce n'est pas un événement de survol-dans votre exemple:

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

, Mais il y a deux choses à noter:

1) le délai de transition ci-dessus doit correspondre à votre animation durée

2) vous ne pouvez pas utiliser la propriété que vous utilisez pour masquer l'animation onLoad dans l'animation. Si vous avez besoin de Visibilité dans l'animation, masquez l'animation initialement comme par exemple

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

A sidenote:

Il est recommandé de mettre les propriétés CSS natives après les préfixes, donc il devrait être

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

Et maintenant, il est un natif transformer

-webkit-transform: translateY(0);
transform: translateY(0);
0
répondu sebilasse 2018-06-04 11:06:37