When the table is not a table tag

How to capture DIV grids, ARIA grids, iframe tables, and open Shadow DOM layouts in Chrome, then export rows that actually line up.

Agenbola108 Editorial 7 min read
When the table is not a table tag

When the table is not a table tag

I lost an afternoon once trying to copy a “table” that was not a table. The page looked like a spreadsheet. It had sticky headers and zebra stripes. The markup was a stack of divs with display: grid and a row of role="row" children. Selecting the block and pasting into Excel gave me a poem.

That pattern is now normal. Front-end teams like grids they can animate. Design systems ship ARIA grids for accessibility. Admin products bury the real data in an iframe so the shell can stay in React while the grid stays in an older app. Open Shadow DOM shows up in web components that render their own cells.

If your extractor only looks for <table>, it will miss the pages you actually use at work.

How to recognise the fake table

View source is the wrong move on a hydrated app. Use the inspector.

A real HTML table has table, thead, tr, td. You can still have a bad time with those, but at least the structure is old and well understood.

A DIV grid often looks like this:

<div class="grid">
  <div class="row">
    <div class="cell">SKU-104</div>
    <div class="cell">12.50</div>
  </div>
</div>

An ARIA grid uses role="grid", role="row", role="gridcell". Screen readers understand it. Your clipboard does not.

An iframe table is a full document inside a frame. The parent page’s selection never reaches those cells.

Open Shadow DOM hides the cells behind a shadow root. If the root is open, a script can still read it. If it is closed, you are stuck unless the component exposes the data another way.

Why copy-paste fails on these layouts

The clipboard gets rendered text plus whatever HTML the browser thinks you selected. For a DIV grid, that HTML is a pile of generic containers. Excel tries to infer columns from tabs and line breaks. There are no tabs. Every cell becomes a new line, or worse, two cells share a line because the CSS put them side by side.

ARIA grids add presentation-only nodes: sort buttons, resize handles, a “selected” outline. Those nodes become empty columns.

Iframes fail earlier. You cannot select across the frame boundary in a way that preserves a grid.

What a serious extractor has to scan

I want one tool that checks more than one structure on the same page:

  • HTML tables
  • repeating DIV layouts
  • ARIA grids
  • tables nested in iframes
  • tables inside open Shadow DOM roots

Then I want to pick the match from a list, because a page can contain all of the above. Cookie banners have been detected as tables. So have footer link groups.

Table Capture Chrome is the extension I point people at for this mix. It is built for awkward tables, not only the textbook <table> demo. After detection you still get Table Studio, so a DIV grid that came out one column short can be repaired before export.

Iframes are their own sport

Embedded dashboards are the usual case. The company bought a BI tool, dropped it into the intranet with an iframe, and now the “official export” button is either missing or produces a PDF.

I capture from the frame, not the shell. If the first scan only finds the navigation table, I look at the other detected sources. Nested frames happen. I have seen a grid inside a frame inside a tabset.

Cell range mode helps when the iframe also contains a mini summary table above the real one. Drag the real one. Ignore the sparkline toy.

DIV grids and the repeated card problem

Some “tables” are cards in a responsive grid. On a wide screen they look like rows. On a narrow screen they wrap. An extractor that assumes a fixed column count will invent empty cells on the wrapped layout.

I widen the window before I capture. It sounds daft. It works. The DOM still has the same nodes, but some layouts omit nodes at small breakpoints.

If each card has a different number of fields, I do not expect a perfect rectangle. I capture, then delete the sparse columns that only exist on “featured” cards.

Shadow DOM without the lecture

I am not going to explain web components from first principles. The practical bit: if the grid lives in an open shadow root, a page-level table scanner that ignores shadow roots will report zero tables. You will think the page has no data. It has data. The component just ate it.

When the capture list suddenly shows a table after a refresh, it is often because the component finished rendering. Capture too early and you get skeletons: grey bars that become empty cells.

After you finally have rows

Treat the result like any other dirty extract.

Check the header. Card layouts often have no header row. I add one in Table Studio (Name, Region, Price) so the CSV is not a mystery tomorrow.

Check types. ARIA grids love to put icons in the first column. Those become junk or a URL.

Export XLSX or CSV depending on the audience. I use JSON when the card was really an object and the grid was a coincidence.

A note on pages that fight you on purpose

Some sites virtualise rows. Only the visible slice exists in the DOM. Capturing that slice is honest. Capturing “the whole table” is a fantasy unless you scroll and recapture, or use a pager.

Some sites render the grid in a canvas. There are no cells to read. You are looking at pixels. Stop. Use the site’s export if it has one, or retype the ten rows you actually need.

The goal is not to win a fight with a front-end framework. The goal is a rectangle of data you can trust. Once the tool can see DIV, ARIA, iframe, and open shadow roots, most of the modern “tables” become ordinary again.

Role attributes that lie

role="table" on a layout wrapper is a gift and a trap. The extractor may find it. The “cells” may be whole sections. I look at the first captured row. If it contains a paragraph of marketing copy, I picked the wrapper, not the grid.

role="list" styled as a table is common on mobile. I switch to a desktop width and recapture. The list items often become rows with a single cell. That is honest. I then decide if I need to split the cell on a delimiter.

Detection lists save embarrassment

A page can contain five “tables”: cookie banner, nav, the real grid, a related-items widget, and a footer of link columns. I pick from a list. I do not assume the largest rectangle is the right one. The footer can be huge.

If two detections look similar, I capture both to the editor and compare a known value. The wrong one is usually missing a column I can name from memory.

When I write a tiny selector note

For a page I will visit again, I write one line: “second detection, DIV grid, ignore the iframe on the right”. That line is worth more than a screenshot. The screenshot goes stale when the brand colour changes. The detection order usually survives.

Markup fashion will keep moving. Extractors that only honour <table> are already late. The useful ones treat a table as a repeating rectangle, whatever tag started it.