Guide
The keyboard and screen readers
Not one of the croppers this replaces can be used without a mouse. That is the whole review.
Choosing a picture
The real <input type="file"> is kept as the control, with the drop zone as its <label>. So:
- Tab reaches it, because it is a real input.
- Enter or Space opens the file picker.
- Clicking anywhere in the zone opens it too, because that is what a label does.
- A screen reader reads the label you already wrote.
Nothing needed a tabindex, a role="button" or a keypress handler — so there is nothing to get
subtly wrong.
Moving the crop
The crop is a focusable, named group with a spoken value:
| Key | What it does |
|---|---|
| ← → ↑ ↓ | Move the crop by 5 pixels. In fixed mode, move the picture instead. |
| Alt + arrow | By 1 pixel. |
| Ctrl or ⌘ + arrow | By 20. |
| Shift + arrow | Resize instead of moving. |
Every change updates aria-valuetext — "400 by 300, at 120, 60" — and is announced through a live
region. The rule-of-thirds grid appears on focus as well as on drag, so a keyboard user sees the same
guides as a mouse user.
The zoom is a real <input type="range">, so it has the browser's own keyboard behaviour, and every
tool is a real <button> with a name and a tooltip.
On a phone
touch-action: none is set on the stage and nowhere else, so the page keeps scrolling normally
until a finger is actually on the crop — one of the open complaints against react-image-crop is that
it swallows the page's scroll. Pinch to zoom works through Pointer Events, and each handle carries an
invisible ten-pixel margin so a finger can find it.
Seeing it
- The handles are solid shapes with a white border, visible on any picture.
- The crop's outline is white over a darkened surround, so it reads on light and dark images alike.
@media (forced-colors: active)gives the outline and handles system colours.prefers-reduced-motionturns off the grid's fade.- Focus rings are drawn on every control.
What is announced, and what is not
The crop's size and position are announced as they change, because that is the information being edited. Progress-like chatter is avoided: opening a picture says "Opening…" once, an error says what is wrong once, and dragging does not narrate every pixel — the live region is updated on key presses, where each change is deliberate, rather than on every frame of a drag.