Skip to content
ThemesIonic — home
WooCommerce

Product Tables in WooCommerce

Grids are for browsing and tables are for ordering. If your customers already know what they want and buy twenty lines at a time, the shop archive is costing you money.

4 min read intermediate

A product grid is a browsing interface, and a lot of WooCommerce stores are not selling to browsers. Trade customers, restaurant menus, spare parts catalogues, uniform ordering and anything with a printed price list share one behaviour: the buyer arrives knowing roughly what they want and needs to place a multi-line order quickly. Making them click into twenty product pages to do it is the single most expensive layout decision such a store can make.

What core can and cannot do

WooCommerce's [products] shortcode and the product listing blocks will output any subset of your catalogue you can express as a query — by category, by IDs, on sale, best selling, sorted however you like. If your only requirement is a compact list on a landing page, that is often enough, and the product shortcodes will do it without a plugin.

What they cannot do is the part that matters for ordering:

  • No quantity field in the loop. The archive add-to-cart control adds one unit. There is no per-row quantity input, so a customer ordering twelve of something has to visit the product page or press the button twelve times.
  • No add-to-cart for variable products in the loop. Variable products render a link to their own page, because the variation form has to exist somewhere and the loop is not it.
  • No sortable, searchable columns. Archive sorting is a single dropdown applied to the whole query, not per column.
  • No arbitrary columns. SKU, weight, stock quantity, custom fields and taxonomy values are not available as columns without template work.

You can restyle a grid into rows with CSS in ten minutes. You will still be missing all four of the above, which is the honest case for a product table plugin.

What you are actually buying

Capability Why it matters
Per-row quantity input The whole point; multi-line orders in one submission
Multi-select and add several rows at once Halves the interaction count again for trade buyers
Variation handling in-row Otherwise repeat buyers still bounce to product pages
Arbitrary columns, including custom fields SKU and pack size are what B2B buyers scan for
Server-side sorting, search and pagination Determines the catalogue size you can support
Filter controls above the table Narrowing 4,000 rows to 40 before scanning

The last two are where products in this category genuinely differ, and they are the questions to ask a vendor first.

The performance question, stated plainly

There are two architectures. A client-side table renders every row into the HTML and lets JavaScript sort and paginate. It feels instant, it works offline of the server, and it collapses somewhere in the low thousands of rows because the page itself becomes enormous. A server-side table requests a page of rows at a time. It scales indefinitely and costs a round trip per sort or search.

Small trade catalogues are fine with the first. Anything approaching a full distributor catalogue needs the second, and no amount of general site speed work will rescue a page that ships four thousand rows of markup and product images. If a plugin does not tell you which model it uses, that is the answer.

Two related details: images in a table should be small thumbnails and lazily loaded, and any table that loads a very large dataset must not be inside a full-page cache that has to be regenerated on every price change.

Getting the data right first

Tables expose your product data honestly, which is uncomfortable. Empty SKUs, inconsistent pack sizes and missing stock quantities are invisible in a grid of pictures and glaring in a column. Fixing that in bulk through the CSV importer before launching a table is faster than editing products afterwards, and it will surface the attribute problems that also block product filtering.

If most rows are variations, decide early whether each variation gets a row. It usually should for repeat purchasing, and that decision changes how you structure product variations — a variation buyers search for by code deserves its own SKU and its own row.

Accessibility and mobile, which are the same problem

A table with real table markup is navigable by screen readers and understood by keyboard users, provided headers are marked up as headers. Tables built from nested divs are not. Ask, or view the source.

On phones there are only two honest options: scroll the table horizontally inside its own container, or collapse each row into a stacked card that keeps the quantity field. Both are acceptable. Squeezing eight columns into 360 pixels is not, and it is what most implementations do by default.

The decision

Use a table when the customer knows what they want, buys multiple lines, or needs to compare specifications rather than photographs. Keep the grid when discovery is the job. Many stores should have both — an ordinary shop for retail visitors and a table-based order form for trade accounts — and that is a configuration choice, not a compromise.

Frequently asked

Not as a real order form. Core shortcodes and product blocks output a grid of cards, and CSS can restyle that grid into rows, but the loop's add-to-cart control has no quantity field and variable products only link through to their own page.
Either the row expands into variation dropdowns, or each variation gets its own row. Separate rows are better for repeat buyers who know their SKU, dropdowns are better for a small number of options, and any plugin worth buying supports both.
It depends entirely on whether sorting, searching and pagination happen in the browser or on the server. Client-side tables load every row into the page and become unusable in the low thousands; server-side tables stay fast but need a request per interaction.

Related guides