About this set
An orders table that stays a normal table on wide screens and turns every row into a labelled card below 620 pixels. There is no JavaScript: each cell carries a data-label attribute with its column name, and inside the media query the table parts switch to display:block, the header row is hidden and each cell prints its label with content: attr(data-label) on the left and its value on the right. An 8 pixel border in the page colour separates the cards. Use this pattern when a table has five or six short columns and people will read it one record at a time on a phone, such as orders, bookings or tickets; for wide numeric tables a horizontal scroll works better. The example has an order number as the row header, customer, total, date and a coloured status pill for Shipped, Processing and Delivered. The Bootstrap version keeps .table and .badge and adds the stacking media query, since Bootstrap has no stacked table of its own; the Tailwind version expresses the same rules with max-[620px]: utilities and before:content-[attr(data-label)].
What’s included
- Rows become labelled cards below 620px with CSS only
- Column names come from data-label via content: attr()
- Order number marked up as a row header
- Status pills for Shipped, Processing and Delivered
- Bootstrap .table and Tailwind max-[620px]: variants of the same layout
Accessibility
The table is labelled by its heading, with scope on column and row headers. The status pill text and the stacked labels meet 4.5:1 contrast. Nothing is interactive, so there is no focus handling to add. Some older screen reader and browser combinations drop table semantics when table elements are set to display:block, so test with your audience's tools if the stacked view is critical.
Customise it
The breakpoint is the 620px media query (max-[620px]: in Tailwind). Colours sit on .rt: header #0f766e, card gap --rt-gap, and the .rt-ship, .rt-proc and .rt-deliv pills; Bootstrap uses --bs-table-* variables on .rt.




















