Responsive Table

Table adapted to narrow screens.

ProductQtyPrice
Wireless mouse 2 £18.00

280px — rows stack into labelled fields below the container's threshold

html

<div class="rsp-rt-viewport" data-labels="true">
  <div class="rsp-rt-container" style="width:280px;">
    <div class="rsp-rt-table">
      <div class="rsp-rt-head"><span>Product</span><span>Qty</span><span>Price</span></div>
      <div class="rsp-rt-row">
        <span class="rsp-rt-cell" data-label="Product: " style="border-left-color:#D9C8F0;">Wireless mouse</span>
        <span class="rsp-rt-cell" data-label="Qty: ">2</span>
        <span class="rsp-rt-cell" data-label="Price: ">&pound;18.00</span>
      </div>
    </div>
  </div>
  <p class="rsp-rt-caption">280px &mdash; rows stack into labelled fields below the container's threshold</p>
</div>
<style>
.rsp-rt-viewport { width: 100%; max-width: 660px; }
.rsp-rt-container { container-type: inline-size; max-width: 100%; background: #FAF7F2; border: 1px solid #24143022; border-radius: 12px; padding: 4px; box-sizing: border-box; }
.rsp-rt-head { display: none; }
.rsp-rt-row { display: flex; flex-direction: column; padding: 10px; font: 13px system-ui, sans-serif; color: #241430; background: #fff; border-radius: 8px; }
.rsp-rt-cell { padding: 3px 0; border-left: 3px solid transparent; padding-left: 8px; }
[data-labels="true"] .rsp-rt-cell::before { content: attr(data-label); font-weight: 700; }
@container (min-width: 380px) {
  .rsp-rt-head { display: flex; justify-content: space-between; padding: 8px 10px; font: 700 11px system-ui, sans-serif; color: #241430aa; text-transform: uppercase; }
  .rsp-rt-row { flex-direction: row; justify-content: space-between; }
  .rsp-rt-cell { border-left: none; padding-left: 0; }
  .rsp-rt-cell::before { content: none !important; }
}
.rsp-rt-caption { margin: 8px 0 0; font: 11px system-ui, sans-serif; color: #241430aa; }
</style>

tailwind

<div class="w-full max-w-[660px]" data-labels="true">
  <div class="tw-rt-container max-w-full bg-[#FAF7F2] border border-[#24143022] rounded-xl p-1 box-border" style="width:280px; container-type:inline-size;">
    <div class="tw-rt-head hidden justify-between px-2.5 py-2 font-bold text-[11px] uppercase text-[#241430]/70"><span>Product</span><span>Qty</span><span>Price</span></div>
    <div class="tw-rt-row flex flex-col p-2.5 font-sans text-sm text-[#241430] bg-white rounded-lg">
      <span class="tw-rt-cell pl-2 border-l-[3px]" data-label="Product: " style="border-left-color:#D9C8F0;">Wireless mouse</span>
      <span class="tw-rt-cell pl-2 border-l-[3px] border-transparent" data-label="Qty: ">2</span>
      <span class="tw-rt-cell pl-2 border-l-[3px] border-transparent" data-label="Price: ">&pound;18.00</span>
    </div>
  </div>
  <p class="mt-2 text-[11px] text-[#241430]/70">280px &mdash; rows stack into labelled fields below the container's threshold</p>
</div>
<style>
[data-labels="true"] .tw-rt-cell::before { content: attr(data-label); font-weight: 700; }
@container (min-width: 380px) {
  .tw-rt-head { display: flex; }
  .tw-rt-row { flex-direction: row; justify-content: space-between; }
  .tw-rt-cell { border-left: none !important; padding-left: 0 !important; }
  .tw-rt-cell::before { content: none !important; }
}
</style>

react

export function ResponsiveTable({
  width = 280,
  showLabels = true,
  productName = "Wireless mouse",
  accent = "#D9C8F0",
}) {
  const cellLabel = (text) => showLabels ? `${text}` : "";
  return (
    <div style={{ width: "100%", maxWidth: 660 }}>
      <div style={{ width, maxWidth: "100%", containerType: "inline-size", background: "#FAF7F2", border: "1px solid #24143022", borderRadius: 12, padding: 4, boxSizing: "border-box" }}>
        <div className="head" style={{ display: "none", justifyContent: "space-between", padding: "8px 10px", fontWeight: 700, fontSize: 11, color: "#241430aa", textTransform: "uppercase" }}>
          <span>Product</span><span>Qty</span><span>Price</span>
        </div>
        <div className="row" style={{ display: "flex", flexDirection: "column", padding: 10, fontFamily: "system-ui, sans-serif", fontSize: 13, color: "#241430", background: "#fff", borderRadius: 8 }}>
          <span style={{ paddingLeft: 8, borderLeft: `3px solid ${accent}` }}>{cellLabel("Product: ")}{productName}</span>
          <span style={{ paddingLeft: 8, borderLeft: "3px solid transparent" }}>{cellLabel("Qty: ")}2</span>
          <span style={{ paddingLeft: 8, borderLeft: "3px solid transparent" }}>{cellLabel("Price: ")}&pound;18.00</span>
        </div>
      </div>
      <p style={{ margin: "8px 0 0", fontSize: 11, color: "#241430aa" }}>{width}px &mdash; rows stack into labelled fields below the container's threshold</p>
      <style>{`
        @container (min-width: 380px) {
          .head { display: flex !important; }
          .row { flex-direction: row; justify-content: space-between; }
        }
      `}</style>
    </div>
  );
}