Search...Search plugins and themes...
⌘K
Sign in
  • Get started
  • Download
  • Pricing
  • Enterprise
  • Account
  • Obsidian
  • Overview
  • Sync
  • Publish
  • Canvas
  • Mobile
  • Web Clipper
  • CLI
  • Learn
  • Help
  • Developers
  • Changelog
  • About
  • Roadmap
  • Blog
  • Resources
  • System status
  • License overview
  • Terms of service
  • Privacy policy
  • Security
  • Community
  • Plugins
  • Themes
  • Discord
  • Forum / 中文论坛
  • Merch store
  • Brand guidelines
Follow us
DiscordTwitterBlueskyThreadsMastodonYouTubeGitHub
© 2026 Obsidian

Canvas Positioning Toolkit

valleytheknightvalleytheknight48 downloads

Auto-layout and arrange Canvas cards into a grid, pick one up and place it with a hotkey instead of dragging, or find a card in a cluster with a text search.

Add to Obsidian
  • Overview
  • Scorecard
  • Updates1

I built this because moving cards around on an Obsidian Canvas board never had a good answer for two specific situations: a messy board that needs tidying, and pulling one card out of a dense cluster when your mouse precision runs out at low zoom. Neither problem had an existing plugin solving it when I checked, so here's what I built instead.

Auto-layout demo

Scope

This plugin only touches Canvas card x/y/width/height on the active board. It never touches file content, other views, or anything outside a Canvas. Every feature below goes through the same three calls: read a card's position off canvas.nodes, write a new one with node.setData(), then tell the canvas it moved with canvas.markMoved() so undo history and the on-disk save stay in sync.

I confirmed that API by reading how the Advanced Canvas plugin (github.com/Developer-Mike/obsidian-advanced-canvas) uses the same objects, and by checking that its own patcher overrides markMoved and requestSave as already-existing methods rather than adding them. That told me these are core Obsidian Canvas methods, not something Advanced Canvas invented, so this plugin has no dependency on it.

Auto-layout

What it does: arranges cards into a tidy grid. Run it with nothing selected and it lays out the whole board; select two or more cards first and only those move, everything else stays put.

Why: I kept ending up with boards where cards landed wherever I'd dropped them, and there was no "just tidy this up" button. Advanced Canvas doesn't have one, and the two mindmap-focused plugins I found only auto-layout tree/connection structures, not an arbitrary set of cards.

How I built it: each row uses the tallest card in that row to offset the next row, so a mix of short and tall cards never overlaps:

export function computeGridLayout(
    nodes: LayoutNode[],
    columns: number,
    gap: number,
): Map<string, LayoutPosition> {
    const positions = new Map<string, LayoutPosition>();
    if (nodes.length === 0 || columns < 1) return positions;

    let cursorY = 0;
    for (let rowStart = 0; rowStart < nodes.length; rowStart += columns) {
        const row = nodes.slice(rowStart, rowStart + columns);
        const rowHeight = Math.max(...row.map((n) => n.height));

        let cursorX = 0;
        for (const node of row) {
            positions.set(node.id, { x: cursorX, y: cursorY });
            cursorX += node.width + gap;
        }

        cursorY += rowHeight + gap;
    }

    return positions;
}

Try it: Command palette → Auto-layout cards (selection, or whole board if nothing selected). Columns and spacing are configurable in the plugin's settings.

Pick up and place

Pick up and place demo

What it does: select a card, run the command, move your mouse with no button held down, click an empty spot to place it. Press Escape instead and it snaps back to where it started.

Why: this one came from a forum post someone sent me (forum.obsidian.md/t/moving-dragging-cards-more-efficiently-across-the-canvas/116135). At low zoom, a card's drag hit-target gets small enough that pulling one card out of a cluster means repeatedly hovering to find the hand cursor. Their proposed fix, a hotkey that picks the card up so it follows your pointer without holding a button, was exactly right, and nobody had built it.

Under the hood: canvas.posFromEvt(event) converts a mouse event straight to canvas coordinates regardless of zoom, so following the pointer comes down to this:

private followPointer(e: PointerEvent): void {
    if (!this.canvas || !this.node) return;
    const pos = this.canvas.posFromEvt(e);
    const node = this.node;
    node.setData({
        ...node.getData(),
        x: pos.x - node.width / 2,
        y: pos.y - node.height / 2,
    });
    this.canvas.markMoved(node);
}

Placing (or canceling) removes the listeners and either saves the new position or restores the original one I recorded when the pick-up started.

On mobile: this listens for Pointer Events (pointermove/pointerup), not mouse events specifically, so a touch drag works the same way: the card follows your finger while it's down, and lifting it places the card. The gesture is naturally a hold-and-drag on touch instead of a move-with-no-button-held, since touch input has no hover state, but the same command and the same code path handle both.

Try it: select a card, then run Pick up selected card (click empty space to place) from the command palette.

Find card by text

Find card by text demo

What it does: opens a fuzzy search over every card's text on the current board. Type part of the card's content, pick it from the list, and it's selected and picked up in one step, ready to place.

Why: pick-up-and-place solves moving a card once you've selected it, but selecting the right card in a tight cluster in the first place has the exact same aiming problem. Searching by text sidesteps aiming entirely instead of trying to make it easier.

How it works: Obsidian's own FuzzySuggestModal does the fuzzy matching. I feed it every card's label:

export class FindCardModal extends FuzzySuggestModal<CanvasNode> {
    getItems(): CanvasNode[] {
        return [...this.canvas.nodes.values()];
    }

    getItemText(node: CanvasNode): string {
        return cardLabel(node.getData());
    }

    onChooseItem(node: CanvasNode): void {
        this.onChoose(node);
    }
}

cardLabel reads a text card's first line, or a file card's filename, so the list shows something meaningful instead of raw IDs.

Try it: run Find card by text and pick it up from the command palette, type part of the card's text, and press Enter.

Settings

  • Grid columns: how many cards per row when running auto-layout.
  • Grid gap: pixel spacing between cards when running auto-layout.

Installation

Not yet in Obsidian's community plugin directory. Manual install for now:

  1. Download main.js, manifest.json, and styles.css from the latest release.
  2. Put them in <your vault>/.obsidian/plugins/canvas-positioning-toolkit/.
  3. Reload Obsidian and enable the plugin in Community plugins.

Contributing

Issues and pull requests are welcome.

Support

If this saved you some dragging, buy me a coffee.

License

MIT

HealthExcellent
ReviewSatisfactory
About
Three tools for moving cards on an Obsidian Canvas board. Auto-layout arranges your cards into a tidy grid. Run it on the whole board or just your current selection, and a scattered mess sorts itself instead of you dragging each card by hand. Pick up and place fixes the low-zoom problem. Zoom out on a busy board and a card's drag target shrinks until grabbing the one you want means hovering around for the hand cursor. A hotkey picks up the selected card instead: it follows your pointer, or your finger on touch and mobile, no button held down. Click, or lift your finger, to place it. Escape cancels and snaps it back. Find card by text is a fuzzy search across every card on the board. Type part of a card's content, pick it from the list, and it is selected and picked up in one move, ready to place. No aiming into a dense cluster required.
CanvasAutomation
Details
Current version
1.0.0
Last updated
6 days ago
Created
6 days ago
Updates
1 release
Downloads
48
Compatible with
Obsidian 1.7.0+
Platforms
Desktop, Mobile
License
MIT
Report bugRequest featureReport plugin
Sponsor
Buy Me a Coffee
Author
valleytheknightvalleytheknight
GitHubchrisairbrown-del
  1. Community
  2. Plugins
  3. Canvas
  4. Canvas Positioning Toolkit

Related plugins

Homepage

Open a note, base, or workspace on startup, or set it for quick access later.

BRAT

Easily install a beta version of a plugin for testing.

Advanced URI

Control everything with URI.

Advanced Canvas

Supercharge your canvas experience. Create presentations, flowcharts and more.

Lazy Loader

Load plugins with a delay on startup, so that you can get your app startup down into the sub-second loading time.

Hot Reload

Automatically reload in-development plugins when their files are changed

Templater

Create and use dynamic templates.

Readwise Official

Sync highlights from Readwise to your vault.

Update modified date

Automatically update a frontmatter modified date field when the file is modified.

Linter

Format and style your notes. Linter can be used to format YAML tags, aliases, arrays, and metadata; footnotes; headings; spacing; math blocks; regular Markdown contents like list, italics, and bold styles; and more with the use of custom rule options.