Build a PDF page thumbnail grid layout
Turn a PDF page count and a chosen number of thumbnail columns into an exact grid specification.
Run — free
The calculator returns the required row count, the total number of grid cells, and the number of page thumbnails placed in the last row. It is useful when building PDF viewers, contact sheets, review dashboards, print planners, or any interface that must reserve a predictable thumbnail area before individual page images are available.
Plan the grid before rendering thumbnails
A PDF thumbnail interface often needs its structure before thumbnail images have finished rendering. Supply the document's page count and the number of columns you want, and this calculator immediately returns the exact row count. It also reports the total cell capacity of that rectangular grid and how many real page thumbnails occupy the final row. Those three values let a layout reserve stable space, create placeholders, size a scroll container, or divide rendering work without opening or modifying the PDF. For example, a 23-page document arranged across five columns needs five rows, provides 25 total cells, and places three thumbnails in its final row. The calculation is deterministic integer arithmetic, so identical inputs always produce identical results in a browser, build process, test suite, or API call. The capability does not render images, inspect PDF bytes, choose thumbnail dimensions, or apply visual styles. It focuses on one narrow planning question and answers it without network access, file uploads, random behavior, or hidden display assumptions.
Interpret rows, cells, and the last row correctly
The returned rows value is the smallest whole number of rows that can hold every page at the requested column count. Total cells is rows multiplied by columns, so it describes the capacity of the complete rectangle, including any unused positions after the last thumbnail. Last-row fill counts actual page thumbnails in the final row. When the page count divides evenly by the column count, the final row is full and last-row fill equals the requested columns; it does not return zero. This convention makes the result convenient for loops, accessibility labels, and final-row styling because every nonempty document has a nonempty last row. Page count and columns must both be positive safe integers. A fractional, missing, textual, infinite, zero, or negative value is rejected rather than rounded or silently converted. In particular, a column count below one is invalid because no finite row count could place pages into a grid with no columns. This strict contract helps catch configuration problems near their source.
Use the result in viewers and document workflows
In a viewer, use rows to estimate the full gallery height from a known thumbnail height and row gap, while total cells can drive a fixed-size placeholder array. Compare total cells with page count to derive unused cells when you need blank slots, although the returned last-row fill usually gives the clearest basis for styling the final row. In a server-rendered review dashboard, the same values can divide pages into predictable batches or generate pagination landmarks before image workers finish. Contact-sheet builders can use the row count to select paper orientation or warn when a chosen column setting creates too many rows. Test suites can assert layout behavior at boundary cases such as one page, a completely filled grid, or a final row containing only one page. Because this capability accepts metadata rather than a PDF file, callers must obtain the trustworthy page count elsewhere. It does not verify that the count matches a particular document. Each API calculation costs $0.002, while the browser version can provide the same pure calculation interactively.
What you can do with it
Reserve a PDF viewer gallery
Compute the row count before page thumbnails finish rendering so the viewer can avoid disruptive layout shifts.
Build a contact-sheet plan
Determine the rectangular capacity and final-row occupancy for a selected number of thumbnail columns.
Test responsive breakpoints
Compare exact grid outcomes for different column counts and assert boundary behavior in automated interface tests.
FAQ
What does one calculation cost?
Each API calculation costs $0.002. The interactive browser calculation is also available on this page.
Does total_cells always equal page_count?
No. Total cells describes the full rectangular grid capacity, so it can include unused positions in a partially filled final row.
What happens when the last row is full?
Last-row fill equals the columns count. A complete final row is reported as full, not as zero.
Can columns be zero?
No. Columns must be a positive integer, and values below 1 produce an invalid-input error.
Does this capability read or render the PDF?
No. It uses only the page count supplied by the caller and returns layout numbers; it never receives PDF bytes or creates images.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/pdf/page-thumbnail-grid-layout \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"page_count":23,"columns":5}'const res = await fetch("https://api.kit.forhosting.com/pdf/page-thumbnail-grid-layout", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"page_count": 23,
"columns": 5
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/pdf/page-thumbnail-grid-layout",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"page_count": 23,
"columns": 5
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/pdf/page-thumbnail-grid-layout", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"page_count":23,"columns":5}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"page_count":23,"columns":5}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/pdf/page-thumbnail-grid-layout", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"page_count": 23,
"columns": 5
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "pdf.page_thumbnail_grid_layout",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
max_mb | 25 |
max_pages | 200 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |