【问题标题】:How to get flex items to grow according to content until both overflow如何让弹性项目根据内容增长,直到两者都溢出
【发布时间】:2021-08-10 23:34:15
【问题描述】:

我有一个包含 2 个项目的 flex 容器,其中包含不同大小的文本。我需要完成的设计有一些限制:

  • 如果两个项目都可以放入容器而无需截断,则两者都占用内容所需的空间
  • 如果一个占用超过 50% 的空间,而另一个没有,则较大的一个可以占用 50% + 剩余可用空间(因此,它应该根据需要进行 flex-grow,而另一个使用内容的宽度)
  • 如果两者都占 50% 以上,则它们的宽度应该相等 50%

flex 的问题在于,在最后一种情况下,似乎每个项目 flex-grow 的比例不同(尽管它们每个都有 flex-grow 1)。如果一个项目的文本比另一个项目长,它会占用更多空间,尽管它们都需要超过 50% 的空间。

我试图在这里重现这个问题:

.container {
    display: flex;
    flex-wrap: nowrap;
    width: 600px;
    margin: 0px auto;
    overflow: hidden;
    background-color: #BDBDBD;
}

.label {
  font-size: 1.2rem;
  text-align: center;
  padding: 20px;
  box-sizing: border-box;
}

.child {
    position: relative;
    width: auto;
    margin: 0.4em;
    border-radius: 1em;
    background-color: lightblue;
    padding: 10px;
    box-sizing: border-box;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  
    flex-grow: 1;
    flex-shrink: 1;
    flex-basis: auto;
    min-width: auto;
    width: auto;
    max-width: 100%;
}

/* Hard-coded */

.problem {
  border: 2px solid red;
}

.equal {
  width: 50%;
  border: 2px solid green;
}

.no-shrink {
  flex-shrink: 0;
  border: 2px solid green;
}
<div class="container">
    <div class="child problem">9 long long long long long long long long long</div>
    <div class="child problem">15 long long long long long long long long long long long long long long long</div>
</div>
<div class="container">
    <div class="child">12 long long long long long long long long long long long long</div>
    <div class="child">12 long long long long long long long long long long long long</div>
</div>

<div class="container">
    <div class="child">12 long long long long long long long long long long long long</div>
    <div class="child problem">7 long long long long long long long</div>
</div>

<div class="container">
    <div class="child red-child">2 long long</div>
    <div class="child green-child">12 long long long long long long long long long long long long</div>
</div>

<!-- The examples below are only to show what I'd like the flex items to do visually -->
<div class="container label">Should look like:</div>

<div class="container">
    <div class="child equal">9 long long long long long long long long long</div>
    <div class="child equal">15 long long long long long long long long long long long long long long long</div>
</div>
<div class="container">
    <div class="child">12 long long long long long long long long long long long long</div>
    <div class="child">12 long long long long long long long long long long long long</div>
</div>

<div class="container">
    <div class="child">12 long long long long long long long long long long long long</div>
    <div class="child no-shrink">7 long long long long long long long</div>
</div>

<div class="container">
    <div class="child">2 long long</div>
    <div class="child">12 long long long long long long long long long long long long</div>
</div>

“long”之前的数字表示“long”这个词出现了多少次,因此该文本有多长。正如您在红色轮廓的 div 中看到的那样,较长的文本会占用更多空间。我硬编码了我需要它在下面的样子——“固定”版本用绿色标出。

flex 能做到这一点吗?还是我需要基本使用javascript来解决这个问题?

【问题讨论】:

  • 我相信您需要 Javascript 来确定如果缺少空间,两者是否都溢出。 flex 不会为你做这件事。

标签: html css flexbox


【解决方案1】:

为了使其工作,每个子元素都需要根据两个子元素的总宽度应用一个最大宽度样式。这可以使用 javascript 来完成,如附件示例。

在此示例中,如果两个子元素都大于容器的 50%,则将“.max-width-50”类应用于两个元素。如果只有一个元素大于 50%,则“.max-width-100”类仅应用于该行中的那个元素。

为了正确计算每个元素的宽度,必须在 javascript 计算完成后应用 overflow: hidden。因此,一个 .overflow 类会在计算完成后应用于所有需要它的元素。

let containers = document.querySelectorAll('.container');

containers.forEach(container => {
  let children = container.querySelectorAll('.child');
  let counter = 0;
  let widthCounter = 0;

  containerWidth = container.offsetWidth;

  if (children.length) {
    children.forEach(child => {
      let childWidth = child.offsetWidth;
      let overMax = childWidth / containerWidth;


      if (overMax > 0.50) {
        child.classList.add('max-width-100');
        counter++;
      }

      widthCounter += childWidth;
    });

    // If both elements are greater than 50%
    if (counter == 2) {
      children.forEach(child => {
        child.classList.add('max-width-50');
        child.classList.remove('max-width-100');
      })
    }

    // If elements total width is greater than 100%
    if (widthCounter > 1.00) {
      children.forEach(child => {
        child.classList.add('overflow-hidden');
      });
    }

  }
});
.container {
  display: flex;
  flex-wrap: nowrap;
  width: 600px;
  margin: 0px auto;
  overflow: hidden;
  background-color: #BDBDBD;
}

.label {
  font-size: 1.2rem;
  text-align: center;
  padding: 20px;
  box-sizing: border-box;
}

.child {
  position: relative;
  width: auto;
  margin: 0.4em;
  border-radius: 1em;
  background-color: lightblue;
  padding: 10px;
  box-sizing: border-box;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex-grow: 1;
  flex-shrink: 1;
  flex-basis: auto;
  max-width: 100%;
}

.max-width-50 {
  flex-basis: 50%;
  max-width: 50%;
}

.max-width-100 {
  max-width: 100%;
}

.overflow-hidden {
  overflow: hidden;
}


/* Hard-coded */

.problem {
  border: 2px solid red;
}

.equal {
  width: 50%;
  border: 2px solid green;
}

.no-shrink {
  flex-shrink: 0;
  border: 2px solid green;
}
<div class="container">
  <div class="child problem">9 long long long long long long long long long</div>
  <div class="child problem">15 long long long long long long long long long long long long long long long</div>
</div>
<div class="container">
  <div class="child">12 long long long long long long long long long long long long</div>
  <div class="child">12 long long long long long long long long long long long long</div>
</div>

<div class="container">
  <div class="child">12 long long long long long long long long long long long long</div>
  <div class="child problem">7 long long long long long long long</div>
</div>

<div class="container">
  <div class="child red-child">2 long long</div>
  <div class="child green-child">12 long long long long long long long long long long long long</div>
</div>

<!-- The examples below are only to show what I'd like the flex items to do visually -->
<div class="container label">Should look like:</div>

<div class="container">
  <div class="child equal">9 long long long long long long long long long</div>
  <div class="child equal">15 long long long long long long long long long long long long long long long</div>
</div>
<div class="container">
  <div class="child">12 long long long long long long long long long long long long</div>
  <div class="child">12 long long long long long long long long long long long long</div>
</div>

<div class="container">
  <div class="child">12 long long long long long long long long long long long long</div>
  <div class="child no-shrink">7 long long long long long long long</div>
</div>

<div class="container">
  <div class="child">2 long long</div>
  <div class="child">12 long long long long long long long long long long long long</div>
</div>

【讨论】:

    猜你喜欢
    • 2021-01-23
    • 1970-01-01
    • 2016-07-13
    • 1970-01-01
    • 2014-08-09
    • 2012-12-10
    • 1970-01-01
    • 2018-07-06
    相关资源
    最近更新 更多