Files
upstream-tldraw/apps/docs/content/sdk-features/grid.mdx
upstream-mirror a774ac673a
Some checks failed
Deploy analytics worker / Deploy analytics worker to ${{ (github.ref == 'refs/heads/production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Failing after 1s
i18n upload strings / Upload latest strings (push) Failing after 1s
Deploy bemo / Deploy bemo to ${{ (github.ref == 'refs/heads/bemo-production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Failing after 1s
Deploy grafana resources / ${{ github.event_name == 'push' && 'Deploy grafana resources' || 'Validate grafana resources (dry run)' }} (push) Failing after 0s
End to end tests (dotcom) / Check for relevant changes (push) Failing after 0s
End to end tests (examples) / Check for relevant changes (push) Failing after 0s
End to end tests (mermaid readability) / Check for relevant changes (push) Failing after 1s
End to end tests (perf) / Check for relevant changes (push) Failing after 0s
Publish editor extensions / Publish editor extensions (push) Failing after 1s
Publish SDK packages / Remove the publish-packages label (push) Has been skipped
Checks / Tests & checks (push) Has been cancelled
Checks / Build all projects (push) Has been cancelled
Deploy templates / Deploy templates (push) Has been cancelled
End to end tests (dotcom) / End to end tests (dotcom) (push) Has been cancelled
End to end tests (mermaid readability) / End to end tests (mermaid readability) (push) Has been cancelled
End to end tests (perf) / End to end tests (perf) (push) Has been cancelled
Deploy .com / Deploy dotcom to ${{ (github.ref == 'refs/heads/production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Has been cancelled
End to end tests (examples) / End to end tests (examples) (push) Has been cancelled
Publish SDK packages / Publish SDK packages (push) Has been cancelled
Publish SDK packages / Tell user released version (push) Has been cancelled
Publish SDK packages / Publishes code templates to separate repositories (push) Has been cancelled
Publish SDK packages / Deploys the template demos with the new SDK version (push) Has been cancelled
snapshot of https://github.com/tldraw/tldraw.git (main, 2026-09-23; blobs > 131072B omitted)
2026-09-23 16:12:52 +05:00

140 lines
4.8 KiB
Plaintext

---
title: Grid
created_at: 1/31/2026
updated_at: 1/31/2026
keywords:
- grid
- background
- canvas grid
- snap to grid
- grid spacing
status: draft
date: 1/31/2026
---
The grid is a dotted background that helps users align shapes on the canvas. When grid mode is on, the editor renders the grid behind shapes and snaps shapes to grid positions as users create, move, and resize them.
## Enabling grid mode
Grid mode is part of the editor's [instance state](/sdk-features/instance-state). Toggle it with [Editor#updateInstanceState](?):
```tsx
import { Tldraw } from 'tldraw'
import 'tldraw/tldraw.css'
export default function App() {
return (
<div style={{ position: 'fixed', inset: 0 }}>
<Tldraw
onMount={(editor) => {
editor.updateInstanceState({ isGridMode: true })
}}
/>
</div>
)
}
```
Users can toggle the grid with Cmd+' (Ctrl+' on Windows) or from the Preferences submenu in the main menu. Grid mode is session state: it persists locally but doesn't sync to collaborators.
```tsx
// Read the current grid mode
const isGridMode = editor.getInstanceState().isGridMode
```
## Grid size
Grid spacing comes from the document's `gridSize` setting, which defaults to 10 page units. Change it with [Editor#updateDocumentSettings](?):
```tsx
editor.updateDocumentSettings({ gridSize: 20 })
```
Because `gridSize` lives on the [TLDocument](?) record, it saves with the document and syncs to collaborators.
## Snap to grid
When grid mode is on, the editor snaps positions to multiples of `gridSize` during these interactions:
- Creating a shape by clicking or dragging with a box tool
- Translating shapes with the select tool
- Resizing and cropping shapes with the selection handles
- Nudging shapes with the arrow keys (one grid unit per press, five with Shift)
- Dragging unbound arrow and line handles
- Dropping external content (like images) onto the canvas
Holding Cmd (Ctrl on Windows) while translating, resizing, or cropping bypasses grid snapping. During translation, grid snapping also yields to [shape snapping](/sdk-features/snapping): if the selection has snapped to another shape's alignment guides, the grid is ignored.
To snap your own values to the grid, use [maybeSnapToGrid](?), which returns the point snapped when grid mode is on and unchanged otherwise:
```tsx
import { maybeSnapToGrid } from 'tldraw'
const point = maybeSnapToGrid(editor.inputs.getCurrentPagePoint(), editor)
```
To snap regardless of grid mode, use [Vec#snapToGrid](?) with the size from [Editor#getDocumentSettings](?):
```tsx
const gridSize = editor.getDocumentSettings().gridSize
const point = editor.inputs.getCurrentPagePoint().clone().snapToGrid(gridSize)
```
## Grid rendering
The [DefaultGrid](?) component draws the grid as SVG dot patterns. It renders one pattern per entry in the editor's `gridSteps` option. Each step describes a dot spacing (in multiples of `gridSize`) and the zoom range over which those dots fade in:
| Field | Description |
| ------ | ----------------------------------------------------- |
| `step` | Dot spacing as a multiple of the document's grid size |
| `min` | Zoom level at which the dots start to fade in |
| `mid` | Zoom level at which the dots reach full opacity |
The defaults show fine dots when zoomed in and progressively coarser dots when zoomed out, so the grid stays readable at any zoom level. Style the dots with the `.tl-grid-dot` CSS class. You can change the steps through the `options` prop:
```tsx
<Tldraw
options={{
gridSteps: [
{ min: -1, mid: 0.15, step: 64 },
{ min: 0.05, mid: 0.375, step: 16 },
{ min: 0.15, mid: 1, step: 4 },
{ min: 0.7, mid: 2.5, step: 1 },
],
}}
/>
```
## Custom grid
Replace the grid entirely by overriding the `Grid` component. Your component receives [TLGridProps](?): the camera position (`x`, `y`, `z`) and the document's grid `size`.
```tsx
import { TLComponents, Tldraw } from 'tldraw'
import 'tldraw/tldraw.css'
const components: TLComponents = {
Grid: ({ x, y, z, size }) => {
// Render your own grid using the camera position and grid size.
// The tl-grid class positions the element correctly on the canvas.
return <canvas className="tl-grid" />
},
}
export default function App() {
return (
<div style={{ position: 'fixed', inset: 0 }}>
<Tldraw components={components} />
</div>
)
}
```
The grid component only renders while grid mode is on. See the [custom grid example](/examples/ui/custom-grid) for a complete canvas-based grid with major and minor lines.
## Related articles
- [Snapping](/sdk-features/snapping) — Shape-to-shape snapping and alignment guides
- [Instance state](/sdk-features/instance-state) — Session state including grid mode
- [UI components](/sdk-features/ui-components) — Overriding canvas components like the grid