Sortable, searchable, paginated data tables for HubSpot. Column data types, sticky headers, a sticky first column, and a stacked card layout on small screens. Sorting runs on the column data type, so numbers and dates order by value. Every colour, size and radius comes from a field.
Financial year 2026
The region column stays put while you scroll sideways, so you never lose track of which row you are reading. Owner is fixed order — a column can opt out of sorting.
40 territories
No territories match that search
Clear the field to see every territory again.
Accounts receivable
A hundred and twenty four rows, kept readable: banded rows, a tighter row height, a header that follows you down the page, and a search that filters as you type.
124 invoices
Nothing matches that search
Clear the field to bring the register back.
Scroll sideways for the balance and the paid flag
Production
Loads twelve at a time rather than paging. Build numbers sit in badges, service names link through, and on a phone each row becomes its own card.
43 services
No services match
Reset the filter to list them all again.
Renewals
Ruled columns and a totals line under the table. On a phone this one scrolls sideways instead of stacking, so the shape of the table survives.
36 contracts
No contracts match that search
Clear the field to see the whole register.
Annual values are the contracted figure at the last renewal.
Data Table Pro turns rows and columns entered in the page editor into a table that sorts, searches, pages and reflows. Columns are defined once and carry their own header, alignment, width and data type. Rows reference those columns by position.
Each column sets a header, a data type, an alignment, a width and an optional prefix and suffix.
Mar 14, 2027 and 2027-03-14 both work.Cells, so the tick and the cross are yours to choose along with their colour and size. The four tables above each use a different pair.Leaving a no blank. Cells › Show An Icon For No switches the second mark off, so the column reads as a list of ticks with nothing beside the rest. That suits a feature comparison, where the absence is the point. It reads as missing data in a table of records, so the demos above all keep both marks — turn it on only where an empty cell is obviously deliberate. The value still reaches a screen reader either way.
Width accepts narrow, auto or wide. The first column takes its width from
Table Shell › First Column Width so the pinned column stays a fixed size.
Every cell holds a value, an optional link and an emphasis setting. Emphasis switches between plain, strong, muted, badge and status pill. A cell with a link renders as an underlined anchor in the link colour.
Setting a cell's emphasis to status pill renders it as a coloured dot followed by the label.
Status Pills › Status Colours is a repeater pairing a cell value with a dot colour, matched
without regard to case, so Active, Pending and whatever else the table carries each
get their own dot. A value with no match falls back to the muted cell colour. The pill background, text
colour, border, radius, text size, padding, dot size and the space between the dot and the label are fields
under Style › Cells. The dot is hidden from assistive technology, so the pill reads as its
label alone.
Table Behaviour › Table Layout chooses the arrangement.
Framed is an arrangement, not a set of fixed values. The shell colour, radius, border and padding, the row
block colour, radius and border, the header label colour and row height, the cell padding and every part of
the totals bar are fields under Style › Framed Layout. Framed carries its totals from
Footer Row › Totals Label and Totals Value rather than from the grid cells,
and it leaves the header in place while the page scrolls, since there is no bar behind it to pin.
Sortable headers render as buttons, so they are reachable with the keyboard and operable with Enter or
Space. A first click sorts ascending, a second click reverses it. The column header carries
aria-sort and the chevron pair shows the active direction. Set
Sort On Load — Column to a column position to sort the table as it renders; zero keeps the
rows in the order they were entered. Individual columns can opt out with Sortable.
The search field filters rows against every cell value in the row, across the whole table rather than the current page. The result count sits in a polite live region so screen readers hear the new total. When nothing matches, the table and the pagination controls are replaced by the empty state, whose title and text are both editable.
Pagination › Mode chooses between showing every row, numbered pages, and a load more
button.
The footer bar is one group at the right end of the table, reading rows per page, then the range, then the arrows:
1–25 of 124.Previous Button Description and Next Button Description, and each disables at its
end of the range.Numbered page buttons are off to begin with; the arrows and the range carry the pager on their own.
Show Numbered Page Buttons adds a button per page between the arrows, each carrying
aria-current on the page it is on.
Footer Alignment moves the whole group: right, centred, left, or split, which pushes the
arrows to opposite edges with the numbers between them. Sorting or searching returns to the first page.
Below the mobile breakpoint the bar wraps, with the numbers taking a line of their own beneath.
Arrow size, arrow button padding, the space between the groups and the clear space above the whole bar are
fields under Style › Pagination & Buttons.
The range reads the span of rows on screen out of everything the current search matched, so it tracks the
filter rather than the whole table. Range Separator sets the character between the two numbers,
an en dash to begin with, and Range Total Wording sets the word before the total.
Show Range Indicator removes it. Under a load more button it counts from the first row to the
last one loaded. Its colour and size are fields.
Rows Per Page Options is a repeater, so the options are yours to define. Each carries the text
the reader sees and the row count it applies, and a count of zero makes an option that shows every row.
Rows Per Page — Selected On Load picks which one starts selected, and that option sets the
starting page size. Rows Per Page Label sets the wording beside it, and
Rows Per Page Placement keeps it at the head of the pager group or moves it to either end of the
bar. Switching Show Rows Per Page Control off removes it and hands the page size back to
Rows Per Page.
Choosing a new size redraws the table straight away, returns to the first page, and leaves the search text
and the sorted column exactly as they were. The control is a native select with a real
label bound to it, so it reaches the keyboard and the screen reader the way a dropdown should.
Its background, border colour and width, radius, text colour, size, padding and focus ring are all fields
under Style › Rows Per Page Control.
With Sticky Header on, the header bar pins to the top of the window while the page scrolls
past the table and releases as the table ends. It stays aligned with the body when the table scrolls
sideways. Sticky First Column pins the first column against horizontal scrolling.
Small Screen Layout chooses between two behaviours below the mobile breakpoint.
Every colour, size, radius, border width and spacing value on the Style tab writes a CSS custom property,
so nothing in the markup carries an inline style. The body font and the heading font inherit from the host
theme, as do the accent colour and the link colour. Density switches the vertical cell padding between the
value you set and that value scaled by Compact Density Scale.
Rows fade and lift into place one after another whenever the table redraws, so sorting, searching and
turning a page all read as movement rather than a jump. Row entrance duration,
stagger and travel set the feel, and setting the duration to zero turns it off.
Row entrance window caps how long the whole thing may run. A fixed delay per row would run away
on a large page, so on a page big enough to overrun the window the module shortens the per-row delay to fit,
and the last row on screen always starts within it whatever the page size. A short page keeps the exact
stagger the field asks for. Under prefers-reduced-motion the entrance is skipped.
aria-sort updated on the active column as the direction changes.prefers-reduced-motion.Every table on this page is the same module. Revenue by region and Contract register run the framed layout; Invoice register and Service status board run plain. What separates them is Style tab values, behaviour switches and content.
Invoice register carries a full year of invoices, so the pager has something to page through: the range reads against the whole register, the arrows walk it, and choosing a different size in the dropdown redraws it at once. Service status board pages with a load more button instead. Contract register switches the numbered page buttons on and carries a totals bar below the rows.