协慌网

登录 贡献 社区

显示屏上的转换:属性

我目前正在设计一个 CSS'mega dropdown' 菜单 - 基本上是一个常规的 CSS-only 下拉菜单,但包含不同类型的内容。

目前, 似乎 CSS3 Transitions 不适用于'display' 属性 ,即你不能进行任何类型的从display: nonedisplay: block (或任何组合)的转换。

当有人将鼠标悬停在其中一个顶级菜单项上时,是否有人会想到上述示例中的第二层菜单可以 “淡入”?

我知道你可以在visibility: property 上使用转换,但我想不出有效利用它的方法。

我也尝试过使用身高,但这只是失败了。

我也知道使用 JavaScript 实现这一点是微不足道的,但是我想挑战自己只使用 CSS 而且我认为我有点短。

欢迎所有和任何建议。

答案

您可以连接两个或更多个转换,这次visibility是最方便的。

div {
  border: 1px solid #eee;
}
div > ul {
  visibility: hidden;
  opacity: 0;
  transition: visibility 0s, opacity 0.5s linear;
}
div:hover > ul {
  visibility: visible;
  opacity: 1;
}
<div>
  <ul>
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
  </ul>
</div>

(不要忘记transition属性的供应商前缀)

更多细节在本文中

您需要通过其他方式隐藏元素才能使其生效。

我通过绝对定位两个<div>并将隐藏的一个设置为opacity: 0来完成效果opacity: 0

如果您甚至将display属性从none切换到block ,则不会发生对其他元素的转换。

要解决此问题,请始终允许元素display: block ,但通过调整以下任何方式隐藏元素:

  1. height设置为0
  2. opacity设置为0
  3. 将元素定位在另一个具有overflow: hidden元素的框架之外。

可能有更多解决方案,但如果您将元素切换为display: none ,则无法执行转换。例如,您可能尝试尝试这样的事情:

div {
    display: none;
    transition: opacity 1s ease-out;
    opacity: 0; 
}
div.active {
    opacity: 1;
    display: block;
}

但是,这行不通的。根据我的经验,我发现这无所事事。

因此,您将始终需要保持元素display: block - 但您可以通过执行以下操作来绕过它:

div {
    transition: opacity 1s ease-out;
    opacity: 0; 
    height: 0;
    overflow: hidden;
}
div.active {
    opacity: 1;
    height: auto;
}

在本文发表时,如果您尝试更改display属性,所有主流浏览器都会禁用 CSS 过渡,但 CSS 动画仍然可以正常工作,因此我们可以将它们用作解决方法。

示例代码: - (您可以相应地将它应用于您的菜单) 演示

将以下 CSS 添加到样式表: -

@-webkit-keyframes fadeIn {
    from { opacity: 0; }
      to { opacity: 1; }
}  
@keyframes fadeIn {
    from { opacity: 0; }
      to { opacity: 1; }
}

然后将fadeIn动画应用于父 hover 上的子项: - (当然还设置display: block

.parent:hover .child {
    display: block;
    -webkit-animation: fadeIn 1s;
    animation: fadeIn 1s;
}

更新 2019 - 也支持淡出的方法:

(有些 JS 需要)

// We need to keep track of faded in elements so we can apply fade out later in CSS
document.addEventListener('animationstart', function (e) {
  if (e.animationName === 'fade-in') {
      e.target.classList.add('did-fade-in');   
  }
});

document.addEventListener('animationend', function (e) {
  if (e.animationName === 'fade-out') {
      e.target.classList.remove('did-fade-in');
   }
});
div {
    border: 5px solid;
    padding: 10px;
}

div:hover {
    border-color: red;
}
 
.parent .child {
  display: none;
}
 
.parent:hover .child {
  display: block;
  animation: fade-in 1s;
}

.parent:not(:hover) .child.did-fade-in {
  display: block;
  animation: fade-out 1s;
} 

@keyframes fade-in {
  from { 
    opacity: 0; 
  }
  to { 
    opacity: 1; 
  }
}

@keyframes fade-out {
  from { 
    opacity: 1; 
  }
  to { 
    opacity: 0;
  }
}
<div class="parent">
    Parent
    <div class="child">
        Child
    </div>
</div>