Nic*_*ick 15 html javascript css jquery html-table
我正在尝试在表行中嵌套表,同时保持单个表的外观,如下面的示例所示(一个表包含一行数据值和两个嵌套表,一个是2x2,另一个是3x3):
这只是一个例子; 实际的表有更多的行和列.我想使用表,因为列宽和行高的自然回流以适应表数据而不必担心容器大小(即表宽度= 100%).
我遇到的问题是最高的表设置行高,但其他表不会扩展以填充该高度,因此内部边框不会从上到下拉伸,如此片段的结果所示:
.display {
border-collapse: collapse;
}
.display, .display td, .display th {
border: 1px solid black;
}
.subtable {
border-collapse: collapse;
}
.subtable td {
border-top: 0;
border-bottom: 1px solid black;
border-left: 0;
border-right: 1px solid black;
}
.subtable tr td:last-of-type {
border-top: 0;
border-bottom: 1px solid black;
border-left: 0;
border-right: 0;
}
.subtable tr:last-of-type td {
border-top: 0;
border-bottom: 0;
border-left: 0;
border-right: 1px solid black;
}
.subtable tr:last-of-type td:last-of-type {
border: 0;
}
td {
padding: 5px;
}
td.d-subtable {
padding: 0;
}Run Code Online (Sandbox Code Playgroud)
<table class="display" cellpadding="0">
<tr><th>Customer</th><th>Items</th><th>Payments</th></tr>
<tr><td>Customer Name</td>
<td class="d-subtable"><table class="subtable" cellpadding="0"><tr><td>Item1</td><td>5</td><td>$400.00</td></tr><tr><td>Item2</td><td>10</td><td>$200.00</td></tr><tr><td>Item3</td><td>2</td><td>$500.00</td></tr></table></td>
<td class="d-subtable"><table class="subtable" cellpadding="0"><tr><td>12 Sep 2018</td><td>$3,000.00</td></tr><tr><td>18 Sep 2018</td><td>$2,000.00</td></tr></table></td>
</tr>
</table>Run Code Online (Sandbox Code Playgroud)
现在我知道我可以使用rowspan来解决这个问题(这就是我目前正在解决问题的方法)但是这需要事先决定哪些行排成一行,这可能会导致问题,例如下面代码片段生成的问题,它在哪里如果我rowspan="2"用2行应用于表的第一行(而不是最后一行),那显然会更好:
td {
border: 1px solid black;
}
table {
border-collapse: collapse;
width: 500px;
}Run Code Online (Sandbox Code Playgroud)
<table cellpadding="5">
<tr><td rowspan="3">x</td>
<td>problem when you have some really long text in the first row</td><td>p</td><td>a</td><td>b</td><td>c</td></tr><tr><td rowspan="2">z</td><td rowspan="2">q</td><td>d</td><td>e</td><td>f</td></tr><tr><td>g</td><td>some other really long text</td><td>i</td>
</tr>
</table>Run Code Online (Sandbox Code Playgroud)
我希望上面的表格看起来像这样:
有没有办法用HTML/CSS实现我想要的东西?表中有很多行,所以我更喜欢浏览器在渲染之前对其进行排序.但是,如果不可能,我会接受Javascript/JQuery解决方案.
更新
虽然我当时找到了一个可行的解决方案(请参阅我发布的答案),但我遇到了一些情况,因为无法预测所有可能的数据,因此事先设置列的宽度(即使是百分比)也很困难.显示.所以我希望找到一个不依赖于这样做的答案.
由于我没有像我应该那样清楚,我有多行我想要嵌套表,保持高度匹配以及列宽.例如,对于两行,我希望能够创建这样的布局:
使用原始表HTML的结果如下所示:
.display {
border-collapse: collapse;
}
.display, .display td, .display th {
border: 1px solid black;
}
.subtable {
border-collapse: collapse;
}
.subtable td {
border-top: 0;
border-bottom: 1px solid black;
border-left: 0;
border-right: 1px solid black;
}
.subtable tr td:last-of-type {
border-top: 0;
border-bottom: 1px solid black;
border-left: 0;
border-right: 0;
}
.subtable tr:last-of-type td {
border-top: 0;
border-bottom: 0;
border-left: 0;
border-right: 1px solid black;
}
.subtable tr:last-of-type td:last-of-type {
border: 0;
}
td {
padding: 5px;
}
td.d-subtable {
padding: 0;
}Run Code Online (Sandbox Code Playgroud)
<table class="display" cellpadding="0">
<tr><th>Customer</th><th>Items</th><th>Payments</th></tr>
<tr><td>Customer 1</td>
<td class="d-subtable"><table class="subtable" cellpadding="0"><tr><td>Item1</td><td>5</td><td>$400.00</td></tr><tr><td>Item2</td><td>100</td><td>$20.00</td></tr><tr><td>Item3</td><td>2</td><td>$500.00</td></tr></table></td>
<td class="d-subtable"><table class="subtable" cellpadding="0"><tr><td>12 Sep 2018</td><td>$3,000.00</td></tr><tr><td>18 Sep 2018</td><td>$2,000.00</td></tr></table></td>
</tr>
<tr><td>Customer 304</td>
<td class="d-subtable"><table class="subtable" cellpadding="0"><tr><td>Item4</td><td>5</td><td>$6.00</td></tr></table></td>
<td class="d-subtable"><table class="subtable" cellpadding="0"><tr><td>20 Sep 2018</td><td>$4.00</td></tr><tr><td>27 Sep 2018</td><td>$26.00</td></tr></table></td>
</tr>
</table>Run Code Online (Sandbox Code Playgroud)
gui*_*ero 10
我建议使用flex来满足你的需求.Flex对于这种布局非常强大,因为我们可以轻松地让内容引导它.请参阅随附的片段.它纯粹由HTML和CSS制成.没有固定的大小,也不需要Javascript.
(旧片段)
.outer {
display: flex;
flex-wrap: wrap;
/* For demo purposes */
max-width: 500px;
margin: 20px auto;
border-left: 1px solid black;
border-top: 1px solid black;
}
.column {
flex: 1 1 auto;
display: flex;
flex-direction: column;
flex-wrap: wrap;
}
.row {
display: flex;
flex-direction: row;
flex: 1 1 auto;
}
.inner {
flex: 1 1 auto;
display: flex;
flex-direction: column;
}
.item {
border-right: 1px solid black;
border-bottom: 1px solid black;
text-align: center;
padding: 3px;
}
.item.heading {
font-weight: bold;
}
.item:not(.heading) {
flex: 1 1 auto;
justify-content: center;
align-items: center;
display: flex;
}
.fixed .narrow {
flex-basis: 20px;
}Run Code Online (Sandbox Code Playgroud)
<div class="outer">
<div class="column">
<div class="item heading">Customer</div>
<div class="item">
<span>Customer Name</span>
</div>
</div>
<div class="column">
<div class="item heading">Items</div>
<div class="inner fixed">
<div class="row">
<div class="item">Item1</div>
<div class="item narrow">5</div>
<div class="item last">$400.00</div>
</div>
<div class="row">
<div class="item">Item2</div>
<div class="item narrow">10</div>
<div class="item last">$200.00</div>
</div>
<div class="row">
<div class="item">Item3</div>
<div class="item narrow">2</div>
<div class="item last">$500.00</div>
</div>
</div>
</div>
<div class="column">
<div class="item heading">Payments</div>
<div class="inner">
<div class="row">
<div class="item">12 sep 2018</div>
<div class="item">$3,000.00</div>
</div>
<div class="row">
<div class="item">
18 sep 2018
</div>
<div class="item">
$2,000.00
</div>
</div>
</div>
</div>
</div>Run Code Online (Sandbox Code Playgroud)
更新:根据您的评论/答案进行更改.这在某种程度上取决于您的HTML结构.我不得不将标题移动到它自己的" .row.row-item",因此需要设置一个flex-basis来对齐列.这可以用多个" .row.row-item" 来扩展.请参阅下面的代码段.
.outer {
display: flex;
flex-wrap: wrap;
/* For demo purposes */
max-width: 600px;
margin: 20px auto;
border-left: 1px solid black;
border-top: 1px solid black;
}
.column {
flex: 1 1 33.33%;
display: flex;
flex-direction: column;
flex-wrap: wrap;
}
.row {
display: flex;
flex-direction: row;
flex: 1 1 auto;
}
.row-item {
flex-basis: 100%;
}
.inner {
flex: 1 1 auto;
display: flex;
flex-direction: column;
}
.item {
border-right: 1px solid black;
border-bottom: 1px solid black;
text-align: center;
}
.item.heading {
font-weight: bold;
flex: 1 1 33.33%;
}
.item:not(.heading) {
flex: 1 1 33.33%;
justify-content: center;
align-items: center;
display: flex;
}
.fixed .narrow {
flex: 1 1 20px;
}Run Code Online (Sandbox Code Playgroud)
<div class="outer">
<div class="row row-item">
<div class="item heading">Customer</div>
<div class="item heading">Items</div>
<div class="item heading">Payments</div>
</div>
<div class="row row-item">
<div class="column">
<div class="item">
<span>Customer 1</span>
</div>
</div>
<div class="column">
<div class="inner fixed">
<div class="row">
<div class="item">Item1</div>
<div class="item narrow">5</div>
<div class="item last">$400.00</div>
</div>
<div class="row">
<div class="item">Item2</div>
<div class="item narrow">10</div>
<div class="item last">$200.00</div>
</div>
<div class="row">
<div class="item">Item3</div>
<div class="item narrow">2</div>
<div class="item last">$500.00</div>
</div>
</div>
</div>
<div class="column">
<div class="inner">
<div class="row">
<div class="item">12 sep 2018</div>
<div class="item">$3,000.00</div>
</div>
<div class="row">
<div class="item">
18 sep 2018
</div>
<div class="item">
$2,000.00
</div>
</div>
</div>
</div>
</div>
<div class="row row-item">
<div class="column">
<div class="item">
<span>Customer 304</span>
</div>
</div>
<div class="column">
<div class="inner fixed">
<div class="row">
<div class="item">Item4</div>
<div class="item narrow">5</div>
<div class="item last">$6.00</div>
</div>
</div>
</div>
<div class="column">
<div class="inner">
<div class="row">
<div class="item">20 sep 2018</div>
<div class="item">$4.00</div>
</div>
<div class="row">
<div class="item">
27 sep 2018
</div>
<div class="item">
$26.00
</div>
</div>
</div>
</div>
</div>
<div class="row row-item">
<div class="column">
<div class="item">
<span>Customer 605</span>
</div>
</div>
<div class="column">
<div class="inner fixed">
<div class="row">
<div class="item">Item5</div>
<div class="item narrow">50</div>
<div class="item last">$60.00</div>
</div>
<div class="row">
<div class="item">Item6</div>
<div class="item narrow">3</div>
<div class="item last">$260.00</div>
</div>
</div>
</div>
<div class="column">
<div class="inner">
<div class="row">
<div class="item">29 sep 2018</div>
<div class="item">$40.00</div>
</div>
<div class="row">
<div class="item">
30 sep 2018
</div>
<div class="item">
$206.00
</div>
</div>
</div>
</div>
</div>
</div>Run Code Online (Sandbox Code Playgroud)
我最终能够通过编写一个onload函数来找到给定行中所有嵌套表的最大高度,然后将该行中每个嵌套表的高度设置为相同的值来解决这个问题.
window.onload=function () {
let rows = document.querySelectorAll('tr');
for (let r = 0; r < rows.length; r++) {
let subtables = rows[r].querySelectorAll('.subtable');
let maxHeight = 0;
for (let i = 0; i < subtables.length; i++) {
maxHeight = Math.max(maxHeight, subtables[i].clientHeight);
}
for (let i = 0; i < subtables.length; i++) subtables[i].style.height='' + maxHeight + 'px';
}
};
Run Code Online (Sandbox Code Playgroud)
这个解决方案的唯一缺点是它意味着我必须<td>在嵌套表中为s 分配宽度.但是,由于我可以使用百分比宽度,这对我来说不是一个大问题:
<table class="display" cellpadding="0">
<tr><th>Customer</th><th>Items</th><th>Payments</th></tr>
<tr><td>Customer 1</td>
<td class="d-subtable"><table class="subtable" cellpadding="0"><tr><td width="35%">Item1</td><td width="20%">5</td><td width="45%">$400.00</td></tr><tr><td>Item2</td><td>10</td><td>$200.00</td></tr><tr><td>Item3</td><td>2</td><td>$500.00</td></tr></table></td>
<td class="d-subtable"><table class="subtable" cellpadding="0"><tr><td width="60%">12 Sep 2018</td><td width="40%">$3,000.00</td></tr><tr><td>18 Sep 2018</td><td>$2,000.00</td></tr></table></td>
</tr>
<tr><td>Customer 2</td>
<td class="d-subtable"><table class="subtable" cellpadding="0"><tr><td width="35%">Item4</td><td width="20%">5</td><td width="45%">$600.00</td></tr></table></td>
<td class="d-subtable"><table class="subtable" cellpadding="0"><tr><td width="60%">20 Sep 2018</td><td width="40%">$4,000.00</td></tr><tr><td>27 Sep 2018</td><td>$2,000.00</td></tr></table></td>
</tr>
</table>
Run Code Online (Sandbox Code Playgroud)
最终输出:
这是一个 JavaScript 解决方案,它自动设置行高和列宽(不需要指定列宽),并支持调整大小。
完整的解决方案/演示在这里: http: //jsfiddle.net/ez0jqc1L/
<td>需要注意的是,这要求您将所有单元格的内容包装起来<div class="content"></div>(请参阅 jsfiddle 的示例)。
首先,我们修复子表的高度:
let tbody = /* the tbody of the <table> containing subtables we are fixing */;
for(let r = 0; r < tbody.children.length; r++) {
let row = tbody.children[r];
let subtables = row.querySelectorAll('.subtable');
let maxHeight = 0;
for(let i = 0; i < subtables.length; i++) {
maxHeight = Math.max(maxHeight, subtables[i].clientHeight);
}
for(let i = 0; i < subtables.length; i++) {
subtables[i].style.height = maxHeight + 'px';
}
}
Run Code Online (Sandbox Code Playgroud)
然后,我们迭代所有子表列以计算每组垂直相邻单元格的最大宽度(我们将其存储到数组中maxColWidths,数组的每个索引对应于垂直相邻单元格的集合):
let forEachSubtableColumn = function(f) {
for(let r = 0; r < tbody.children.length; r++) {
let row = tbody.children[r];
let subtables = row.querySelectorAll('.subtable');
let c = 0;
for(let i = 0; i < subtables.length; i++) {
let subtable = subtables[i];
if(subtable.children.length === 0 || subtable.children[0].children.length === 0) {
continue;
}
let stbody = subtable.children[0];
for(let j = 0; j < stbody.children.length; j++) {
let srow = stbody.children[j];
for(let k = 0; k < srow.children.length; k++) {
let td = srow.children[k];
f(c + k, td);
}
}
c += stbody.children[0].children.length;
}
}
};
let maxColWidths = [];
forEachSubtableColumn(function(c, td) {
if(c >= maxColWidths.length) {
maxColWidths.push(td.children[0].clientWidth);
} else {
maxColWidths[c] = Math.max(td.children[0].clientWidth, maxColWidths[c]);
}
});
Run Code Online (Sandbox Code Playgroud)
最后,我们设置列宽。这是<div class="content">需要换行的地方,因为设置 a 的宽度<td>并不能保证浏览器将使其达到精确的宽度,但我可以通过具有display: inline-block.
forEachSubtableColumn(function(c, td) {
td.children[0].style.width = maxColWidths[c] + 'px';
});
Run Code Online (Sandbox Code Playgroud)
为了调整支持大小,我们清除所有强制的宽度和高度,以便之后可以重新计算它们:
onresize = function() {
let tables = document.querySelectorAll('.subtable');
for(let i = 0; i < tables.length; i++) {
let table = tables[i];
table.style.removeProperty('height');
}
let tds = document.querySelectorAll('.subtable td');
for(let i = 0; i < tds.length; i++) {
let td = tds[i];
td.children[0].style.removeProperty('width');
}
updateTables();
};
Run Code Online (Sandbox Code Playgroud)
编辑:更正了onresize代码。
| 归档时间: |
|
| 查看次数: |
1466 次 |
| 最近记录: |