web-dev-qa-db-fra.com

CSS Transition de display aucun à bloc d'affichage et vice versa

Je sais que cette question a probablement été posée des millions de fois ici à SO, mais j’ai essayé la plupart des solutions, je ne sais pas pourquoi cela ne fonctionne pas pour moi.

J'ai donc une liste déroulante avec display initialement ciblée sur none. Quand je clique dessus, ça montre une belle transition. (Jusqu'ici tout va bien). Mais lorsque je clique à nouveau dessus pour cacher le menu déroulant, il se cache immédiatement, mais je ne le veux pas. Je veux cacher avec une transition similaire qui a été assignée à montrer. Voici mon code pour CSS:

.dropdown-menu {
  padding: 0 0;
  display: none;
  -webkit-animation: slide-down .3s ease-out;
  -moz-animation: slide-down .3s ease-out;
}

.table-dropdown-open {
  display: block;
  -webkit-animation: slide-down .3s ease-out;
  -moz-animation: slide-down .3s ease-out;
}

@-webkit-keyframes slide-down {
  0% {
    opacity: 0;
    -webkit-transform: translateY(-10%);
  }
  100% {
    opacity: 1;
    -webkit-transform: translateY(0);
  }
}

@-moz-keyframes slide-down {
  0% {
    opacity: 0;
    -moz-transform: translateY(-10%);
  }
  100% {
    opacity: 1;
    -moz-transform: translateY(0);
  }
}

Ce n'est pas une duplication car je tente de passer de block à none. Pas de none à block

7
DingDong

display votre élément à tout moment et seulement transition toute propriété animatable. Dans votre cas, opacity ressemble à un bon candidat, bien que jouer avec transform puisse également vous donner le résultat souhaité. Exemple simple: 

any {
  transform: scale(0);
  transition: transform .4s cubic-bezier(.5,0,.3,1);
}
any.animated {
  transform: scale(1);
}

En effet, opacity et transform devraient être les deux seules propriétés que vous devriez animer, car elles ne nécessitent pas de repeindre DOM sur autre chose que l'élément animé, afin de ne pas affecter les performances du navigateur, même lorsque vous animez simultanément une quantité considérable d'éléments .

Veuillez noter que, même s'ils ne sont pas peints, vos éléments sont en réalité à l'endroit où ils se trouveraient lorsqu'ils ne seraient pas du tout transformed. Donc, vous voudrez peut-être leur donner pointer-events:none quand ils seront dans l'état "invisible" et pointer-events:all quand ils seront dans l'état "visible", de sorte qu'ils n'attraperont aucun événement de pointeur tant que invisible.


Compte tenu de votre exemple, je vous ai donné deux exemples d'animation (avec images clés et sans). N'oubliez pas que vous devez prefix your code . Pour une compatibilité totale du navigateur, utilisez > 0% dans les paramètres (la petite boîte en bas).

setTimeout(function(){
  var dm = document.querySelector('.dropdown-menu');
  dm.classList.remove('hide-menu');
}, 300);
/* simple animation example, on parent. No keyframes. */
.dropdown-menu.hide-menu {
  opacity: 0;
}
.dropdown-menu {
  opacity: 1;
  transition: opacity .2s cubic-bezier(.4,0,.2,1);
  position: relative;
  animation: delay-overflow .3s;
  animation-fill-mode: forwards;
  animation-iteration-count: 1;
}
.dropdown-menu:hover {
  animation: none;
  cursor: pointer;
}

/* animation example with keyframes, on child */

.dropdown-menu ul {
  position: absolute;
  margin-top: 0;
  padding-top: 1rem;
  top: 100%;
  opacity: 0;
  transform: translateY(-10%);
  animation: slide-up .3s;
  animation-fill-mode: forwards;
  animation-iteration-count: 1;
}

.drowdown-menu.hide-menu ul {
  animation-duration: 0s;
}
.dropdown-menu:hover ul {
  animation: slide-down .3s;
  animation-fill-mode: forwards;
}


@keyframes slide-down {
  from {
    opacity: 0;
    transform: translateY(-10%);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes slide-up {
  from {
    opacity: 1;
    transform: translateY(0);
  }
  to {
    opacity: 0;
    transform: translateY(-10%);
  }
}
@keyframes delay-overflow {
  0% {
    overflow: visible;
  }
  99% {
    overflow: visible;
  }
  100% {
    overflow: hidden;
  }
}
<div class="dropdown-menu hide-menu">
  <span>Menu</span>
  <ul>
    <li>A menu item</li>
    <li>Another menu item</li>
    <li>...</li>
    <li>And so on...</li>
  </ul>
</div>

Note: Une astuce très pratique avec la propriété animation est qu'elle vous permet de retarder l'application de toute propriété, même non animable, de l'application pendant la durée souhaitée. J'utilise cette astuce pour retarder l'application de overflow:hidden sur le parent (et overflow n'est pas animable) afin que l'animation de l'enfant - qui se passe en dehors des limites du parent - soit visible jusqu'à la fin. Une fois terminé, le overflow:hidden s'applique et il ne capte plus les événements de la souris en dehors de l'ouvre-menu.

10
Andrei Gheorghiu

c'est juste une simple logique, vous avez actuellement stylé vous glissez vers le bas mais vous n'avez pas stylé l'annulation de la div. Vous devez d'abord avoir un état fermé que je crois dans votre cas est .dropdown-menu

.dropdown-menu {
    transition: all 500ms ease;
}

ou juste utiliser 

.dropdown-menu {
    transition: margin 300ms cubic-bezier(0.17, 0.04, 0.03, 0.94);
}

Si cela ne fonctionne pas, 

0
Tsitso Makhakhe