Issue
I have HTML that looks a bit like this
<html><body><table>
<thead><tr><th>A</th><th>B</th><th>C</th><th>D</th><th>E</th></tr></thead>
<tbody>
<tr><td>1A</td><td>1B</td><td>1C</td><td>1D</td><td>1E</td></tr>
<tr><td>2A</td><td>2B</td><td>2C</td><td>2D</td><td>2E</td></tr>
<tr><td>3A</td><td>3B</td><td>3C</td><td>3D</td><td>3E</td></tr>
</tbody>
</table></body></html>
Each row represents an object, and the columns are its properties. The cell values are rather longer in reality – sometimes even 20–30 characters long. It renders fine on most devices, but can be problematic on smaller phones. I know I can suppress certain columns on narrow devices, but that doesn’t feel right in this particular instance. Currently I have x-overflow: scroll
on the table, but I would prefer to have some CSS that causes the table to render more like this on narrow devices:
A: 1A
B: 1B
C: 1C
D: 1D
E: 1E
-----
A: 2A
B: 2B
C: 2C
D: 2D
E: 2E
-----
(etc)
I understand how to test for device width, so for the purpose of this question, let’s assume I want to do this unconditionally. Changing the HTML markup a bit is okay, e.g. to add extra classes or attributes, though I’d like to keep it using a <table>
element with one <tr>
per logical row. This is for backwards compatibility as I know quite a few users scrape the site (despite the existence of a much cleaner API). Due to internal politics, I’d prefer to avoid a solution that requires Javascript, if possible (and in any case, I know how to write a JS solution if need be).
I can get part way there with this, but I’m not sure how to start with the field names which are just hardcoded to ‘X’ here:
thead { display: none; }
table, tr, td { display: block; }
tr + tr { border-top: thin solid black; }
td::before { content: "X:"; display: inline-block; width: 2em; }
I’ve seen lots of sites do this sort of thing, but at the moment I’m struggling to find one that does it in CSS. It seems like it should be a frequently asked question, but I’m struggling to know what terms to search for, so may be missing some good explanations, here or elsewhere.
Solution
You're almost there. Might use e.g. data-col
attributes on <td>
elements and refer them in CSS content
on :before
thead {
display: none;
}
table,
tr,
td {
display: block;
}
tr+tr {
border-top: thin solid black;
}
td::before {
content: attr(data-col)':';
display: inline-block;
width: 2em;
}
<table>
<thead>
<tr>
<th>A</th>
<th>B</th>
<th>C</th>
<th>D</th>
<th>E</th>
</tr>
</thead>
<tbody>
<tr>
<td data-col="A">1A</td>
<td data-col="B">1B</td>
<td data-col="C">1C</td>
<td data-col="D">1D</td>
<td data-col="E">1E</td>
</tr>
<tr>
<td data-col="A">2A</td>
<td data-col="B">2B</td>
<td data-col="C">2C</td>
<td data-col="D">2D</td>
<td data-col="E">2E</td>
</tr>
<tr>
<td data-col="A">3A</td>
<td data-col="B">3B</td>
<td data-col="C">3C</td>
<td data-col="D">3D</td>
<td data-col="E">3E</td>
</tr>
</tbody>
</table>
Another approach using CSS variables to store cols, less repetitive, so may save you some bytes on longer tables:
thead {
display: none;
}
table,
tr,
td {
display: block;
}
tr+tr {
border-top: thin solid black;
}
td:before {
display: inline-block;
width: 2em;
}
td:nth-child(1):before {
content: var(--col1)':';
}
td:nth-child(2):before {
content: var(--col2)':';
}
td:nth-child(3):before {
content: var(--col3)':';
}
td:nth-child(4):before {
content: var(--col4)':';
}
td:nth-child(5):before {
content: var(--col5)':';
}
<table style="--col1:'A'; --col2:'B'; --col3:'C'; --col4:'D'; --col5:'E'">
<thead>
<tr>
<th>A</th>
<th>B</th>
<th>C</th>
<th>D</th>
<th>E</th>
</tr>
</thead>
<tbody>
<tr>
<td>1A</td>
<td>1B</td>
<td>1C</td>
<td>1D</td>
<td>1E</td>
</tr>
<tr>
<td>2A</td>
<td>2B</td>
<td>2C</td>
<td>2D</td>
<td>2E</td>
</tr>
<tr>
<td>3A</td>
<td>3B</td>
<td>3C</td>
<td>3D</td>
<td>3E</td>
</tr>
</tbody>
</table>
Answered By - Kosh
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.