【问题标题】:Transition flex-grow with dynamic content height具有动态内容高度的过渡 flex-grow
【发布时间】:2016-04-30 08:39:03
【问题描述】:

我正在显示一个项目列表。每个项目都有一个标题和一些内容。单击其标题时,每个项目的高度都会展开/折叠。每个项目内容的高度是动态的。

我有以下有效的代码(见下文)。但是,在用户单击 .header 和过渡开始之间会有一点延迟。

这种延迟似乎是由于我使用max-height: min-content 而引起的。我相信在添加/删除.isCollapsed 类之后,浏览器需要一点时间来重新计算内容的高度。

不知道有没有更正确的方法可以达到这个效果?

如果我删除max-height: min-content,那么.item 上的flex: 1 会导致每个项目在展开时具有相同的高度。这是不希望的。我希望每个项目的高度适合其内容。

我不想要需要我用 JavaScript 或类似语言测量文本的解决方案。目标是利用 flexbox 在不知道content 的高度的情况下执行过渡。

$('.header').click(function() {
  $(this).parent().toggleClass('isCollapsed');
});
*,
*::before,
*::after {
  box-sizing: border-box;
}
html,
body {
  height: 100%;
  margin: 0;
}
ul,
li {
  list-style: none;
  margin: 0;
  padding: 0;
}
.items {
  display: flex;
  flex-direction: column;
  height: 100%;
  flex: 1;
}
.item {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  min-height: 48px;
  transition: flex-grow 1s;
  flex: 1;
  max-height: min-content;
}
.header {
  display: flex;
  height: 48px;
  padding: 16px;
  align-items: center;
  flex-shrink: 0;
}
.isCollapsed {
  flex-grow: .001;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class='items'>
  <li class='item'>
    <div class='header'>Item A Header</div>
    <div class='content'>Item A Content This content is</br>
      really</br>
      really</br>
      really</br>
      really</br>
      long.
    </div>
  </li>
  <li class='item'>
    <div class='header'>Item B Header</div>
    <div class='content'>
      Item B Content This content is</br>
      short.
    </div>
  </li>
</ul>

【问题讨论】:

  • 这根本没有回答我的问题。您可以从我的示例代码中看到,我为 flex-grow 指定了 0.001 的值,并且它在我提供的示例中成功地设置了动画。请阅读问题。
  • 用户交互和动画之间存在延迟。如果我删除 max-height: min-content 延迟消失,但每个项目的高度变得太大/不受其内容的限制。
  • 是的...不确定这里是否有使用 flexbox 的答案。正如您所建议的,延迟是由浏览器进行数学运算引起的。
  • 我查看了 Bootstrap 如何进行折叠菜单,看起来他们在 JS 中测量文本,设置高度、过渡,然后删除固定高度。你知道这是否是目前实现这种效果的唯一可行方法吗?我认为 Bootstrap 的解决方案可能只是针对较旧的浏览器支持。我找不到太多关于严格针对常青浏览器执行此操作的信息。
  • 这里最好的技巧是将它的最大高度转换为一个总是大于内容的值,并使用缓出,使它看起来最好。

标签: html css flexbox


【解决方案1】:

在以下代码块中,还有一些提高效率的空间。

.item {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  min-height: 48px;
  transition: flex-grow 1s;
  flex: 1;
  max-height: min-content;
}

您正在使用min-heightflex。但是有了flex,你就不需要min-height了。

试试这个:

.item {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  /* min-height: 48px; */
  transition: flex-grow 1s;
  flex: 1 0 48px; /* adjusted */
  max-height: min-content;
}

延迟已经结束了。

DEMO

我还更正了&lt;br&gt; 标签(&lt;/br&gt; 无效)。

【讨论】:

  • 通过将 transition: flex-grow 0.4s; 添加到 .isCollapsed 类中,它会更快地响应/折叠,使其看起来更好,至少对于内容较少的 2:nd 项目。它在 Chrome 中看起来非常好,但在 Firefox 和 Edge 中表现得很奇怪。
  • 我很确定min-height: 48pxflex-basis: auto 等同于flex-basis: 48px,因为flex-basis: auto 只是指height。我承认这是一个更好的短手,但在功能上是等效的。请参阅此处“内容”下的注释:developer.mozilla.org/en-US/docs/Web/CSS/flex-basis#Values 您的演示中肯定仍然存在延迟。如果您打开开发工具并检查元素,它可能会对您有所帮助。在任何过渡效果开始之前,您就会看到 isCollapsed 类出现/消失。
  • isCollapsed 类与过渡同时出现/消失。也许与缓存或本地硬件处理有关。在 Chrome 上测试(我相信这是唯一支持 min-content 的浏览器。caniuse.com/#search=min-content
【解决方案2】:

这是一个版本,对于不支持 min-content 的浏览器有一个后备方案。

人们总是可以使用max-heighttransition-duration 值来实现更平滑的过渡,但要使其完美,并假设content 高度不是静态的,我(今天)看不到这种情况发生没有脚本。

我在 Chrome(使用 min-content)上注意到的一件奇怪的事情是,可见的过渡效果在不同的视口大小上的速度不同,而 max-height 版本没有。

$('.header').click(function() {
  $(this).parent().toggleClass('isCollapsed');  
});
*,
*::before,
*::after {
  box-sizing: border-box;
}
html,
body {
  height: 100%;
  margin: 0;
}
ul,
li {
  list-style: none;
  margin: 0;
  padding: 0;
}
.items {
  display: flex;
  flex-direction: column;
  height: 100%;
  flex: 1;
}
.item {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  min-height: 48px;
  transition: max-height .5s;
  flex: 0 0 auto;
  max-height: 300px;
}
.header {
  display: flex;
  height: 48px;
  padding: 16px;
  align-items: center;
  flex-shrink: 0;
}
.isCollapsed {
  max-height: 48px;
  transition: max-height .2s;
}
@supports (max-height: min-content) {
  .item {
    max-height: min-content;
    transition: flex-grow .6s;
    flex: 1;
  }
  .isCollapsed {
    max-height: min-content;
    flex: .001;
    transition: flex-grow .3s;
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class='items'>
  <li class='item'>
    <div class='header'>Item A Header</div>
    <div class='content'>Item A Content This content is<br>
      really<br>
      really<br>
      really<br>
      really<br>
      long.
    </div>
  </li>
  <li class='item'>
    <div class='header'>Item B Header</div>
    <div class='content'>
      Item B Content This content is<br>
      short.
    </div>
  </li>
  <li class='item'>
    <div class='header'>Item C Header</div>
    <div class='content'>Item C Content This content is<br>
      really<br>
      really<br>
      really<br>
      really<br>
      long.
    </div>
  </li>
</ul>

【讨论】:

    猜你喜欢
    • 2012-06-14
    • 2015-06-19
    • 2020-01-15
    • 2019-05-27
    • 2021-09-16
    • 1970-01-01
    • 1970-01-01
    • 2012-01-21
    • 2021-08-26
    相关资源
    最近更新 更多