【问题标题】:css grid grows over 100% width with fr but not with minmaxcss 网格使用 fr 增长超过 100% 的宽度,但没有使用 minmax
【发布时间】:2018-07-09 19:51:08
【问题描述】:

.small-container { width: 200px; }
.small-container > div { margin: 16px; }
.border { box-shadow: 0 0 2px 2px black; }

.break-long-text {
    width: 100%;
    word-wrap: break-word;
    overflow-wrap: break-word;
}

.grid-fr {
    display: grid;
    grid-template-columns: 1fr;
}

.grid-minmax {
    display: grid;
    grid-template-columns: minmax(120px, 1fr);
}
<div class="small-container">
  <div class="grid-fr">
    <div class="break-long-text border">
      LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG
    </div>
  </div>
  <div class="grid-minmax">
    <div class="break-long-text border">
      LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG
    </div>
  </div>
</div>

这两个网格完全一样,唯一不同的是grid-template-columns的值。但是,一个网格尊重其父级 (200px) 的宽度,而另一个则忽略宽度。

  1. grid:grid-template-columns: 1fr; => 忽略父宽度并继续直到内容被填满

  2. grid: grid-template-columns: minmax(120px, 1fr); => 只上升到父宽度 (200px) 然后变得尽可能高。但是,它仍然大于定义的最小宽度(120px),这当然是正确的,因为在本例中1fr 大于120px

由于最后两者应该具有相同的宽度1fr,我想知道不同的结果。这是错误还是预期行为?为什么第二个网格按我预期的方式工作,而不是第一个?

如果我不希望一个单元格大于其父单元格,我是否应该始终使用minmax

【问题讨论】:

标签: html css css-grid


【解决方案1】:

这是第二个网格的解决方案。

.grid-minmax {
   display: grid;
   grid-template-columns: minmax(120px, 1fr);
 }

这是浏览器计算轨道大小的方式:

(200px container) - (120px nonflexible track size) + (1fr leftover space) = 200px

使用规范中提供的指导(见下文),上述行为相对简单明了。

但是为什么第一个容器中的内容会溢出呢?

这是一个棘手的场景,在这一点上,我可以看到两个可能的答案路径。

  1. 之间的工作存在问题/问题/错误:

    .break-long-text {
        word-wrap: break-word;
        overflow-wrap: break-word;
     }
    

    grid-template-columns: 1fr;
    

    我这样说是因为当字符串被分解时,问题中的问题就不存在了。换句话说,两个网格容器的行为相同 (demo)。

  1. 我在规范中找不到答案。我查看了以下部分。


fr 单元的详细工作原理如下:

来自规范:

§ 7.2.3. Flexible Lengths: the fr unit

灵活的长度或&lt;flex&gt; 是具有fr 单位的维度,它表示网格容器中剩余空间的一小部分。

大小为fr 单位的轨道被称为灵活轨道,因为它们会根据剩余空间进行伸缩,类似于伸缩项如何填充伸缩容器中的空间。

好的。到现在为止还挺好。网格布局中的fr 单元的功能类似于弹性布局中的flex-grow

继续规范...

剩余空间的分配发生在所有非灵活轨道大小函数都达到最大值之后。

这些行或列的总大小从可用空间中减去,产生剩余空间,然后根据它们的弹性系数在弹性大小的行和列之间分配。

(强调我的)

换句话说,首先从可用空间(在本例中为 200 像素)中减去所有非灵活轨道大小(例如基于像素或 em 的轨道大小)。剩下的任何空间都被认为是剩余空间,然后将成为fr 单元的目标。

另外,究竟什么是“轨道尺寸函数”?

每个轨道大小函数都可以指定为长度、网格容器大小的百分比、占用列或行的内容的度量,或者网格中可用空间的一小部分。

也可以使用minmax() 表示法将其指定为范围,它可以结合任何前面提到的机制来为列或行指定单独的最小和最大轨道大小函数。

https://www.w3.org/TR/css3-grid-layout/#grid-template-rows-track-sizing-function

这解释了第二个网格容器(使用minmax())而不是第一个(使用1fr)的工作原理。

【讨论】:

  • 我也确信这可能是一个错误 .. 正在等待你确认这不是一个合乎逻辑的行为:p
  • 我不认为这是一个错误,因为支持 Grid 的所有主要浏览器的行为都是一致的。但是因为当字符串被打断时问题就解决了,它留下了这种可能性。 @TemaniAfif
  • 您好,感谢您的回答!但是我认为这与overflow-wrap: break-word; 没有任何关系,当我删除相应的类时,行为保持不变(updated fiddle - 你可以在box-shadow 上看到它)
  • 是的,正如我在上面的评论中提到的,错误选项不太可能,但在我看来,仍然在可能的范围内。我会更加重视我的第二个选择。
  • 另一个认为这与网格大小算法有关的原因是1frauto 呈现相同的布局。同样,我没有看到或不理解与此行为相关的规范语言。
【解决方案2】:

解决方案

设置 min-width:0.break-long-text 容器就可以了。

.small-container { width: 200px; }
.small-container > div { margin: 16px; }
.border { box-shadow: 0 0 2px 2px black; }

.min-width-0{
    min-width: 0;
}
.break-long-text {
    width: 100%;
    word-wrap: break-word;
    overflow-wrap: break-word;
}

.grid-fr {
    display: grid;
    grid-template-columns: 1fr;
}

.grid-minmax {
    display: grid;
    grid-template-columns: minmax(120px, 1fr);
}
<div class="small-container">
  <div class="grid-fr">
    <div class="break-long-text border min-width-0">
      LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG
    </div>
  </div>
  <div class="grid-fr">
    <div class="break-long-text border">
      LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG
    </div>
  </div>
  <div class="grid-minmax">
    <div class="break-long-text border">
      LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG
    </div>
  </div>
</div>

说明:

From css-tricks:

网格列的最小宽度为自动。 (顺便说一下,flex 项目也是如此。)

由于 auto 完全基于内容,我们可以说它是“无限”大小的,它的尺寸是可变的。如果我们要在列上设置一个明确的宽度,例如 50% 或 400px,那么我们会说它是“绝对”大小的。

要应用我们的修复,我们需要确保列具有明确的最小宽度而不是自动。

【讨论】:

    【解决方案3】:

    如果我不想让一个单元格变大,我应该总是使用 minmax 比它的父母?

    在我看来,网格fr 单位与word-wrap , overflow-wraphyphens 属性的配合并不好。

    既然如此,当您有理由相信内部文本会包含长词时,我建议您使用minmax() 函数作为解决方法。

    注意:因为我们试图模拟 fr 单位的结果 - 在 minmax() 函数中使用 0 作为最小长度是有意义的。例如:grid-template-columns: minmax(0, 1fr);

    下面的演示将 fr 单位和 minmax() 与长文本进行比较 - 结果看起来一样!

    .medium-container { 
      width: 50vw;
      border: 1px solid green;
      padding: 20px; 
    }
    .border { box-shadow: 0 0 2px 2px black; }
    
    .break-long-text {
        width: 100%;
        word-wrap: break-word;
        overflow-wrap: break-word;
    }
    
    
    .grid-fr {
        display: grid;
        grid-template-columns: repeat(3, 1fr);
        grid-gap: 20px;
    }
    
    .grid-minmax {
        display: grid;
        grid-template-columns: repeat(3, minmax(0, 1fr));
        grid-gap: 20px;
    }
    
    .break-long {
        width: 100%;
        word-wrap: break-word;
        overflow-wrap: break-word;
    }
    <h2>Using 'fr' units:</h2>
    <div class="medium-container">
      <div class="grid-fr">
        <div class="break-long-text border"> Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled
          it to make a type specimen book. 
        </div>
        <div class="break-long-text border"> Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s,  when an unknown printer took a galley of type and scrambled
          it to make a type specimen book. 
        </div>
        <div class="break-long-text border"> Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled
          it to make a type specimen book. 
        </div>
          </div>
    </div>
    <hr>
    <h2>Using 'minmax' workaround (contains long text):</h2>
    <div class="medium-container">
      <div class="grid-minmax">
        <div class="break-long-text border"> Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG when an unknown printer took a galley of type and scrambled
          it to make a type specimen book. 
        </div>
        <div class="break-long-text border"> Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG when an unknown printer took a galley of type and scrambled
          it to make a type specimen book. 
        </div>
        <div class="break-long-text border"> Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG when an unknown printer took a galley of type and scrambled
          it to make a type specimen book. 
        </div>
          </div>
    </div>

    Codepen demo(调整大小以查看效果)


    另一种解决方法:word-break: break-word;

    'fr' 单位word-break 属性配合得很好

    .break-long-text {
        word-break: break-word; /* word-break workaround */
    }
    

    特别是,基于闪烁的浏览器可以使用 break-word 值,而 Firefox 需要 break-all 值。

    .small-container { width: 200px; }
    .small-container > div { margin: 16px; }
    .border { box-shadow: 0 0 2px 2px black; }
    
    .break-long-text {
        word-break: break-word;
    }
    /* firefox only CSS */
    @-moz-document url-prefix() {
      .break-long-text {
        word-break: break-all;
      }
    }
    
    .grid-fr {
        display: grid;
        grid-template-columns: 1fr;
    }
    
    .grid-minmax {
        display: grid;
        grid-template-columns: minmax(120px, 1fr);
    }
    <div class="small-container">
      <div class="grid-fr">
        <div class="break-long-text border">
          LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG
        </div>
      </div>
      <div class="grid-minmax">
        <div class="break-long-text border">
          LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG
        </div>
      </div>
    </div>

    此解决方法的问题在于,需要 break-all 值的浏览器 - 例如 firefox - break 在中间工作 - 通常不是预期的结果。

    .small-container { width: 200px; }
    .small-container > div { margin: 16px; }
    .border { box-shadow: 0 0 2px 2px black; }
    
    .break-long-text {
        word-break: break-all;
    }
    
    .grid-fr {
        display: grid;
        grid-template-columns: 1fr;
    }
    
    .grid-minmax {
        display: grid;
        grid-template-columns: minmax(0, 1fr);
    }
    <div class="small-container">
      <div class="grid-fr">
        <div class="break-long-text border">
          Lorem Ipsum is simply dummy text of the printing and typesetting industry. LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG when an unknown printer took a galley of type and scrambled
        </div>
      </div>
      <div class="grid-minmax">
        <div class="break-long-text border">
          Lorem Ipsum is simply dummy text of the printing and typesetting industry. LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG when an unknown printer took a galley of type and scrambled
        </div>
      </div>
    </div>

    【讨论】:

      猜你喜欢
      • 2018-09-29
      • 1970-01-01
      • 2013-07-29
      • 1970-01-01
      • 2021-05-07
      • 2019-01-28
      • 2011-09-17
      • 1970-01-01
      • 2013-10-03
      相关资源
      最近更新 更多