ReoGrid ReoGrid Web

Zoom

Since v1.7.0 every sheet has a zoom — Excel’s zoom box — from 10% to 400%. Available in both editions.

Only the view scales. Row heights, column widths, fonts, printing, PDF and xlsx export all stay at 100%, so zooming out to see a whole form never changes a stored value.

const ws = grid.worksheet

ws.setZoom(1.5)   // 150%
ws.getZoom()      // 1.5
ws.setZoom(1)     // back to 100%

Setting the zoom

1 means 100%. Values are clamped to 0.1–4 (10%–400%); NaN, 0 and negative values are ignored.

Without a second argument the top-left cell stays put, as with Excel’s zoom box. Pass a point in canvas CSS px to keep the part of the sheet under that point in place instead — this is what the wheel gesture does with the pointer position:

ws.setZoom(2, { x: 300, y: 200 })   // zoom in around (300, 200) on the canvas

The anchor is followed on an axis only when the point lies over the scrollable body — over a header or a frozen pane there is nothing to scroll. Near the edge of the sheet the scroll position is clamped, so the point can drift slightly.


Ctrl/Cmd + wheel and pinch

Over the grid, Ctrl + wheel (or Cmd + wheel on macOS) zooms the active sheet around the pointer. A trackpad pinch reaches the browser as the same event, so it zooms smoothly as well. One notch of a mouse wheel is roughly 15%, and the same travel back returns you to where you started.

Up to v1.6 this gesture fell through to the browser’s page zoom. If your page relies on that, turn the gesture off:

import { createReogrid } from '@reogrid/lite'

const grid = createReogrid({ workspace: '#grid', wheelZoom: false })

setZoom() keeps working with wheelZoom: false — only the gesture is switched off. No keyboard shortcut (such as Ctrl+0) is assigned, so the browser keeps its own.


One zoom per sheet

Each sheet keeps its own zoom, as in Excel: zoom one tab to 75%, switch to another at 100%, and coming back finds the first one still at 75%.

Following zoom changes

Subscribe on the instance — the listener follows whichever sheet is active:

const label = document.querySelector('#zoom-label')!

const show = (zoom: number) => {
  label.textContent = `${Math.round(zoom * 100)}%`
}

grid.onZoomChange(show)

// Switching tabs is not a zoom *change* — re-read the new sheet's zoom
grid.workbook.onActiveSheetChange(() => show(grid.worksheet.getZoom()))

The listener fires only when the value actually changes: Ctrl/Cmd + wheel, setZoom(), or an xlsx load that brings its own zoom. worksheet.onZoomChange(listener) is the per-sheet version. Both return an unsubscribe function.

A zoom box

// <select id="zoom">
//   <option value="0.5">50%</option> <option value="1" selected>100%</option>
//   <option value="1.5">150%</option> <option value="2">200%</option>
// </select>
const select = document.querySelector<HTMLSelectElement>('#zoom')!

select.addEventListener('change', () => {
  grid.worksheet.setZoom(Number(select.value))
  grid.focus()   // hand the keyboard back to the grid
})

React and Vue

In v1.7.0 the React and Vue components have no zoom prop or event of their own. Subscribe on the instance the component hands you:

// React
import { useState } from 'react'
import { Reogrid } from '@reogrid/lite/react'

function Sheet() {
  const [zoom, setZoom] = useState(1)
  return (
    <>
      <span>{Math.round(zoom * 100)}%</span>
      <Reogrid
        style={{ height: 400 }}
        onReady={(grid) => { grid.onZoomChange(setZoom) }}
      />
    </>
  )
}
<!-- Vue -->
<script setup lang="ts">
import { ref } from 'vue'
import { Reogrid, type ReogridInstance } from '@reogrid/lite/vue'

const zoom = ref(1)
function onReady(grid: ReogridInstance) {
  grid.onZoomChange((z) => { zoom.value = z })
}
</script>

<template>
  <span>{{ Math.round(zoom * 100) }}%</span>
  <Reogrid style="width: 100%; height: 400px" @ready="onReady" />
</template>

What stays at 100%

Zoom is applied only where the sheet meets the screen. Everything that is measured, stored or printed keeps its 100% value:

When zoomed
Cells, text and images on screenDrawn larger or smaller
Row heights, column widths, font sizesUnchanged — the API, xlsx and JSON all see the 100% values
Grid lines, the selection outline, thin bordersStay one device pixel thin, as in Excel
Resize grips, the drag-to-move edge, image handlesKeep the same size on screen, so they are as easy to grab at 25% as at 100%
Browser print, PDF export, print to HTMLAlways 100% — the page setup’s scale / fit-to-pages is a separate setting
Cell tooltips, comments, validation messagesScale with the sheet (they are drawn on the canvas)
Dropdown lists, the filter listKeep their size; only their position follows the cell

Zoom in xlsx

The sheet’s zoomScale is read and written, so a workbook saved at 85% in Excel opens at 85% and saves back at 85%. For a sheet saved in page-break preview or page layout view, the normal-view zoom (zoomScaleNormal) is used. xlsx stores whole percentages, so a pinch that ended at 123.4% is written as 123%.

Zoom is a viewer setting, not sheet content:

  • Loading an xlsx applies the file’s zoom — 100% when the file records none.
  • reset() and loadJson() leave the zoom where it is, and ReoGrid JSON does not store it.

Overlaying your own elements

getCellRect(), getRangeRect() and getImageRect() return 100% sheet px. If you position your own elements over the grid from them, multiply by the zoom:

const ws = grid.worksheet

// An absolutely positioned element of yours, inside a box whose top-left
// corner lines up with the grid canvas
const badge = document.querySelector<HTMLElement>('#badge')!

function placeBadge(row: number, col: number) {
  const r = ws.getCellRect(row, col)   // 100% sheet px
  const z = ws.getZoom()
  badge.style.left = `${r.x * z}px`
  badge.style.top = `${r.y * z}px`
  badge.style.width = `${r.width * z}px`
  badge.style.height = `${r.height * z}px`
}

placeBadge(2, 1)

// Re-place it whenever the zoom or the scroll position changes
ws.onZoomChange(() => placeBadge(2, 1))
ws.onScrollChange(() => placeBadge(2, 1))

Code that never overlays its own DOM needs no change.


Limits

  • At a combined scale that is not a whole number — 90% on a standard display, say — thin lines can look slightly lighter, just as they do under Windows’ 125% / 150% display scaling.
  • Zoom is not part of ReoGrid JSON; persist it yourself if your app should remember it.

  • Zoom demo — Ctrl/Cmd + wheel, pinch and a zoom box on a live sheet.
  • Grid Options — wheelZoom and the other createReogrid() options.
  • Multi-Sheet Workbook — per-sheet state and the instance events that follow the active sheet.
  • Page Layout — the print scale and fit-to-pages, which are separate from zoom.
  • XLSX Import & Export — what else travels with the file.
Was this page helpful?
Stay Updated

Be first to know — get updates as they ship

Get notified of new releases, features, and announcements.
No spam — just updates that matter.