【问题标题】:Setting overflow: scroll on a table with display: flex设置溢出:在带有 display: flex 的表格上滚动
【发布时间】:2015-08-31 07:30:21
【问题描述】:

我有一个带有display: flex 属性的表格,其单元格将垂直居中。当单元格数超出表格可以显示的范围时,overflow: scroll 属性不会考虑顶部的单元格。

在下面的示例代码中,滚动在字母 K 处停止,而应该一直向上到字母 A。这是什么原因造成的?

#container {
  height: 180px;
  display: flex;
  flex-flow: row;
  align-items: stretch;
  border: 1px dashed gray;
}

table {
  display: flex;
  flex-flow: row;
  align-items: center;
  margin: 10px;
  overflow: scroll;
  border: 1px dashed blue;
}

td {
  height: 10px;
  width: 100px;
  border: 1px solid red;
}

#container div {
  flex: 1;
  margin: 10px;
  border: 1px dashed red;
}
<div id="container">
  <table>
    <tr><td>A</td></tr>
    <tr><td>B</td></tr>
    <tr><td>C</td></tr>
    <tr><td>D</td></tr>
    <tr><td>E</td></tr>
    <tr><td>F</td></tr>
    <tr><td>G</td></tr>
    <tr><td>H</td></tr>
    <tr><td>I</td></tr>
    <tr><td>J</td></tr>
    <tr><td>K</td></tr>
    <tr><td>L</td></tr>
    <tr><td>M</td></tr>
    <tr><td>N</td></tr>
    <tr><td>O</td></tr>
    <tr><td>P</td></tr>
    <tr><td>Q</td></tr>
    <tr><td>R</td></tr>
    <tr><td>S</td></tr>
    <tr><td>T</td></tr>
    <tr><td>U</td></tr>
    <tr><td>V</td></tr>
    <tr><td>W</td></tr>
    <tr><td>X</td></tr>
    <tr><td>Y</td></tr>
    <tr><td>Z</td></tr>
  </table>
  <table>
    <tr><td>A</td></tr>
    <tr><td>B</td></tr>
    <tr><td>C</td></tr>
  </table>
  <div></div>
</div>

【问题讨论】:

  • 看起来行位置的计算首先被执行,任何溢出顶部边缘的内容都会被忽略。很奇特。我对 flexbox 不够熟悉,无法解释为什么会发生这种情况。

标签: html css overflow flexbox


【解决方案1】:

根据HTML spec,如果没有&lt;tr&gt;元素,浏览器必须将&lt;tbody&gt;元素包裹起来:

&lt;tbody&gt; 的高度将是所有行的高度。但是,&lt;table&gt; 的高度可以更小。这在表格布局中不会成为问题,因为表格的高度将被视为最小高度。

但是,&lt;table&gt; 现在参与弹性布局,而不是表格布局。由于&lt;tbody&gt;table-row-group 元素,其父元素既不是table 也不是inline-table(它是flex),因此会生成anonymous table 父元素。

所以现在我们有了一个&lt;table&gt;,它是一个带有单条伸缩线的伸缩容器,其中包含一个伸缩项(匿名table)。

弹性线的高度将是弹性容器的高度(spec):

如果 flex 容器是 single-line 并且有明确的交叉 size, flex line 的 cross size 是 flex 容器的内部 交叉尺寸。

然后你使用align-items: center。这将垂直对齐柔性线中间的匿名table(与&lt;tbody&gt;),即使它溢出上方或下方。

问题是滚动条允许滚动查看下方溢出的内容,而不是上方溢出的内容。

因此,我建议使用aligning with auto margins,而不是align-items: center

在通过justify-contentalign-self 对齐之前, 任何正的可用空间都分配到自动边距 维度。

注意区别:自动边距仅分配可用空间,而不是负空间。

因此,我们只需要为弹性项目设置样式

margin: auto 0; /* Push to the center (vertically) */

但是有一个问题:如上所述,flex item是一个匿名生成的元素,所以我们不能用CSS选择器选择它。

为了解决这个问题,我们可以将display: block 添加到&lt;tbody&gt;。然后,它不会被包裹在任何匿名的table 元素中,因此它将是一个弹性项目并且对齐会起作用。

注意这不会破坏表格,因为&lt;tr&gt;s 的一堆,它们是table-rows,将生成一个匿名的table 父级,但现在在&lt;tbody&gt; 内:

所以你可以使用这个代码:

tbody {
  display: block; /* Disable tabular layout, and make <tbody> a flex item */
  margin: auto 0; /* Push to the center (vertically) */
}

#container {
  height: 180px;
  display: flex;
  flex-flow: row;
  align-items: stretch;
  border: 1px dashed gray;
}
table {
  display: flex;
  flex-flow: row;
  margin: 10px;
  overflow: scroll;
  border: 1px dashed blue;
}
tbody {
  display: block; /* Disable tabular layout, and make <tbody> a flex item */
  margin: auto 0; /* Push to the center (vertically) */
}
td {
  height: 10px;
  width: 100px;
  border: 1px solid red;
}
#container div {
  flex: 1;
  margin: 10px;
  border: 1px dashed red;
}
<div id="container">
  <table>
    <tbody>
      <tr><td>A</td></tr>
      <tr><td>B</td></tr>
      <tr><td>C</td></tr>
      <tr><td>D</td></tr>
      <tr><td>E</td></tr>
      <tr><td>F</td></tr>
      <tr><td>G</td></tr>
      <tr><td>H</td></tr>
      <tr><td>I</td></tr>
      <tr><td>J</td></tr>
      <tr><td>K</td></tr>
      <tr><td>L</td></tr>
      <tr><td>M</td></tr>
      <tr><td>N</td></tr>
      <tr><td>O</td></tr>
      <tr><td>P</td></tr>
      <tr><td>Q</td></tr>
      <tr><td>R</td></tr>
      <tr><td>S</td></tr>
      <tr><td>T</td></tr>
      <tr><td>U</td></tr>
      <tr><td>V</td></tr>
      <tr><td>W</td></tr>
      <tr><td>X</td></tr>
      <tr><td>Y</td></tr>
      <tr><td>Z</td></tr>
    </tbody>
  </table>
  <table>
    <tbody>
      <tr><td>A</td></tr>
      <tr><td>B</td></tr>
      <tr><td>C</td></tr>
    </tbody>
  </table>
  <div></div>
</div>

【讨论】:

  • @Oriol - 很快就会得到很好的答案。 :) 我正在尝试相同的方式,但不知何故我尝试了更多选项为 tbody 的 display 参数并花了一段时间让它工作 block 显示。
  • 注意:CSS 工作组决定改变这种行为。现在应该阻止 tbody 而不是生成匿名父级。详见this answer
【解决方案2】:

请访问-https://jsfiddle.net/3y80zqzc/1/

您将看到为tbody 新增的类。 边距参数是确保内容垂直居中位置的最重要参数。

margin: auto, 0; /*this is for vertically middle position*/
margin: 0, auto; /*this is for horizontally center position*/

您还可以查看 HTML 代码

<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta content="text/html; charset=UTF-8" http-equiv="content-type">
<style>
#container {
  height: 180px;
  display: flex;
  flex-flow: row;
  align-items: stretch;
  border: 1px dashed gray;
}

table {
  display: flex;
  flex-flow: row;
  align-items: center;
  margin: 10px;
  overflow: scroll;
  border: 1px dashed blue;
}

td {
  height: 10px;
  width: 100px;
  border: 1px solid red;
}

#container div {
  flex: 1;
  margin: 10px;
  border: 1px dashed red;
}
tbody {
  display: block;
  margin: auto 0;
}
</style>
</head>
<body>
<div id="container">
  <table>
    <tr><td>A</td></tr>
    <tr><td>B</td></tr>
    <tr><td>C</td></tr>
    <tr><td>D</td></tr>
    <tr><td>E</td></tr>
    <tr><td>F</td></tr>
    <tr><td>G</td></tr>
    <tr><td>H</td></tr>
    <tr><td>I</td></tr>
    <tr><td>J</td></tr>
    <tr><td>K</td></tr>
    <tr><td>L</td></tr>
    <tr><td>M</td></tr>
    <tr><td>N</td></tr>
    <tr><td>O</td></tr>
    <tr><td>P</td></tr>
    <tr><td>Q</td></tr>
    <tr><td>R</td></tr>
    <tr><td>S</td></tr>
    <tr><td>T</td></tr>
    <tr><td>U</td></tr>
    <tr><td>V</td></tr>
    <tr><td>W</td></tr>
    <tr><td>X</td></tr>
    <tr><td>Y</td></tr>
    <tr><td>Z</td></tr>
  </table>
  <table>
    <tr><td>A</td></tr>
    <tr><td>B</td></tr>
    <tr><td>C</td></tr>
  </table>
  <div></div>
</div>
</body>
</html>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-13
    • 2020-05-20
    • 2019-10-01
    • 1970-01-01
    • 2014-12-29
    • 1970-01-01
    • 2020-11-19
    • 1970-01-01
    相关资源
    最近更新 更多