html 过渡灵活增长与动态内容高度

tgabmvqs  于 11个月前  发布在  其他
关注(0)|答案(3)|浏览(99)

我正在显示一个项目列表。每个项目都有一个标题和一些内容。单击标题时,每个项目的高度将展开/折叠。每个项目内容的高度是动态的。
我得到了下面的代码(见下文),它的工作。但是,在用户点击.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>
x7rlezfr

x7rlezfr1#

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

.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

  • 我还更正了<br>标记(</br>无效)。*
s4chpxco

s4chpxco2#

这是一个版本,它为不支持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>
wljmcqd8

wljmcqd83#

使用flex-box:

let toggleOpen = () => {
  document.querySelector('.wrapper').classList.toggle('is-open');
}
.wrapper {
  display: flex;
}

.inner {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.5s ease-out;
}

.wrapper.is-open .inner {
  max-height: 100%;
}

.fillBelow {
 background-color: red;
}
<button onclick="toggleOpen()">toggle collapsed</button>
<div class="wrapper is-open">
 <div>
  <div class="inner">
  Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent mi enim, venenatis non facilisis sed, finibus in enim. Sed auctor enim nisl, sit amet feugiat risus blandit vitae.
  </div>
  </div>
</div>
<div class="fillBelow">other content</div>

使用网格:

let toggleOpen = () => {
  document.querySelector('.wrapper').classList.toggle('is-open');
}
.wrapper {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.5s ease-out;
}

.wrapper.is-open {
  grid-template-rows: 1fr;
}

.inner {
  overflow: hidden;
}

.fillBelow {
 background-color: red;
}
<button onclick="toggleOpen()">toggle collapsed</button>
<div class="wrapper is-open">
  <div class="inner">
  Lorem ipsum  Nulla lectus diam, sagittis id urna in, tincidunt facilisis sapien. Sed ante turpis, porttitor a diam at, auctor lobortis sapien. Cras ornare dolor sed arcu laoreet volutpat ut tristique ipsum.
  </div>
</div>
<div class="fillBelow">other content</div>

注意:我知道这个问题是关于flex-grow的,但我相信它的意图更接近于“如何用css动画 accordion ”。这个问题恰好是我在谷歌上的第一个点击。我没有想到这个,但它来自https://keithjgrant.com/posts/2023/04/transitioning-to-height-auto/

相关问题