← Back to blog
Tutorial · 6 min read

Chrome Extension Popup Tutorial: Build a Toolbar UI

How to build a popup UI for a Chrome extension — markup, scripts, sizing and messaging — without hitting Manifest V3 CSP errors.

Illustration for the ManifestGo article: Chrome Extension Popup Tutorial: Build a Toolbar UI

The popup is the small panel that opens when a user clicks your toolbar icon. It is a normal HTML page with extension privileges, but a few Manifest V3 rules trip people up on their first build.

Wire the popup into the manifest

Add "action": { "default_popup": "popup.html" } to manifest.json. Chrome opens that file each time the icon is clicked, and closes it whenever focus is lost — so the popup has no long-lived state.

Write CSP-safe code

  • No inline <script> blocks and no onclick attributes — both are blocked by MV3 CSP.
  • Load popup.js with a <script src="popup.js"></script> tag at the end of the body.
  • Attach handlers with addEventListener inside a DOMContentLoaded listener.
  • No remote CDN scripts or fonts; bundle everything locally.

Sizing the popup

Chrome sizes the popup to its content, up to 800x600. Set an explicit width (320–420px is comfortable) on the body and avoid percentage heights, which collapse to zero.

Talking to the service worker

Use chrome.runtime.sendMessage from the popup and chrome.runtime.onMessage.addListener in background.js. Because the popup dies on close, persist anything durable with chrome.storage rather than in-memory variables.

Frequently asked questions

Why is my popup blank?

Usually an inline script blocked by CSP or a wrong file path in default_popup. Right-click the icon and choose Inspect popup to see the console error.

Can the popup stay open when I click the page?

No. Popups close on blur. Use a side panel or an injected content-script UI if you need a persistent surface.

Keep reading