Skip to content
← Server-side Pagination
Edit Server-side Pagination
Name
Also known as (comma separated)
Brief definition
Pagination performed by the backend.
Notes
Tier
Core
Useful
Reference
Deleted
Controls schema (JSON array)
[ { "id": "caption", "type": "text", "label": "Caption", "default": "Customer orders" }, { "id": "accent", "type": "color", "label": "Accent", "default": "#241430", "presets": [ "#241430", "#A8E6C1", "#F5C2E0", "#BFD9F2", "#D9C8F0", "#E8A020" ] }, { "id": "page", "type": "select", "label": "Current page", "default": "1", "options": [ "1", "2", "3" ] }, { "id": "pageSize", "type": "select", "label": "Rows per page", "default": "10", "options": [ "10", "25", "50" ] }, { "id": "loading", "type": "toggle", "label": "Loading next page", "default": false } ]
Templates (JSON object keyed by format)
{ "html": "<div class=\"ssp{{#if loading}} ssp--loading{{/if}}\" data-page=\"{{page}}\" style=\"--accent:{{accent}};\">\n <div class=\"ssp__scroll\">\n <table class=\"ssp__table\">\n <caption>{{caption}} · {{pageSize}} rows per page</caption>\n <thead><tr><th scope=\"col\">Order</th><th scope=\"col\">Customer</th><th scope=\"col\">Status</th><th scope=\"col\">Total</th></tr></thead>\n <tbody>\n <tr data-row-page=\"1\"><td>#1042</td><td>A. Whitfield</td><td>Shipped</td><td>£64.00</td></tr>\n <tr data-row-page=\"1\"><td>#1041</td><td>R. Okafor</td><td>Processing</td><td>£128.50</td></tr>\n <tr data-row-page=\"2\"><td>#1040</td><td>M. Iqbal</td><td>Shipped</td><td>£22.00</td></tr>\n <tr data-row-page=\"2\"><td>#1039</td><td>S. Novak</td><td>Refunded</td><td>£40.00</td></tr>\n <tr data-row-page=\"3\"><td>#1038</td><td>L. Duarte</td><td>Shipped</td><td>£96.20</td></tr>\n <tr data-row-page=\"3\"><td>#1037</td><td>P. Andersson</td><td>Processing</td><td>£15.75</td></tr>\n </tbody>\n </table>\n </div>\n <div class=\"ssp__footer\">\n <button type=\"button\" class=\"ssp__nav\" {{#unless loading}}{{/unless}}>← Prev</button>\n <div class=\"ssp__pages\" role=\"group\" aria-label=\"Pages\">\n <button type=\"button\" class=\"ssp__page ssp__page--1\" aria-label=\"Page 1\">1</button>\n <button type=\"button\" class=\"ssp__page ssp__page--2\" aria-label=\"Page 2\">2</button>\n <button type=\"button\" class=\"ssp__page ssp__page--3\" aria-label=\"Page 3\">3</button>\n </div>\n <button type=\"button\" class=\"ssp__nav\">Next {{#if loading}}<span class=\"ssp__spinner\" aria-hidden=\"true\"></span>{{/if}}</button>\n </div>\n</div>\n<style>\n.ssp { font: 14px system-ui, sans-serif; color: #241430; background: #FAF7F2; max-width: 480px; border: 1px solid #24143020; border-radius: 10px; overflow: hidden; }\n.ssp__scroll { overflow-x: auto; }\n.ssp__table { border-collapse: collapse; width: 100%; }\n.ssp__table caption { text-align: left; font-weight: 600; padding: 10px 14px; }\n.ssp__table th, .ssp__table td { padding: 10px 14px; text-align: left; border-bottom: 1px solid #24143020; white-space: nowrap; }\n.ssp__table th { background: var(--accent); color: #FAF7F2; }\n.ssp[data-page=\"1\"] tbody tr:not([data-row-page=\"1\"]) { display: none; }\n.ssp[data-page=\"2\"] tbody tr:not([data-row-page=\"2\"]) { display: none; }\n.ssp[data-page=\"3\"] tbody tr:not([data-row-page=\"3\"]) { display: none; }\n.ssp__footer { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 10px 14px; border-top: 1px solid #24143020; }\n.ssp__nav { font-size: 12px; border: 1px solid #24143040; background: #FAF7F2; border-radius: 6px; padding: 5px 10px; cursor: pointer; display: inline-flex; align-items: center; gap: 6px; }\n.ssp__nav:hover { background: #24143010; }\n.ssp__pages { display: flex; gap: 4px; }\n.ssp__page { width: 26px; height: 26px; border: 1px solid #24143040; background: #FAF7F2; border-radius: 6px; font: inherit; font-size: 12px; cursor: pointer; }\n.ssp[data-page=\"1\"] .ssp__page--1,\n.ssp[data-page=\"2\"] .ssp__page--2,\n.ssp[data-page=\"3\"] .ssp__page--3 { background: var(--accent); color: #FAF7F2; border-color: var(--accent); }\n.ssp__spinner { width: 10px; height: 10px; border-radius: 50%; border: 2px solid #24143030; border-top-color: var(--accent); }\n@keyframes ssp-spin { to { transform: rotate(360deg); } }\n@media (prefers-reduced-motion: no-preference) {\n .ssp__spinner { animation: ssp-spin .2s linear infinite; }\n}\n.ssp--loading .ssp__scroll { opacity: .6; }\n</style>", "tailwind": "<div class=\"max-w-[480px] rounded-[10px] border border-[#24143020] font-sans text-sm text-[#241430] bg-[#FAF7F2] overflow-hidden{{#if loading}} [&_.ssp__scroll]:opacity-60{{/if}}\" data-page=\"{{page}}\" style=\"--accent:{{accent}};\">\n <div class=\"ssp__scroll overflow-x-auto\">\n <table class=\"border-collapse w-full\">\n <caption class=\"text-left font-semibold px-3.5 py-2.5\">{{caption}} · {{pageSize}} rows per page</caption>\n <thead><tr class=\"text-[#FAF7F2]\" style=\"background:{{accent}}\">\n <th scope=\"col\" class=\"p-3.5 text-left whitespace-nowrap\">Order</th>\n <th scope=\"col\" class=\"p-3.5 text-left whitespace-nowrap\">Customer</th>\n <th scope=\"col\" class=\"p-3.5 text-left whitespace-nowrap\">Status</th>\n <th scope=\"col\" class=\"p-3.5 text-left whitespace-nowrap\">Total</th>\n </tr></thead>\n <tbody>\n <tr data-row-page=\"1\"><td class=\"p-3.5 border-b border-[#24143020] whitespace-nowrap\">#1042</td><td class=\"p-3.5 border-b border-[#24143020] whitespace-nowrap\">A. Whitfield</td><td class=\"p-3.5 border-b border-[#24143020] whitespace-nowrap\">Shipped</td><td class=\"p-3.5 border-b border-[#24143020] whitespace-nowrap\">£64.00</td></tr>\n <tr data-row-page=\"1\"><td class=\"p-3.5 border-b border-[#24143020] whitespace-nowrap\">#1041</td><td class=\"p-3.5 border-b border-[#24143020] whitespace-nowrap\">R. Okafor</td><td class=\"p-3.5 border-b border-[#24143020] whitespace-nowrap\">Processing</td><td class=\"p-3.5 border-b border-[#24143020] whitespace-nowrap\">£128.50</td></tr>\n <tr data-row-page=\"2\"><td class=\"p-3.5 border-b border-[#24143020] whitespace-nowrap\">#1040</td><td class=\"p-3.5 border-b border-[#24143020] whitespace-nowrap\">M. Iqbal</td><td class=\"p-3.5 border-b border-[#24143020] whitespace-nowrap\">Shipped</td><td class=\"p-3.5 border-b border-[#24143020] whitespace-nowrap\">£22.00</td></tr>\n <tr data-row-page=\"2\"><td class=\"p-3.5 border-b border-[#24143020] whitespace-nowrap\">#1039</td><td class=\"p-3.5 border-b border-[#24143020] whitespace-nowrap\">S. Novak</td><td class=\"p-3.5 border-b border-[#24143020] whitespace-nowrap\">Refunded</td><td class=\"p-3.5 border-b border-[#24143020] whitespace-nowrap\">£40.00</td></tr>\n <tr data-row-page=\"3\"><td class=\"p-3.5 border-b border-[#24143020] whitespace-nowrap\">#1038</td><td class=\"p-3.5 border-b border-[#24143020] whitespace-nowrap\">L. Duarte</td><td class=\"p-3.5 border-b border-[#24143020] whitespace-nowrap\">Shipped</td><td class=\"p-3.5 border-b border-[#24143020] whitespace-nowrap\">£96.20</td></tr>\n <tr data-row-page=\"3\"><td class=\"p-3.5 border-b border-[#24143020] whitespace-nowrap\">#1037</td><td class=\"p-3.5 border-b border-[#24143020] whitespace-nowrap\">P. Andersson</td><td class=\"p-3.5 border-b border-[#24143020] whitespace-nowrap\">Processing</td><td class=\"p-3.5 border-b border-[#24143020] whitespace-nowrap\">£15.75</td></tr>\n </tbody>\n </table>\n </div>\n <div class=\"flex items-center justify-between gap-2 px-3.5 py-2.5 border-t border-[#24143020]\">\n <button type=\"button\" class=\"text-xs border border-[#24143040] bg-[#FAF7F2] rounded-md px-2.5 py-1\">← Prev</button>\n <div class=\"flex gap-1\" role=\"group\" aria-label=\"Pages\">\n <button type=\"button\" class=\"ssp__page ssp__page--1 w-[26px] h-[26px] border border-[#24143040] bg-[#FAF7F2] rounded-md text-xs\" aria-label=\"Page 1\">1</button>\n <button type=\"button\" class=\"ssp__page ssp__page--2 w-[26px] h-[26px] border border-[#24143040] bg-[#FAF7F2] rounded-md text-xs\" aria-label=\"Page 2\">2</button>\n <button type=\"button\" class=\"ssp__page ssp__page--3 w-[26px] h-[26px] border border-[#24143040] bg-[#FAF7F2] rounded-md text-xs\" aria-label=\"Page 3\">3</button>\n </div>\n <button type=\"button\" class=\"text-xs border border-[#24143040] bg-[#FAF7F2] rounded-md px-2.5 py-1 inline-flex items-center gap-1.5\">Next {{#if loading}}<span aria-hidden=\"true\" class=\"w-2.5 h-2.5 rounded-full border-2 border-[#24143030] motion-safe:animate-spin\" style=\"border-top-color:{{accent}}\"></span>{{/if}}</button>\n </div>\n</div>\n<style>\n[data-page=\"1\"] tbody tr:not([data-row-page=\"1\"]) { display: none; }\n[data-page=\"2\"] tbody tr:not([data-row-page=\"2\"]) { display: none; }\n[data-page=\"3\"] tbody tr:not([data-row-page=\"3\"]) { display: none; }\n[data-page=\"1\"] .ssp__page--1, [data-page=\"2\"] .ssp__page--2, [data-page=\"3\"] .ssp__page--3 { background: var(--accent); color: #FAF7F2; border-color: var(--accent); }\n</style>", "react": "function ServerSidePagination({\n caption = \"{{caption}}\",\n accent = \"{{accent}}\",\n page = \"{{page}}\",\n pageSize = \"{{pageSize}}\",\n loading = {{loading}},\n}) {\n const rows = [\n [\"#1042\", \"A. Whitfield\", \"Shipped\", \"£64.00\", \"1\"],\n [\"#1041\", \"R. Okafor\", \"Processing\", \"£128.50\", \"1\"],\n [\"#1040\", \"M. Iqbal\", \"Shipped\", \"£22.00\", \"2\"],\n [\"#1039\", \"S. Novak\", \"Refunded\", \"£40.00\", \"2\"],\n [\"#1038\", \"L. Duarte\", \"Shipped\", \"£96.20\", \"3\"],\n [\"#1037\", \"P. Andersson\", \"Processing\", \"£15.75\", \"3\"],\n ];\n const visible = rows.filter((r) => r[4] === page);\n const cell = { padding: \"10px 14px\", borderBottom: \"1px solid #24143020\", whiteSpace: \"nowrap\" };\n return (\n <div style={{ maxWidth: 480, borderRadius: 10, border: \"1px solid #24143020\", overflow: \"hidden\", font: \"14px system-ui, sans-serif\", color: \"#241430\", background: \"#FAF7F2\" }}>\n <div style={{ overflowX: \"auto\", opacity: loading ? .6 : 1 }}>\n <table style={{ borderCollapse: \"collapse\", width: \"100%\" }}>\n <caption style={{ textAlign: \"left\", fontWeight: 600, padding: \"10px 14px\" }}>{caption} · {pageSize} rows per page</caption>\n <thead>\n <tr style={{ background: accent, color: \"#FAF7F2\" }}>\n {[\"Order\", \"Customer\", \"Status\", \"Total\"].map((h) => <th key={h} scope=\"col\" style={cell}>{h}</th>)}\n </tr>\n </thead>\n <tbody>\n {visible.map((row) => (\n <tr key={row[0]}>{row.slice(0, 4).map((c, j) => <td key={j} style={cell}>{c}</td>)}</tr>\n ))}\n </tbody>\n </table>\n </div>\n <div style={{ display: \"flex\", alignItems: \"center\", justifyContent: \"space-between\", gap: 8, padding: \"10px 14px\", borderTop: \"1px solid #24143020\" }}>\n <button type=\"button\" style={{ fontSize: 12, border: \"1px solid #24143040\", background: \"#FAF7F2\", borderRadius: 6, padding: \"5px 10px\", cursor: \"pointer\" }}>← Prev</button>\n <div role=\"group\" aria-label=\"Pages\" style={{ display: \"flex\", gap: 4 }}>\n {[\"1\", \"2\", \"3\"].map((p) => (\n <button key={p} type=\"button\" aria-label={`Page ${p}`} style={{ width: 26, height: 26, border: `1px solid ${page === p ? accent : \"#24143040\"}`, background: page === p ? accent : \"#FAF7F2\", color: page === p ? \"#FAF7F2\" : \"#241430\", borderRadius: 6, fontSize: 12, cursor: \"pointer\" }}>{p}</button>\n ))}\n </div>\n <button type=\"button\" style={{ fontSize: 12, border: \"1px solid #24143040\", background: \"#FAF7F2\", borderRadius: 6, padding: \"5px 10px\", cursor: \"pointer\", display: \"inline-flex\", alignItems: \"center\", gap: 6 }}>\n Next {loading && <span aria-hidden=\"true\" style={{ width: 10, height: 10, borderRadius: \"50%\", border: \"2px solid #24143030\", borderTopColor: accent }} />}\n </button>\n </div>\n </div>\n );\n}" }
Save
History