Как перевести дочерний элемент, когда родитель переходит с экрана: none to block

У меня возникли проблемы с созданием всплывающего меню с определенным эффектом. Всплывающее окно выводится с экрана: никто не блокирует, а затем я использую jquery для анимации непрозрачности от 0 до 1 (и наоборот). Это необходимо, потому что в противном случае переход не произойдет, когда элемент просто изменил свойство отображения. Я не думал, что это будет распространяться на детей. Но внутри моего вылета у меня есть 4 столбца ссылок, у которых есть переход прозрачности, каждый со своей собственной задержкой, поэтому они входят в один за раз. Однако это не работает, когда появляется всплывающее окно. Они мгновенно на непрозрачность: 1 и даже с большим временем задержки все еще не работают.

Есть ли способ обойти это? Я знал, что анимация CSS наряду с изменением отображения на одном и том же элементе не работает, но выяснение того, что любые дочерние анимации также не работают, немного расстраивает. Я бы предпочел не писать javascript, когда CSS так прост. Но если javascript - единственный ответ, тогда это будет легко решить.

Здесь очень упрощенный пример кода:

$flyout.addClass('in').animate({opacity: 1}, 200, "linear");

"in" - это класс, который вызывает переход по столбцам:

.flyout { display: none; }

.flyout.in { display: block; }

.columns li {
    opacity: 0;
    -webkit-transition: opacity 0.2s;
}

.flyout.in .columns li { opacity: 1; }

// delay increases with each column
.columns > li:first-child {
    -webkit-transition-delay: 0.2s;
}

Ответ 1

Есть ли способ обойти это? Я знал, что анимация CSS наряду с изменением отображения на одном и том же элементе не работает, но выяснение того, что любые дочерние анимации также не работают, немного расстраивает.

Он применим не только к одному и тому же элементу, но и всему поддереву - поскольку все поддерево не отображается.

  • вы можете установить display: block на обертке, а затем принудительно wrapperElement.offsetHeight; (путем wrapperElement.offsetHeight; буфера стиля с помощью wrapperElement.offsetHeight;), а затем добавить класс, который задает opacity:1 вашим детям (или делать то, что вы делаете, чтобы начать анимации).
  • вы можете использовать другой метод визуального скрытия вашей обертки, например width: 0; height: 0; overflow: hidden; visibility: hidden; width: 0; height: 0; overflow: hidden; visibility: hidden; (или, для более приятных переходов transform: scale(0); visibility: hidden; pointer-events: none;)

Как только display:none не участвует, вы ввернуты, когда дело доходит до переходов. Лучше всего это избежать. Я использовал второй вариант без каких-либо серьезных проблем уже довольно давно.


редактировать после того, как OP добавил какой-то демо-код:

  • .animate() обертки можно сделать также в CSS
  • не только использовать свойство CSS с -webkit-transition префиксом поставщика -webkit-transition, но и надлежащий transition
  • //delay increases with each column выглядит как заблуждение. все элементы селектора .columns > li:first-child применяется к той же самой задержке - они не будут ждать, пока предыдущий элемент завершит свой переход. Если вы хотите определить, что в CSS, вам придется играть с : nth-child() или одним из своих кузенов

Ответ 2

если вы хотите только изменить opacity вы можете использовать функции FadeIn и FadeOut JQuery, но если вы хотите более сложный переход, вы можете использовать CSS3 (это действительно хорошая библиотека). См. Этот ДЕМО, где вы можете увидеть это двумя разными способами.

Вы также можете добавить элемент управления в класс следующим образом:

    $("OBJECT").click(function(){
    if ($("OBJECT").hasClass("CLASS")){
        $("OBJECT").removeClass("CLASS");
    } else {
        $("OBJECT").addClass("CLASS");
    }
});

для выполнения двухсторонних функций.

$(document).ready(function(){
$("#fadeOut").click(function(){
    var duration = 500;
    $("#div").fadeOut(duration);
});
$("#css").click(function(){
    $("#div").addClass("out");
    setTimeout(
       function() {
          $("#div").css("display", "none");
       },
    2001);
});
});
#div {
    width:200px;
    height:200px;
    background-color:red;
    text-align:center;
    vertical-align:middle;
    /* Animation CSS */
    -webkit-animation-duration: 2s;
    animation-duration: 2s;
    -webkit-animation-fill-mode: both;
    animation-fill-mode: both;
}
/* Setup CSS3 animations */
@-webkit-keyframes out {
  0% {
    -webkit-transform-origin: top left;
    transform-origin: top left;
    -webkit-animation-timing-function: ease-in-out;
    animation-timing-function: ease-in-out;
  }

  20%, 60% {
    -webkit-transform: rotate3d(0, 0, 1, 80deg);
    transform: rotate3d(0, 0, 1, 80deg);
    -webkit-transform-origin: top left;
    transform-origin: top left;
    -webkit-animation-timing-function: ease-in-out;
    animation-timing-function: ease-in-out;
  }

  40%, 80% {
    -webkit-transform: rotate3d(0, 0, 1, 60deg);
    transform: rotate3d(0, 0, 1, 60deg);
    -webkit-transform-origin: top left;
    transform-origin: top left;
    -webkit-animation-timing-function: ease-in-out;
    animation-timing-function: ease-in-out;
    opacity: 1;
  }

  to {
    -webkit-transform: translate3d(0, 700px, 0);
    transform: translate3d(0, 700px, 0);
    opacity: 0;
  }
}

@keyframes out {
  0% {
    -webkit-transform-origin: top left;
    transform-origin: top left;
    -webkit-animation-timing-function: ease-in-out;
    animation-timing-function: ease-in-out;
  }

  20%, 60% {
    -webkit-transform: rotate3d(0, 0, 1, 80deg);
    transform: rotate3d(0, 0, 1, 80deg);
    -webkit-transform-origin: top left;
    transform-origin: top left;
    -webkit-animation-timing-function: ease-in-out;
    animation-timing-function: ease-in-out;
  }

  40%, 80% {
    -webkit-transform: rotate3d(0, 0, 1, 60deg);
    transform: rotate3d(0, 0, 1, 60deg);
    -webkit-transform-origin: top left;
    transform-origin: top left;
    -webkit-animation-timing-function: ease-in-out;
    animation-timing-function: ease-in-out;
    opacity: 1;
  }

  to {
    -webkit-transform: translate3d(0, 700px, 0);
    transform: translate3d(0, 700px, 0);
    opacity: 0;
  }
}
.out {
    -webkit-animation-name: out;
    animation-name: out;
}
<html>
<head>
    <link rel="stylesheet" type="text/css" href="style.css">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
    <script type="text/javascript" src="script.js"></script>
</head>
<body>
<div id="div"></div>
<button id="fadeOut">fadeOut</button>

<button id="css">CSS3</button>
</body>
</html>

Ответ 3

@rodneyrehm Answer в значительной степени суммирует все, что вам нужно при обработке анимации с помощью свойства отображения CSS.

После переключения свойства отображения необходимо активировать оплату и применить после него класс анимации.

// find elements
const banner = $("#banner")
const button = $(".banner__button")
const text = $(".banner__text")
let isVisible = false

// toggle display
button.on("click", () => {
	if (!isVisible) {
  	text.addClass("display--block")
    text.outerWidth()
    text.addClass("text--show")
    isVisible = true
  } else {
  	text.addClass("text--hide")
    .one('webkitAnimationEnd oanimationend msAnimationEnd animationend', () => {
  		text.removeClass("display--block")
      text.removeClass("text--show")
      text.removeClass("text--hide")
      isVisible = false
    })
  }
  
})
body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
}

#banner {
  background: #fff;
  border-radius: 4px;
  padding: 20px;
  font-size: 25px;
  text-align: center;
  margin: 0 auto;
  width: 300px;
  height: 150px;
  display: flex;
  flex-flow: column nowrap;
}

.banner__button {
  background: #0084ff;
  border: none;
  border-radius: 5px;
  padding: 8px 14px;
  font-size: 15px;
  color: #fff;
  cursor: pointer;
  transition: box-shadow 0.3s, transform 0.6s;
}

.banner__button:hover {
  box-shadow: 0 3px 8px 2px #9d9d91;
  transform: translateY(-2px)
}

.banner__button:focus {
  outline: 0;
}

.flex--1 {
  flex: 1;
}

.banner__text {
  display: none;
  opacity: 0;
  transition: all 0.6s;
}

.display--block {
  display: block;
}
.text--show {
  animation: slide-in 1s forwards;
}
.text--hide {
  animation: slide-out 1s forwards;
}

@keyframes slide-in {
  0% {
    opacity: 0;
    transform: translateX(-30px)
  }
  100% {
    opacity: 1;
    transform: translateX(0px)
  }
}
@keyframes slide-out {
  0% {
    opacity: 1;
    transform: translateX(0px)
  }
  100% {
    opacity: 0;
    transform: translateX(30px)
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="banner">
  <div class="flex--1">
    <p class="banner__text">Hello World</p>  
  </div>
  <button class="banner__button">Toggle Text</button>
</div>

Ответ 4

Я вошел в эту же проблему некоторое время назад, мой обходной путь был очень взломанным, но в основном работает

Когда вы меняете a, скажем, непереходное свойство, например, "дисплей", происходит очень быстро, я решил, что если вы используете тиммер для изменения свойства непереходного и несколько миллисекунд позже, вы измените другое переходное свойство, это вроде работает, вам также нужно использовать другой таймер для поворота

HTML-код

<div class="content_menu_item">
   <a href="#">Im a menu item</a>
   <ul>
     <li>
       <a href="#">Sub Item 1</a>
     </li>
     <li>
      <a href="#">Sub Item 2</a>
     </li>
     <li>
      <a href="#">Sub Item 3</a>
     </li>
   </ul>
</div><div class="content_menu_item">
   <a href="#">Im a menu item</a>
   <ul>
     <li>
       <a href="#">Sub Item 1</a>
     </li>
     <li>
      <a href="#">Sub Item 2</a>
     </li>
     <li>
      <a href="#">Sub Item 3</a>
     </li>
   </ul>
</div>

CSS

.content_menu_item{
  vertical-align: top;
  display:inline-block;
  width: 140px;
  height: 32px;
  position:relative;
  border:1px solid #b388ff;
  text-align: center;
    background-color: #6200ea;
}

.content_menu_item a{
  line-height: 32px;
  display: inline-block;
  text-decoration: none;
  color:white;
  width: 140px;
}

ul{
  padding: 0;
  list-style:none;
  display:none;
  margin: 0;
  opacity:0.5;
}
.content_menu_item ul li{
  color:white;
  background: #1e88e5;
  line-height: 26px;
  vertical-align: top;
  transition:all 385ms cubic-bezier(0.895, 0.03, 0.685, 0.22);
  opacity:0;
}

.content_menu_item ul li.on{
  opacity:1;
}

.content_menu_item ul li.on:nth-child(1){
  transition-delay:0ms;
}
.content_menu_item ul li.on:nth-child(2){
  transition-delay:50ms;
}
.content_menu_item ul li.on:nth-child(3){
  transition-delay:100ms;
}

.content_menu_item ul li.off{
  opacity:0;
}

.content_menu_item ul li.off:nth-child(3){
  transition-delay:0ms;
}
.content_menu_item ul li.off:nth-child(2){
  transition-delay:50ms;
}
.content_menu_item ul li.off:nth-child(1){
  transition-delay:100ms;
}

jQuery для handlig состояния мыши

$('.content_menu_item').hover(
 function(){
  // mouse over
  $(this).find('ul').show(); // show the sub list of the menu, basicaly display block
  timmeron = setTimeout(()=>{ // 10 miliseconds later add the class to change the opacity, the on class has a transition-delay for every element usin nth-child
    $(this).find('li').addClass('on');
  },10);
 },function(){
    //mouse out
    $(this).find('li').removeClass('on'); // remove the on class 
    $(this).find('li').addClass('off'); // add the off class to invert the transition-delay
        timmeroff = setTimeout(()=>{
          $(this).find('ul').hide(); // hide the element with time after the transition completes 
          $(this).find('li').removeClass('off'); // remove both classes
          $(this).find('li').removeClass('on');
      },500);
})

И вот рабочий пример https://codepen.io/Teobis/pen/QxmqGQ

Надеюсь это поможет