Formatting Toolbar

The Formatting Toolbar appears whenever you highlight text in the editor.

image

Changing the Formatting Toolbar

You can change or replace the Formatting Toolbar with your own React component. In the demo below, 2 buttons are added to the default Formatting Toolbar - one to add a blue text/background, and one to toggle code styles.

We first define our custom BlueButton. The useComponentsContext hook gets all components used internally by BlockNote, so we want to use Components.FormattingToolbar.Button for this.

We use the FormattingToolbar component to create a custom Formatting Toolbar. By specifying its children, we can replace the default buttons in the toolbar with our own.

This custom Formatting Toolbar is passed to a FormattingToolbarController, which controls its position and visibility (above or below the highlighted text).

Setting formattingToolbar={false} on BlockNoteView tells BlockNote not to show the default Formatting Toolbar.

Changing Block Type Select (Dropdown) Items

The first element in the default Formatting Toolbar is the Block Type Select, and you can change the items in it. The demo makes the Block Type Select work for image blocks by adding an item to it.

Here, we use the FormattingToolbar component but keep the default buttons (we don't pass any children). Instead, we pass our customized Block Type Select items using the blockTypeSelectItems prop.

Mobile Formatting Toolbar

On touch devices, BlockNote's default UI replaces the floating Formatting Toolbar with a mobile Formatting Toolbar that sits just above the on-screen keyboard. It shows the same items as the regular Formatting Toolbar and is enabled by default - there's nothing to set up. Open any of the examples above on a phone to see it.

The mobile Formatting Toolbar works with two page layouts. Which one you get is decided purely by your app's CSS:

  • Scrolling document (the default): the page scrolls as usual and BlockNote repositions the toolbar as you scroll.
  • Pinned scroll container: the document itself doesn't scroll; a container pinned to the visual viewport scrolls instead, and the toolbar never has to move.

Scrolling document

This is what you get without any changes to your app. The toolbar follows the visible area above the keyboard as the page scrolls. Mobile browsers only report visual viewport changes after the fact, so the toolbar can lag or jitter slightly while the page is scrolling. If that matters for your app, switch to a pinned scroll container.

Pinned scroll container

In this layout, <html> and <body> are locked and all page content lives inside a single scroll container that BlockNote keeps aligned with the visual viewport. Since the document never scrolls, the toolbar can stay at a truly fixed position and the lag/jitter disappears. The trade-off is that browser gestures which rely on document scrolling, like pull-to-refresh, no longer work.

Setting it up takes two CSS rules. First, lock scrolling on the document:

html,
body {
  margin: 0;
  overflow: hidden;
}

Then make your scroll container (.scroll-host in the example below) the element that actually scrolls, and pin it to the visual viewport using the --bn-vv-* CSS variables that BlockNote publishes on <html>:

.scroll-host {
  position: fixed;
  top: var(--bn-vv-top, 0px);
  left: var(--bn-vv-left, 0px);
  width: var(--bn-vv-width, 100vw);
  height: var(--bn-vv-height, 100dvh);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
}

BlockNote keeps --bn-vv-top, --bn-vv-left, --bn-vv-width, and --bn-vv-height (plus --bn-vv-scale, the pinch-zoom factor) up to date as the keyboard opens and closes and as the user pans or zooms, so the scroll container always lines up with the visible area above the keyboard without any JavaScript on your end.

Because this layout changes how the whole page scrolls, the example can't be embedded here - open the standalone example on a phone instead. It puts a navigation bar, some static text, and the editor inside a .scroll-host styled as above, and the switch in the navigation bar toggles the pinned scroll container layout on and off so you can compare it with the default scrolling document. Select some text and scroll in each layout to see the difference.