如何根据媒体查询使用 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 个左右。) 表格中的行数不受限制,取决于内容。列布局是固定的。

这是使用&lt;div&gt;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 媒体查询断点的类?

匹配 Bootstrap -xs、-sm 等修饰符的媒体查询? [复制]

根据屏幕大小/媒体查询更改 Bootstrap 列类属性

如果存在媒体查询,则 SVG 掩码不起作用

如何让 Wordpress 在 CSS 中读取我的媒体查询?

针对不同媒体查询的不同 CSS 文件