10

我的 Web GUI 布局部分由 CSS 表驱动。这主要是因为我希望“单元格”在所有情况下都具有相同的高度,而不会在对齐方面造成任何巨大的麻烦。总的来说,这种方法非常成功。

但是,我确实有一个问题,即表格中的右侧单元格有时可能需要一些时间来呈现,导致左侧单元格短暂地具有 100% 的页面宽度。这会导致明显的“闪烁”效果,虽然很小,但有点烦人。我决定修复它。

这是我的页面如何工作的模糊表示:

#tbl      { display: table; width: 200px; border: 1px solid black; }
#tbl-row  { display: table-row; }
#tbl-col1,
#tbl-col2 { display: table-cell; }

#tbl-col1 { width: 50px; background-color: red; }
#tbl-col2 { background-color: blue; }
<div id="tbl">
    <div id="tbl-row">
        <div id="tbl-col1">LHS</div>
        <div id="tbl-col2">RHS</div>
    </div>
</div>

一切都很好,直到你使用你的开发工具给出#tbl-col2一个display: none指令,[我希望准确地]模拟浏览器渲染引擎在#tbl-col1被渲染和#tbl-col2被渲染之间的状态。

请注意#tbl-col1,尽管我给了它宽度,但它立即占据了表格宽度的 100%。我有点理解为什么会发生这种情况:毕竟,我已经要求浏览器让divs 表现得像表格一样。不过,这里还是不受欢迎的。

我试图通过插入一个“垫片”来解决这个问题,希望没有width它它会扩展以填充右侧的所有空间,直到右侧被渲染:

#tbl      { display: table; width: 200px; border: 1px solid black; }
#tbl-row  { display: table-row; }
#tbl-col1,
#tbl-spc,
#tbl-col2 { display: table-cell; }

#tbl-col1 { width: 50px;  background-color: red; }
#tbl-col2 { width: 150px; background-color: blue; }
<div id="tbl">
    <div id="tbl-row">
        <div id="tbl-col1">LHS</div>
        <div id="tbl-spc"></div>
        <div id="tbl-col2">RHS</div>
    </div>
</div>

正如您再次 hide 所看到的那样#tbl-col2,它并没有产生任何盲目的区别:#tbl-col1仍然占据了表格的整个宽度,而不是我允许的 50px。

假设我宁愿解决这个问题也不愿完全放弃 CSS 表格布局,我该怎么办?

还是我将不得不更换布局,或者更糟糕的是,采用 JavaScript 方法来解决 FoUC?

4

4 回答 4

3

在类似情况下(例如 html 电子邮件)我喜欢做的是使用空单元格以这种方式预定义列宽:

.tbl {
    display: table;
    width: 200px;
    border: 1px solid black;
    color: #fff;
}
.tbl-row {
    display: table-row;
}
.tbl-cell {
    display: table-cell;
}
.tbl-col1 {
    width: 50px;
    background-color: red;
}
.tbl-col2 {
    background-color: blue;
}
<h3>Pre-define columns width by adding additional row</h3>

<div class="tbl">
    <div class="tbl-row tbl-format">
        <div class="tbl-cell tbl-col1"></div>
        <div class="tbl-cell tbl-col2"></div>
    </div>
    <div class="tbl-row">
        <div class="tbl-cell tbl-col1">LHS</div>
        <div class="tbl-cell tbl-col2">RHS</div>
    </div>
</div>

如果单元格内没有内容,则该格式化列是不可见的,但它仍然告诉浏览器应该格式化表格的方式。

于 2015-06-27T21:45:51.363 回答
2

这是因为,默认情况下,表格使用自动表格布局

CSS 2.1 规范没有定义这种布局模式,但提出了一种(非规范的)算法,它反映了几种流行的 HTML 用户代理的行为。

根据该算法,

如果使用的宽度大于 MIN,则额外的宽度应分布在列上。

但是,它没有解释它应该如何分发事实上,您插入“spacer”元素的尝试在 Firefox 上完美运行,但在 Chrome 上却不行。

相反,您可能想尝试在规范中正确定义的固定表模式(因此更可靠),通常更快,并且也解决了问题:

在固定表格布局算法中,每列的宽度确定如下:

  1. auto具有非属性值的列元素width设置该列的宽度。
  2. 否则,第一行中具有非属性值的单元格将auto确定width该列的宽度。如果单元格跨越多列,则宽度将按列划分。
  3. 任何剩余的列均分剩余的水平表空间(减去边框或单元格间距)。

根据第 3 点,spacer 元素将在最后一个单元格加载之前接收剩余的 150px。加载后将收到剩余的 0px。

所以你需要

#tbl { table-layout: fixed; }

.tbl {
  display: table;
  table-layout: fixed;
  width: 200px;
  border: 1px solid black;
}
.tbl-row {
  display: table-row;
}
.tbl-col1,
.tbl-spc,
.tbl-col2 {
  display: table-cell;
}
.tbl-col1 {
  width: 50px;
  background-color: red;
}
.tbl-col2 {
  width: 150px;
  background-color: blue;
}
.hide {
  display: none;
}
While parsing the first cell:
<div class="tbl">
  <div class="tbl-row">
    <div class="tbl-col1">LHS</div>
    <div class="tbl-spc hide"></div>
    <div class="tbl-col2 hide">RHS</div>
  </div>
</div>

While parsing the spacer:
<div class="tbl">
  <div class="tbl-row">
    <div class="tbl-col1">LHS</div>
    <div class="tbl-spc"></div>
    <div class="tbl-col2 hide">RHS</div>
  </div>
</div>

While parsing the second cell:
<div class="tbl">
  <div class="tbl-row">
    <div class="tbl-col1">LHS</div>
    <div class="tbl-spc"></div>
    <div class="tbl-col2">RHS</div>
  </div>
</div>

但是,仍然存在一个问题:直到第一个单元格被完全解析后,才会显示分隔符。

这意味着必须首先加载垫片,但不能首先显示。遗憾的是,CSS 表格布局不允许对单元格重新排序。但它可以通过从 HTML 中删除非语义分隔符并使用::after伪元素来实现:

#tbl-row:after {
  content: '';
  display: table-cell;
}

.tbl {
  display: table;
  table-layout: fixed;
  width: 200px;
  border: 1px solid black;
}
.tbl-row {
  display: table-row;
}
.tbl-row:after {
  content: '';
  display: table-cell;
}
.tbl-col1,
.tbl-col2 {
  display: table-cell;
}
.tbl-col1 {
  width: 50px;
  background-color: red;
}
.tbl-col2 {
  width: 150px;
  background-color: blue;
}
.hide {
  display: none;
}
While parsing the first cell:
<div class="tbl">
  <div class="tbl-row">
    <div class="tbl-col1">LHS</div>
    <div class="tbl-col2 hide">RHS</div>
  </div>
</div>

While parsing the second cell:
<div class="tbl">
  <div class="tbl-row">
    <div class="tbl-col1">LHS</div>
    <div class="tbl-col2">RHS</div>
  </div>
</div>

于 2015-06-30T00:48:41.843 回答
1

这是一个合理的解决办法吗?

#tbl      { display: table; width: 200px; border: 1px solid black; }
#tbl-row  { display: flex;  }
#tbl-col1,
#tbl-spc,
#tbl-col2 {
   flex:0;
   overflow:hidden
}

#tbl-col1 { flex-basis: 50px;  background-color: red; }
#tbl-col2 { flex-basis: 150px; background-color: blue; }
<div id="tbl">
    <div id="tbl-row">
        <div id="tbl-col1">LHS-LHS-LHS-LHS</div>
        <div id="tbl-spc"></div>
        <div id="tbl-col2">RHS</div>
    </div>
</div>

编辑:

这是一个带有前缀和后备的小提琴

于 2015-06-27T21:09:16.090 回答
0

想试试这个 - JS Fiddle

.tbl{display:table;}
.fixed{width: 200px; border: 1px solid black; }
.tblRow { display: table-row; }
.tblCol{ display: table-cell; }
.col1 .tbl { width: 50px;  background-color: red; }
.col2 .tbl { width: 150px; background-color: blue; display:none; }

正如我在评论中所说,使用表格宽度。所以就在这里。display:none从样式行中删除,.col2 .tbl { width: 150px; background-color: blue; display:none; }您可以看到所有内容。这也许就是你想要的。

于 2015-06-27T21:03:52.920 回答