如何根据媒体查询使用 colspan/rowspan 创建不同的类似表格的布局?
Posted
技术标签:
【中文标题】如何根据媒体查询使用 colspan/rowspan 创建不同的类似表格的布局?【英文标题】:How to create different table-like layouts with colspan/rowspan based on media queries? 【发布时间】:2021-02-01 02:05:52 【问题描述】:我想在一个类似表格的布局中展示一些内容,这些内容会根据媒体查询发生变化。对于大屏幕,一些内容显示在第三个表格列中,而对于小屏幕,此内容显示在一个额外的行中。我希望代码 sn-p 能说明这一点。
在这两种情况下,我都需要单元格的宽度由最大单元格的内容来确定。我不在乎标记实际上是 <table>
还是只是一些 <div>
s。
到目前为止我发现:使用display: table
似乎不是一个选项,因为它不支持 colspan/rowspan。对于 flexbox 布局或其他基于 <div>
的方法,我只是看不到一种方法可以自动将宽度调整为文本的长度,并为一列的所有单元格提供共同的宽度。
我看到的唯一选择是将大单元格两次添加到标记中,并根据媒体查询隐藏其中一个。有没有更优雅的选择(即没有重复和没有 javascript)?
<p>layout for large screen sizes:</p>
<table border="1">
<tr><td>A1</td><td>A2</td><td rowspan="2">this is<br>the first<br>multiline cell</td></tr>
<tr><td>cell B1</td><td>this is cell B2</td></tr>
<tr><td>C1</td><td>C2</td><td rowspan="3">this is<br>the second<br>multiline cell</td></tr>
<tr><td>D1</td><td>D2</td></tr>
<tr><td>E1</td><td>E2</td></tr>
<table>
<p>layout for small screen sizes:</p>
<table border="1">
<tr><td>A1</td><td>A2</td></tr>
<tr><td>cell B1</td><td>this is cell B2</td></tr>
<tr><td colspan="2">this is<br>the first<br>multiline cell</td></tr>
<tr><td>C1</td><td>C2</td></tr>
<tr><td>D1</td><td>D2</td></tr>
<tr><td>E1</td><td>E2</td></tr>
<tr><td colspan="2">this is<br>the second<br>multiline cell</td></tr>
<table>
编辑:我注意到,在将问题简化为一个抽象的最小示例时,我未能明确哪些假设是有效的,哪些是无效的。我通过添加 E1/E2 行稍微更改了示例表。一些附加信息:
大单元格需要跨越任意数量的行。 (实际上这可能会限制在 20 个左右。) 表格中的行数不受限制,取决于内容。列布局是固定的。这是使用<div>
s 的自然标记的建议。将 col1 和 col2 视为项目列表,而每个 col3 包含有关前一组项目的更多信息。如果可能,最好不要使用col3-rowspanN
类。
<div class="table">
<div class="col1">A1</div>
<div class="col2">A2</div>
<div class="col1">cell B1</div>
<div class="col2">this is cell B2</div>
<div class="col3 col3-rowspan2">this is
<br>the first
<br>multiline cell
</div>
<div class="col1">C1</div>
<div class="col2">C2</div>
<div class="col1">D1</div>
<div class="col2">D2</div>
<div class="col1">E1</div>
<div class="col2">E2</div>
<div class="col3 col3-rowspan3">this is
<br>the second
<br>multiline cell
</div>
</div>
【问题讨论】:
嗨!我认为您最好的解决方案是使用 flex ,您可以在其中定义部分的 flex 增长。你有没有想过使用类似 bootstrap 的东西来让你更轻松? 我对 flexbox 没有太多经验,所以你能解释一下这将如何解决我的问题吗?我认为随着 flex 增长,我必须自己指定列宽的比率。但是,我需要它们像表格一样适应单元格的内容。所以现在,文本“cell B1”定义了第一列的宽度。如果文本更改为“B1”,则单元格 A1、B1、C1 和 D1 的宽度需要相应减小。 如果您想将类似表格的布局更改为汉堡布局,css 网格是更好的解决方案。在这种情况下甚至比使用 flex-boxes 更好。 【参考方案1】:首先从 CSS-Grid 而不是表格开始。要使每个“单元格”的宽度使用width: min-content;
,并且在空格后没有自动换行,请使用white-space: nowrap;
div
border: 1px solid black;
padding: 3px;
.table
display: grid;
grid-template-columns: min-content min-content min-content;
white-space: nowrap;
grid-auto-rows: auto;
grid-gap: 3px;
width: min-content;
.doubleRow
grid-row: span 2;
<p>layout for large screen sizes:</p>
<div class="table">
<div id="A1">A1</div>
<div id="A2">A2</div>
<div class="doubleRow" id="firstDouble">this is
<br>the first
<br>multiline cell
</div>
<div id="B1">cell B1</div>
<div id="B2">this is cell B2</div>
<div id="C1">C1</div>
<div id="C2">C2</div>
<div class="doubleRow" id="secondDouble">this is
<br>the second
<br>multiline cell
</div>
<div id="D1">D1</div>
<div id="D1">D2</div>
</div>
对于移动视图,您可以使用媒体查询并像这样替换网格:
div
border: 1px solid black;
padding: 3px;
.table
display: grid;
grid-template-columns: min-content min-content;
white-space: nowrap;
grid-auto-rows: auto;
grid-gap: 3px;
width: min-content;
.doubleRow
grid-column: span 2;
#A1, #A2
grid-row: 1 / 2;
#B1, #B2
grid-row: 2 / 3;
#firstDouble
grid-row: 3 / 4;
#C1, #C2
grid-row: 4 / 5;
#D1, #D2
grid-row: 5 / 6;
#secondDouble
grid-row: 6 / 7;
<p>layout for large screen sizes:</p>
<div class="table">
<div id="A1">A1</div>
<div id="A2">A2</div>
<div class="doubleRow" id="firstDouble">this is
<br>the first
<br>multiline cell
</div>
<div id="B1">cell B1</div>
<div id="B2">this is cell B2</div>
<div id="C1">C1</div>
<div id="C2">C2</div>
<div class="doubleRow" id="secondDouble">this is
<br>the second
<br>multiline cell
</div>
<div id="D1">D1</div>
<div id="D1">D2</div>
</div>
【讨论】:
这已经很有帮助了,它向我展示了如何使用网格来获得由列的最大元素定义的宽度。不幸的是,我没有明确说明哪些假设对最小示例有效。我的真实数据的行数可能比示例多得多,并且行跨度并不总是 2。请查看我更新的问题。有没有办法不用硬编码 CSS 中的表格布局就可以达到同样的效果? 你可以自动对齐项目。但是在这种情况下,位置很重要。您可以使用网格跨越任意数量的“单元格”。为此使用grid-row:
或grid-column:
,然后使用´span x;`,而x是您想要跨越的单元格数,例如grid-column: span 15;
如果您想跨越15个单元格。
另外,如果您想使用您已经熟悉的表格,请制作 2 个具有不同 ID 的表格,然后您可以为它们提供属性 display: none;
,这不会显示它们。在媒体查询中,您可以通过告诉他们display: block;
来覆盖它。这样只会显示正确的表格。【参考方案2】:
基于来自 tacoshy 的非常有用的示例,我以某种方式完成了这项工作,因此我现在正在回答我自己的问题,以防它对某人有用。我对 CSS 网格不是很熟悉,所以请随时指出潜在的改进。
我做了什么:首先,我更改了标记,让大单元格始终跟随小单元格组。这基本上使小屏幕布局变得微不足道。在大屏布局中,我使用grid-auto-flow: row dense;
使第三列自动上移。
我觉得唯一有点不雅的是我需要明确地提供行跨度。使用自定义 CSS 属性,我至少找到了一种无需为每个可能的值定义类的方法。
我仍然对垂直对齐不满意,为此我创建了a separate question。
大屏幕尺寸代码:
div
border: 1px solid black;
padding: 3px;
.table
display: grid;
grid-template-columns: min-content min-content min-content;
white-space: nowrap;
grid-auto-rows: auto;
grid-gap: 3px;
width: min-content;
grid-auto-flow: row dense;
.col1
grid-column-start: 1;
.col2
grid-column-start: 2;
.col3
grid-column-start: 3;
grid-row-end: span var(--span);
<div class="table">
<div class="col1">A1</div>
<div class="col2">A2</div>
<div class="col1">cell B1</div>
<div class="col2">this is cell B2</div>
<div class="col3" style="--span: 2;">this is<br>the first<br>multiline cell</div>
<div class="col1">C1</div>
<div class="col2">C2</div>
<div class="col1">D1</div>
<div class="col2">D2</div>
<div class="col1">E1</div>
<div class="col2">E2</div>
<div class="col3" style="--span: 3;">this is<br>the second<br>multiline cell</div>
</div>
小屏幕代码:
div
border: 1px solid black;
padding: 3px;
.table
display: grid;
grid-template-columns: min-content min-content;
white-space: nowrap;
grid-auto-rows: auto;
grid-gap: 3px;
width: min-content;
.col3
grid-column: span 2;
<div class="table">
<div class="col1">A1</div>
<div class="col2">A2</div>
<div class="col1">cell B1</div>
<div class="col2">this is cell B2</div>
<div class="col3" style="--span: 2;">this is<br>the first<br>multiline cell</div>
<div class="col1">C1</div>
<div class="col2">C2</div>
<div class="col1">D1</div>
<div class="col2">D2</div>
<div class="col1">E1</div>
<div class="col2">E2</div>
<div class="col3" style="--span: 3;">this is<br>the second<br>multiline cell</div>
</div>
【讨论】:
以上是关于如何根据媒体查询使用 colspan/rowspan 创建不同的类似表格的布局?的主要内容,如果未能解决你的问题,请参考以下文章
匹配 Bootstrap -xs、-sm 等修饰符的媒体查询? [复制]