Skip to main content
Chrome and Firefox both show an extension page next to the current tab. Chrome calls it a side panel and Firefox calls it a sidebar. The manifest key, the permission, and the runtime API are different in each browser. This page shows the two APIs side by side and one codebase that builds for both.

Which API each browser uses

Firefox does not have chrome.sidePanel, and Chrome does not have sidebarAction. Safari has neither. See Building Safari extensions for the guard that keeps a Safari background alive.

Declare the panel in the manifest

Use browser prefixes so that each build gets its own key:
manifest.json
The browser-specific fields page explains the prefixes. The path resolution page shows where the panel page goes in dist/. The available browsers page lists the targets that each prefix reaches. Three rules apply to this manifest:
  • Chrome needs the sidePanel permission. Without it, Chrome shows no panel. The build does not add it for a side_panel key that you wrote.
  • A prefixed key replaces the plain key. If you also write a plain permissions list, chromium:permissions replaces it on Chromium builds. Put every Chromium permission in chromium:permissions.
  • One key alone still gives Firefox a sidebar. With Extension.js 4.1.33, a manifest that declares only side_panel builds for Firefox with a sidebar_action key that points at the same page. The build prints a warning when it does this. Declare both keys to control each browser yourself.

Runtime API: chrome.sidePanel vs browser.sidebarAction

Notes on the table:
  • sidePanel.close() exists from Chrome 141. It does nothing when the panel is already closed. From Chrome 145, close({ tabId }) rejects when only the global panel is open. Before Chrome 145, the same call closed the global panel.
  • Chrome has no isOpen(). To know the state, listen to onOpened and onClosed.
  • Firefox setPanel, setTitle, and setIcon fail if you pass both tabId and windowId. Pass one, or pass neither to change the global value.
  • Chrome has no title or icon API for the panel. Chrome shows the extension icon in the side panel menu. chrome.action.setTitle and chrome.action.setIcon change the toolbar button only.
The versions come from the Chrome sidePanel reference and the MDN sidebarAction reference.

User gesture rules

Both browsers open a panel only when the user does something. The rules are not the same:
  • Firefox: open(), close(), and toggle() work only inside the handler for a user action. A toolbar click, a context menu item, a keyboard command, and a button on an extension page all count.
  • Chromium: open() works only after a user gesture. A toolbar click, a keyboard command, a context menu item, and a click on an extension page or in a content script all count. close() has no gesture rule in the Chrome reference.
  • The toolbar click is the exception on Chromium. Call setPanelBehavior once, at the top level of the background script. After that, a toolbar click opens the panel and your code does not run.
Call open() directly in the handler. Do not await anything before the call. A handler that waits for a promise loses its user gesture, and the call fails.

Open the panel from the toolbar button

This background script gives each browser its own path. The check runs at build time, so each bundle keeps only its own half:
background.js
Call setPanelBehavior at the top level, not inside a click handler. The behavior applies to the next clicks only, so a call from inside the first click leaves that first click with no panel. The Firefox half uses browserAction because the manifest above builds Firefox as Manifest V2. See environment variables for the value of EXTENSION_PUBLIC_BROWSER on each target.

Open the panel from your own gesture

To open the panel from a context menu, a button, or a shortcut, test for the API at runtime. Branch on sidebarAction.open, the method that you call, and not on the browser object alone:
background.js
Add contextMenus to both permission lists:
manifest.json
openPanel calls open() with no await before it, so the gesture from the menu click is still valid.

Firefox builds warn about chrome.sidePanel

From 4.1.18, a production build for Firefox warns when the bundle reads chrome.sidePanel. The build still succeeds. The runtime check in the previous section triggers this warning, because the Firefox bundle still contains the chrome.sidePanel.open call. The isFirefoxLike check from the toolbar sample does not trigger it, because the build removes the Chromium half. See Firefox builds warn about Chromium-only APIs for the full message and the fix. To clear the warning in the context menu sample, replace the runtime check in openPanel with isFirefoxLike.

Next steps