---
title: "Auto tab order for PDF annotations | Nutrient"
canonical_url: "https://www.nutrient.io/guides/web/knowledge-base/automatic-annotation-field-tab-ordering/"
md_url: "https://www.nutrient.io/guides/web/knowledge-base/automatic-annotation-field-tab-ordering.md"
last_updated: "2026-05-18T14:28:53.388Z"
description: "In document annotation workflows, maintaining a logical tab order for fields is essential for smooth user navigation and accessibility."
---

In document annotation workflows, maintaining a logical tab order for fields is essential for smooth user navigation and accessibility. Nutrient’s `setPageTabOrder` API offers a reliable way to set a customized tab ordering for annotations, enabling users to cycle through annotations in a meaningful sequence. This guide walks you through implementing an automatic tab order based on field positions using a JavaScript-based approach. We’ll address the challenges introduced in Nutrient versions after 2024.3.0 and provide a solution that works across affected versions.

## Why tab ordering matters

Annotations are often used in PDF forms, where they represent interactive fields, such as text boxes and checkboxes. By default, annotations may not follow a logical visual order when tabbed through, which can cause frustration and reduce accessibility. Our solution programmatically defines the tab sequence based on field positions, creating a more intuitive navigation experience.

## Setting up tab order initialization

We begin by initializing the tab order setup on document load using `initializeTabOrder`. This function sets a tab order for each page by sorting annotations based on their vertical and horizontal positions, so users can move sequentially from top-left to bottom-right.

### Code overview

Here’s the code for setting up and maintaining the tab order on each page:

```javascript

let isTabOrderInitialized = false;

const initializeTabOrder = async (instance) => {
  // Return early if already initialized.
  if (!isTabOrderInitialized) {
    try {
      // Initialize tab reordering for each page.
      await Promise.all(
        Array.from({
          length: instance.totalPageCount
        }).map((_, pageIndex) =>
          instance.setPageTabOrder(
            pageIndex,
            (currentTabOrderedAnnotations) =>
              currentTabOrderedAnnotations.sort((a, b) => a.boundingBox.top - b.boundingBox.top).map((annotation) => annotation.id)
          )
        )
      );
      isTabOrderInitialized = true;
      console.log("Tab order initialized");
    } catch (error) {
      console.error("Failed to initialize tab order:", error);
      throw error;
    }
  }
};

```

This function initializes the tab order across all pages on document load. Each page’s annotations are sorted by their `boundingBox.top` value, with ties broken by `boundingBox.left`. The sorted order is then mapped to annotation IDs to set the order using `instance.setPageTabOrder`.

## Handling dynamic annotation creation and updates

Annotations may be added or updated after initialization, requiring dynamic updates to the tab order. For this, we use `annotations.create` and `annotations.update` event listeners to reorder annotations whenever a new annotation is created or an existing one is modified:

```javascript

const annotationReorder = async (annotations) => {
  const annotation = annotations?.get(0);

  if (annotation) {
    const currentTabOrder = await globalInstance.getPageTabOrder(
      annotation.pageIndex
    );

    // Add annotation to tab order if it's missing.
    if (!currentTabOrder?.includes(annotation.id)) {
      currentTabOrder.push(annotation.id);
    }

    await globalInstance.setPageTabOrder(
      annotation.pageIndex,
      (currentTabOrderedAnnotations) =>
        currentTabOrderedAnnotations.sort((a, b) =>
            a.boundingBox.top!== b.boundingBox.top? a.boundingBox.top - b.boundingBox.top
              : a.boundingBox.left - b.boundingBox.left
          ).map((annotation) => annotation.id)
    );
  }
};

```

This function first checks if the annotation exists and isn’t already part of the tab order. If it’s missing, it’s added to the list, and then the tab order is updated based on the position-based sorting logic described above.

## Addressing the known bug in Nutrient 2024.3.1 to 2024.7.0

A bug affects `setPageTabOrder` in versions 2024.3.1 to 2024.7.0, where the tab ordering fails to update correctly in certain cases. To work around this, we use `renderPageCallback` to ensure `initializeTabOrder` is called whenever a page is rendered, maintaining correct tab behavior.

Here’s the code that integrates our solution with the Nutrient document load process, including this workaround:

```javascript

let globalInstance = null;

NutrientViewer.load({...baseOptions,
  theme: NutrientViewer.Theme.DARK,
  initialViewState: new NutrientViewer.ViewState({
    prerenderedPageSpreads: null
  }),
  renderPageCallback: function (ctx, pageIndex, pageSize) {
    initializeTabOrder(globalInstance);
  }
}).then(async (instance) => {
  globalInstance = instance;

  // Event listeners for dynamic annotation reordering
  instance.addEventListener("annotations.create", annotationReorder);
  instance.addEventListener("annotations.update", annotationReorder);
});

```

In this setup:

- `initializeTabOrder` is invoked within `renderPageCallback`, ensuring the tab order is reset for any page that renders.

- Event listeners for `annotations.create` and `annotations.update` maintain the tab order dynamically as annotations are added or modified.

This approach works reliably across versions, including those affected by the bug, making it a versatile solution for maintaining tab order consistency.

## Conclusion

By implementing this solution, you ensure annotations in Nutrient-powered documents follow a logical tab order based on their positions on the page. This code is ideal for customers requiring Adobe-like tab ordering. Although a bug currently impacts the `setPageTabOrder` method in some versions, the workaround with `renderPageCallback` restores expected functionality. This approach provides a seamless user experience, with enhanced accessibility and ease of navigation through annotations.

## References

- **Nutrient Playground example** — For a working Playground example, see the [tab ordering Playground](https://www.nutrient.io/demo/sandbox?p=eyJ2IjoxLCJzZXR0aW5ncyI6eyJmaWxlTmFtZSI6ImZvcm0ucGRmIiwiand0Ijp7InBlcm1pc3Npb25zIjpbInJlYWQtZG9jdW1lbnQiLCJ3cml0ZSJdLCJ1c2VySWQiOiJyYW5kb21sRTFRdTBjN2NUIiwibGF5ZXIiOiJyYW5kb21rUWdTNGo4SnJIIn19LCJqcyI6ImxldCBpc1RhYk9yZGVySW5pdGlhbGl6ZWQ9ITE7Y29uc3QgaW5pdGlhbGl6ZVRhYk9yZGVyPWFzeW5jIGluc3RhbmNlPT57XG4vLyBSZXR1cm4gZWFybHkgaWYgYWxyZWFkeSBpbml0aWFsaXplZFxuaWYoIWlzVGFiT3JkZXJJbml0aWFsaXplZCl0cnl7XG4vLyBpbml0IHRhYiByZS1vcmRlclxuYXdhaXQgUHJvbWlzZS5hbGwoQXJyYXkuZnJvbSh7bGVuZ3RoOmluc3RhbmNlLnRvdGFsUGFnZUNvdW50fSkubWFwKCgoXyxwYWdlSW5kZXgpPT5pbnN0YW5jZS5zZXRQYWdlVGFiT3JkZXIocGFnZUluZGV4LChjdXJyZW50VGFiT3JkZXJlZEFubm90YXRpb25zPT5jdXJyZW50VGFiT3JkZXJlZEFubm90YXRpb25zLnNvcnQoKChhLGIpPT5hLmJvdW5kaW5nQm94LnRvcC1iLmJvdW5kaW5nQm94LnRvcCkpLm1hcCgoYW5ub3RhdGlvbj0%252BYW5ub3RhdGlvbi5pZCkpKSkpKSksaXNUYWJPcmRlckluaXRpYWxpemVkPSEwLGNvbnNvbGUubG9nKCdsb2FkZWQnKX1jYXRjaChlcnJvcil7dGhyb3cgY29uc29sZS5lcnJvcignRmFpbGVkIHRvIGluaXRpYWxpemUgdGFiIG9yZGVyOicsZXJyb3IpLGVycm9yfX07bGV0IGdsb2JhbEluc3RhbmNlPW51bGw7UFNQREZLaXQubG9hZCh7Li4uYmFzZU9wdGlvbnMsdGhlbWU6UFNQREZLaXQuVGhlbWUuREFSSyx0b29sYmFySXRlbXM6W3t0eXBlOidmb3JtLWNyZWF0b3InfSwuLi5QU1BERktpdC5kZWZhdWx0VG9vbGJhckl0ZW1zXSxpbml0aWFsVmlld1N0YXRlOm5ldyBQU1BERktpdC5WaWV3U3RhdGUoe3ByZXJlbmRlcmVkUGFnZVNwcmVhZHM6bnVsbH0pLHJlbmRlclBhZ2VDYWxsYmFjazpmdW5jdGlvbihjdHgscGFnZUluZGV4LHBhZ2VTaXplKXtpbml0aWFsaXplVGFiT3JkZXIoZ2xvYmFsSW5zdGFuY2UpfX0pLnRoZW4oKGFzeW5jIGluc3RhbmNlPT57Z2xvYmFsSW5zdGFuY2U9aW5zdGFuY2U7Y29uc3QgYW5ub3RhdGlvblJlb3JkZXI9YXN5bmMgYW5ub3RhdGlvbnM9Pntcbi8vZ2V0dGluZyB0aGUgY3JlYXRlZCBhbm5vdGF0aW9uXG5jb25zdCBhbm5vdGF0aW9uPWFubm90YXRpb25zPy5nZXQoMCksY3VycmVudFRhYk9yZGVyPWF3YWl0IGluc3RhbmNlLmdldFBhZ2VUYWJPcmRlcihhbm5vdGF0aW9uLnBhZ2VJbmRleCk7cmV0dXJuIGFubm90YXRpb24mJiFjdXJyZW50VGFiT3JkZXI%252FLmluY2x1ZGVzKGFubm90YXRpb24uaWQpPyhjdXJyZW50VGFiT3JkZXIucHVzaChhbm5vdGF0aW9uLmlkKSxhd2FpdCBpbnN0YW5jZS5zZXRQYWdlVGFiT3JkZXIoYW5ub3RhdGlvbi5wYWdlSW5kZXgsKGN1cnJlbnRUYWJPcmRlcmVkQW5ub3RhdGlvbnM9PmN1cnJlbnRUYWJPcmRlcmVkQW5ub3RhdGlvbnMuc29ydCgoKGEsYik9PmEuYm91bmRpbmdCb3gudG9wIT09Yi5ib3VuZGluZ0JveC50b3A%252FYS5ib3VuZGluZ0JveC50b3AtYi5ib3VuZGluZ0JveC50b3A6YS5ib3VuZGluZ0JveC5sZWZ0LWIuYm91bmRpbmdCb3gubGVmdCkpLm1hcCgoYW5ub3RhdGlvbj0%252BYW5ub3RhdGlvbi5pZCkpKSkpOmF3YWl0IGluc3RhbmNlLnNldFBhZ2VUYWJPcmRlcihhbm5vdGF0aW9uLnBhZ2VJbmRleCwoY3VycmVudFRhYk9yZGVyZWRBbm5vdGF0aW9ucz0%252BY3VycmVudFRhYk9yZGVyZWRBbm5vdGF0aW9ucy5zb3J0KCgoYSxiKT0%252BYS5ib3VuZGluZ0JveC50b3AtYi5ib3VuZGluZ0JveC50b3ApKS5tYXAoKGFubm90YXRpb249PmFubm90YXRpb24uaWQpKSkpfTtpbnN0YW5jZS5hZGRFdmVudExpc3RlbmVyKCdhbm5vdGF0aW9ucy5jcmVhdGUnLGFubm90YXRpb25SZW9yZGVyKSxpbnN0YW5jZS5hZGRFdmVudExpc3RlbmVyKCdhbm5vdGF0aW9ucy51cGRhdGUnLGFubm90YXRpb25SZW9yZGVyKX0pKTsiLCJjc3MiOiIvKiBBZGQgeW91ciBDU1MgaGVyZSAqL1xuIiwibW9kZSI6InN0YW5kYWxvbmUifQ%253D%253D).

- **Nutrient Web API documentation** — For more details on `setPageTabOrder` and related methods, refer to the [Nutrient API reference](https://www.nutrient.io/api/web/).

- **Nutrient knowledge base**— See more examples of `setPageTabOrder` use and discussion in our [knowledge base](https://www.nutrient.io/guides/web/knowledge-base/add-listener-toolbar-item.md).
---

## Related pages

- [Add Custom Keyboard Shortcuts](/guides/web/knowledge-base/add-custom-keyboard-shortcuts.md)
- [How to add a custom toolbar item to display current zoom percentage](/guides/web/knowledge-base/add-custom-zoom-perentage.md)
- [Add Listener Text Note Annotation](/guides/web/knowledge-base/add-listener-text-note-annotation.md)
- [Add Listener Toolbar Item](/guides/web/knowledge-base/add-listener-toolbar-item.md)
- [Add Signature Initials](/guides/web/knowledge-base/add-signature-initials.md)
- [Listen to an annotation’s hover event](/guides/web/knowledge-base/annotations-hover-event.md)
- [Blurry Print Resolution](/guides/web/knowledge-base/blurry-print-resolution.md)
- [Change Default Line Width Ink Annotations](/guides/web/knowledge-base/change-default-line-width-ink-annotations.md)
- [Check Document Contains Annotations](/guides/web/knowledge-base/check-document-contains-annotations.md)
- [Keep widget annotation dimensions consistent across devices](/guides/web/knowledge-base/consistent-widget-annotation-dimensions.md)
- [Customize Page Indicator](/guides/web/knowledge-base/customize-page-indicator.md)
- [Check Password Protected Files](/guides/web/knowledge-base/check-password-protected-files.md)
- [Control Appearance Of Delete Button On Ink Annotations](/guides/web/knowledge-base/control-appearance-of-delete-button-on-ink-annotations.md)
- [Create Highlight Annotations From Text Extraction Technology](/guides/web/knowledge-base/create-highlight-annotations-from-text-extraction-technology.md)
- [Default To Cloudy Border](/guides/web/knowledge-base/default-to-cloudy-border.md)
- [Delete All Annotations](/guides/web/knowledge-base/delete-all-annotations.md)
- [Deselect Text](/guides/web/knowledge-base/deselect-text.md)
- [Detect Pspdfkit Ui Loaded](/guides/web/knowledge-base/detect-pspdfkit-ui-loaded.md)
- [Determine Current Layout Mode](/guides/web/knowledge-base/determine-current-layout-mode.md)
- [Disable Context Menu](/guides/web/knowledge-base/disable-context-menu.md)
- [How to disable text annotation movement in web apps](/guides/web/knowledge-base/disable-text-annotation-movement.md)
- [Download Exported Document](/guides/web/knowledge-base/download-exported-document.md)
- [Disable Resize Of Annotations](/guides/web/knowledge-base/disable-resize-of-annotations.md)
- [Export Ink Annotation Image](/guides/web/knowledge-base/export-ink-annotation-image.md)
- [Find Ink Annotation For Signature Form Field](/guides/web/knowledge-base/find-ink-annotation-for-signature-form-field.md)
- [Focus Viewer After Loading](/guides/web/knowledge-base/focus-viewer-after-loading.md)
- [Focus the delete button in a confirm dialog](/guides/web/knowledge-base/focus-delete-button-in-confirm-modal-component.md)
- [Extracting text and cursor position in annotations](/guides/web/knowledge-base/extract-annotation-text-and-retrieve-cursor-position.md)
- [Focus Widget Annotation](/guides/web/knowledge-base/focus-widget-annotation.md)
- [Get Entered Document Password](/guides/web/knowledge-base/get-entered-document-password.md)
- [Fix errors with unsupported form field actions](/guides/web/knowledge-base/handle-unsupported-form-field-actions.md)
- [Get Visible Annotations](/guides/web/knowledge-base/get-visible-annotations.md)
- [Handling Clicks On Custom Overlays](/guides/web/knowledge-base/handling-clicks-on-custom-overlays.md)
- [Highlight required form fields](/guides/web/knowledge-base/highlight-required-fields.md)
- [How Do I Limit The Number Of Annotations](/guides/web/knowledge-base/how-do-i-limit-the-number-of-annotations.md)
- [How Do I Disable Scrolling On Page Edges](/guides/web/knowledge-base/how-do-i-disable-scrolling-on-page-edges.md)
- [How Do I Prevent Printing Annotations](/guides/web/knowledge-base/how-do-i-prevent-printing-annotations.md)
- [Resize multiline text fields to avoid overflow](/guides/web/knowledge-base/how-do-i-resize-form-fields.md)
- [How Do I Toggle The Theme](/guides/web/knowledge-base/how-do-i-toggle-the-theme.md)
- [How Do I Rotate A Page](/guides/web/knowledge-base/how-do-i-rotate-a-page.md)
- [How Do I Zoom To A Specific Value](/guides/web/knowledge-base/how-do-i-zoom-to-a-specific-value.md)
- [How To Create Bookmarks From Outline Elements](/guides/web/knowledge-base/how-to-create-bookmarks-from-outline-elements.md)
- [Image Attachments Lost Stamp Annotation Templates](/guides/web/knowledge-base/image-attachments-lost-stamp-annotation-templates.md)
- [License Registered Different Bundle Id](/guides/web/knowledge-base/license-registered-different-bundle-id.md)
- [Iterate over form fields and widgets](/guides/web/knowledge-base/iterate-over-form-fields.md)
- [Load Pdf As Arraybuffer](/guides/web/knowledge-base/load-pdf-as-arraybuffer.md)
- [Link Text](/guides/web/knowledge-base/link-text.md)
- [Load Pdf From Stream](/guides/web/knowledge-base/load-pdf-from-stream.md)
- [Loading Multiple Files](/guides/web/knowledge-base/loading-multiple-files.md)
- [Nutrient Size Optimization](/guides/web/knowledge-base/nutrient-size-optimization.md)
- [Load Pdf Stub From String](/guides/web/knowledge-base/load-pdf-stub-from-string.md)
- [Disabling automatic synchronization in Nutrient Web SDK](/guides/web/knowledge-base/manual-instant-sync.md)
- [Observe Document Editor Visibility](/guides/web/knowledge-base/observe-document-editor-visibility.md)
- [Override Ink Signature Dialog](/guides/web/knowledge-base/override-ink-signature-dialog.md)
- [Override User Agent](/guides/web/knowledge-base/override-user-agent.md)
- [Persist Currently Edited Note Test](/guides/web/knowledge-base/persist-currently-edited-note-test.md)
- [Overview](/guides/web/knowledge-base/overview.md)
- [Prevent Shortcut Printing](/guides/web/knowledge-base/prevent-shortcut-printing.md)
- [Persist Ink Signatures Across Instances](/guides/web/knowledge-base/persist-ink-signatures-across-instances.md)
- [Place Annotation At Visible Center](/guides/web/knowledge-base/place-annotation-at-visible-center.md)
- [Prevent Editing Content Text Annotation](/guides/web/knowledge-base/prevent-editing-content-text-annotation.md)
- [Process Currently Rendered Pages](/guides/web/knowledge-base/process-currently-rendered-pages.md)
- [Programmatically Navigate To Page](/guides/web/knowledge-base/programmatically-navigate-to-page.md)
- [Render Document Full Height](/guides/web/knowledge-base/render-document-full-height.md)
- [Programmatic Comment Annotations](/guides/web/knowledge-base/programmatic-comment-annotations.md)
- [Read-only forms](/guides/web/knowledge-base/read-only-forms.md)
- [Render Night Mode](/guides/web/knowledge-base/render-night-mode.md)
- [Render Page Black White](/guides/web/knowledge-base/render-page-black-white.md)
- [Render Visible Area In Current Page](/guides/web/knowledge-base/render-visible-area-in-current-page.md)
- [Render Page Without Annotations](/guides/web/knowledge-base/render-page-without-annotations.md)
- [Render Watermark When Printing](/guides/web/knowledge-base/render-watermark-when-printing.md)
- [Restore Last Seen Page](/guides/web/knowledge-base/restore-last-seen-page.md)
- [Save Modified Pdf To Document Engine](/guides/web/knowledge-base/save-modified-pdf-to-document-engine.md)
- [Show Annotations Properties As Tooltip](/guides/web/knowledge-base/show-annotations-properties-as-tooltip.md)
- [Rotate Ink Annotation](/guides/web/knowledge-base/rotate-ink-annotation.md)
- [Show Focus Ring Read Only](/guides/web/knowledge-base/show-focus-ring-read-only.md)
- [Submit Ink Signatures With Form](/guides/web/knowledge-base/submit-ink-signatures-with-form.md)
- [Wait For Element Appear](/guides/web/knowledge-base/wait-for-element-appear.md)
- [Web Sdk Vs Dws Viewer](/guides/web/knowledge-base/web-sdk-vs-dws-viewer.md)
- [Easily zoom to specific annotations in PDF](/guides/web/knowledge-base/zoom-to-specific-annotation.md)

