Skip to content

shadcn.io is an independent project built on shadcn/ui

Zoom Controls Button Group for React

Zoom from 25% to 400% in steps of 25, starting at 100%, with Reset and Fit both returning to 100%.

Zoom starts at 100%. Zoom out and zoom in move by 25, and the level stays between 25% and 400%. The buttons stay enabled at the ends. Reset and Fit both go back to 100%. The percent between the icons does not change the zoom, and nothing is scaled.

Use this for an image or a document. Fit should measure the content if 100% is not actually a fit. A smooth level is a Slider. In React, Base UI does not scale the content.

Preview

Preview width

Installation

Sign in to get your install command
Free with an account. It carries your token, so the CLI installs everything in one go.
Use email insteadNo credit card

Anatomy

Button Group anatomy: root, group, button, separator

Usage

<div className="flex flex-col gap-4">
  <ButtonGroup aria-label="Zoom">
    <Button
      aria-label="Zoom out"
      onClick={zoomOut}
      size="icon-sm"
      variant="outline"
    >
      <ZoomOutIcon aria-hidden="true" />
    </Button>
    <Button onClick={resetZoom} size="sm" variant="outline">
      <RotateCcwIcon aria-hidden="true" data-icon="inline-start" />
      Reset
    </Button>
    <Button
      aria-label="Zoom in"
      onClick={zoomIn}
      size="icon-sm"
      variant="outline"
    >
      <ZoomInIcon aria-hidden="true" />
    </Button>
    <Button onClick={resetZoom} size="sm" variant="outline">
      <MaximizeIcon aria-hidden="true" data-icon="inline-start" />
      Fit
    </Button>
  </ButtonGroup>
  <ButtonGroup aria-label="Zoom">
    <Button
      aria-label="Zoom out"
      onClick={zoomOut}
{/* The rest of the file is under Installation. */}

FAQ

How is the zoom tracked?

As a number, starting at 100. Zoom out subtracts 25 and stops at 25; zoom in adds 25 and stops at 400.

How are the icon-only buttons named?

Zoom out and Zoom in are aria-labels, with size="icon-sm". Reset and Fit have text, and their icons have aria-hidden="true".

Why do Reset and Fit do the same thing?

In the demo both set 100%, since there's no content to measure. Make Fit compute the level that fits your content in its container.

Does the percentage button do anything?

No. It shows the level and has no handler. Make it reset to 100% if you want, or use ButtonGroupText so it doesn't take focus.

Should zoom out be disabled at 25%?

It can be. The demo leaves both buttons enabled and clamps the value instead. Disable them at the limits so people can see they've reached the end.

How do I apply the zoom?

Scale your content with a CSS transform: scale() from the number divided by 100, or pass it to your viewer.

API Reference

Button Group

Sets aria-label="Zoom". The rest is on the Button Group page.

Button

Sets aria-label="Zoom out", onClick={zoomOut}, size="icon-sm", variant="outline", onClick={resetZoom} and size="sm". The rest is on the Button page.