Welcome What's new in Chrome extensions API reference Samples
Welcome What's new in Chrome extensions API reference Samples

Design the user interface

Published on Updated on

Like Chrome's user interface, an extension user interface should be purposeful and minimal. Extensions should allow users to customize or enhance the user's browsing experience without distracting from it.

This guide explores required and optional user interface features. Use it to understand how and when to implement different user interface elements within an extension.

The extension action

The Action API controls the extension's action (toolbar icon). It can either open a popup or trigger some functionality when it's clicked.

Users can trigger an extension's action by expanding the extension menu and selecting the desired extension.

To make it easier to access an extension, the user may choose to pin the extension's action to the toolbar. Once pinned, the extension's action will appear to the left of the extension menu. Users can rearrange their pinned extensions by dragging and dropping their action icons to the desired order.

Unpinned extension
Unpinned extension.
Pinned extension
Pinned extension.

Register the action

To use the Action API, the extension's manifest must contain an "action" key. This informs the browser that the extension will customize the action.

manifest.json:

{
"name": "My Awesome action MV3 Extension",
...
"action": {
...
}
...
}

See the manifest section of the Action API docs for a full description of the optional properties of this field.

Activate the action conditionally

The DeclarativeContent API allows you to enable the extension's action based on the page URL or when the CSS selectors match the elements on the page.

When an extension is disabled, the icon is grayed out. If the user clicks the disabled extension, the extension's context menu will appear.

Clicked Disabled extension
Disabled extension.

Respond to the action

It's possible to register an OnClicked handler for when the user clicks the action item. However, this won't fire if the action has a popup (default or otherwise).

service-worker.js:

chrome.action.onClicked.addListener((tab) => {
chrome.action.setTitle({tabId: tab.id, title: `You are on tab: ${tab.id}`});
});

Action badge

Badges display a colored banner on top of the action icon. They can only be used when the "action" is declared in the manifest.

Use badges to indicate the state of the extension. The Drink Water sample extension displays a badge with "ON" to show the user they have successfully set an alarm and displays nothing when the extension is idle. Badges can contain up to 4 characters.

Badge On
An action icon with a badge.
Badge Off
An action icon without a badge.

You can set the text of the badge by calling chrome.action.setBadgeText() and the banner color by calling chrome.action.setBadgeBackgroundColor().

service-worker.js:

chrome.action.setBadgeText({text: 'ON'});
chrome.action.setBadgeBackgroundColor({color: '#4688F1'});

Designate action icons

Icons specific to the toolbar are registered in the "default_icon" field under "action" in the manifest. Including multiple sizes is encouraged to scale for the 16-dip space. At minimum, 16x16 and 32x32 sizes are recommended.

manifest.json:

{
"name": "My Awesome Extension",
...
"action": {
"default_icon": {
"16": "extension_toolbar_icon16.png",
"32": "extension_toolbar_icon32.png"
}
}
...
}

A popup is an HTML file that is displayed in a special window when the user clicks the action icon. A popup works similarly to a web page; it can contain links in style and script tags, but does not allow inline JavaScript.

The Drink Water Event example popup displays available timer options. Users set an alarm by clicking one of the provided buttons.

The Drink Water popup
The Drink Water popup.

popup.html:

<html>
<head>
<title>Water Popup</title>
</head>
<body>
<img src="./stay_hydrated.png" id="hydrateImage">
<button id="sampleSecond" value="0.1">Sample Second</button>
<button id="min15" value="15">15 Minutes</button>
<button id="min30" value="30">30 Minutes</button>
<button id="cancelAlarm">Cancel Alarm</button>
<script src="popup.js"></script>
</body>
</html>

The popup is registered in the manifest under the "action" key.

manifest.json:

{
"name": "Drink Water Event",
...
"action": {
"default_popup": "popup.html"
}
...
}

Popups can also be set dynamically by calling action.setPopup().

???:

chrome.storage.local.get('signed_in', (data) => {
if (data.signed_in) {
chrome.action.setPopup({popup: 'popup.html'});
} else {
chrome.action.setPopup({popup: 'popup_sign_in.html'});
}
});

Tooltip

Use a tooltip to give short descriptions or instructions to users when they hover over the action icon. By default, the tootip displays the name of the extension.

An example tooltip
An example tooltip.

Provide the extension icons

An extension requires at least one icon to represent it. Provide icons in PNG format for the best visual results, although any raster format supported by Chrome is accepted. This includes BMP, GIF, ICO, and JPEG.

Caution

SVG files are not supported for any icons declared in the manifest.

Ensure your icon follows the extension icon best practices.

All icons should be square or they may be distorted. If no icons are supplied, Chrome will add a generic one to the toolbar with the first letter of the extension name.

Include additional icons in the following sizes for uses outside of the toolbar.

Icon SizeIcon Use
16x16Favicon on the extension's pages and context menu icon.
32x32Windows computers often require this size.
48x48Displays on the extension management page.
128x128Displays on installation and in the Chrome Web Store.

Register icons in the manifest under the "icons" field.

manifest.json:

{
"name": "My Awesome Extension",
...
"icons": {
"16": "extension_icon16.png",
"32": "extension_icon32.png",
"48": "extension_icon48.png",
"128": "extension_icon128.png"
}
...
}

Additional user interface features

Side panel

An extension side panel is an HTML file that provides additional functionality alongside the main content of a web page. The Dictionary side panel example allows users to right-click on a word and see the definition in the side panel.

Selecting the Dictionary side panel
Dictionary side panel extension.
Dictionary side panel context menu choosing the word extensions
Dictionary extension defining the word "Extensions".

For more samples and use cases, see the Side Panel API reference page.

Tooltips are registered in the "default_title" field under the "action" key in the manifest.

manifest.json:

{
"name": "Tab Flipper",
...
"action": {
"default_title": "Press Ctrl(Win)/Command(Mac)+Shift+Right/Left to flip tabs"
}
...
}

Tooltips can also be set or updated by calling action.setTitle().

Omnibox

Users can invoke extension functionality through the Omnibox API. Include the "omnibox" field in the manifest and designate a keyword. The Omnibox New Tab Search sample extension uses nt as the keyword.

manifest.json:

{
"name": "Omnibox New Tab Search",
...
"omnibox": { "keyword" : "nt" },
"default_icon": {
"16": "newtab_search16.png",
"32": "newtab_search32.png"
}
...
}

When the user types "nt" into the omnibox, it activates the extension. To signal this to the user, it grayscales the provided 16x16 icon and includes it in the omnibox next to the extension name.

An example of Omnibox functionality
An example of Omnibox functionality.

The extension listens to the omnibox.onInputEntered event. After it's triggered, the extension opens a new tab containing a Google search for the user's entry.

service-worker.js:

chrome.omnibox.onInputEntered.addListener((text) => {
// Encode user input for special characters , / ? : @ & = + $ #
const newURL = `https://www.google.com/search?q=${encodeURIComponent(text)}`;
chrome.tabs.create({ url: newURL });
});

Context menu

You can use the ContextMenus API by granting the "contextMenus" permission in the manifest.

manifest.json:

{
"name": "Global Google Search",
...
"permissions": [
"contextMenus",
"storage"
],
"icons": {
"16": "globalGoogle16.png",
"48": "globalGoogle48.png",
"128": "globalGoogle128.png"
}
...
}

The 16x16 icon is displayed next to the new menu entry.

A context menu icon
A context menu icon.

Create a context menu by calling contextMenus.create() in the service worker. Do this in the runtime.onInstalled event listener.

service-worker.js:

chrome.runtime.onInstalled.addListener(async () => {
for (let [tld, locale] of Object.entries(tldLocales)) {
chrome.contextMenus.create({
id: tld,
title: locale,
type: 'normal',
contexts: ['selection'],
});
}
});

locals.js:

const tldLocales = {
'com.au': 'Australia',
'com.br': 'Brazil',
'ca': 'Canada',
'cn': 'China',
'fr': 'France',
'it': 'Italy',
'co.in': 'India',
'co.jp': 'Japan',
'com.ms': 'Mexico',
'ru': 'Russia',
'co.za': 'South Africa',
'co.uk': 'United Kingdom'
};

The Global Google Search context menu example provides multiple context menu options based on the list in locales.js (see above). When an extension contains more than one context menu, Chrome automatically collapses them into a single parent menu (see below).

Multiple context menus will collapse
Multiple context menus will collapse.

Commands

Use the Commands API to define commands and bind them to a key combination. Register one or more shortcuts in the manifest under the "commands" key.

manifest.json:

{
"name": "Tab Flipper",
...
"commands": {
"flip-tabs-forward": {
"suggested_key": {
"default": "Ctrl+Shift+Right",
"mac": "Command+Shift+Right"
},
"description": "Flip tabs forward"
},
"flip-tabs-backwards": {
"suggested_key": {
"default": "Ctrl+Shift+Left",
"mac": "Command+Shift+Left"
},
"description": "Flip tabs backwards"
}
}
...
}

Use commands to provide new or alternative browser shortcuts. The Tab Flipper sample extension listens to the commands.onCommand event in the service worker and defines functionality for each registered combination.

service-worker.js:


chrome.commands.onCommand.addListener((command) => {
// command will be "flip-tabs-forward" or "flip-tabs-backwards"

chrome.tabs.query({currentWindow: true}, tabs => {
// Sort tabs according to their index in the window.
tabs.sort((a, b) => a.index - b.index);
const activeIndex = tabs.findIndex((tab) => tab.active);
const lastTab = tabs.length - 1;
let newIndex = -1;
if (command === 'flip-tabs-forward') {
newIndex = activeIndex === 0 ? lastTab : activeIndex - 1;
} else { // 'flip-tabs-backwards'
newIndex = activeIndex === lastTab ? 0 : activeIndex + 1;
}
chrome.tabs.update(tabs[newIndex].id, {active: true, highlighted: true});
});
});

Override pages

An extension can override one of thee possible pages:

  • History
  • New tab
  • Bookmarks

Use a custom HTML file to do this. As with a popup, it can include specialized logic and style, but does not allow inline JavaScript. Register it in the manifest under the "chrome_url_overrides" field.

manifest.json:

{
"name": "Awesome Override Extension",
...

"chrome_url_overrides" : {
"newtab": "override_page.html"
},
...
}

The "newtab" field should be replaced with "bookmarks" or "history" when overriding those pages.

override_page.html:

<html>
<head>
<title>New Tab</title>
</head>
<body>
<h1>Hello World</h1>
<script src="logic.js"></script>
</body>
</html>

Notifications

You can communicate relevant information to users by displaying notifications directly in their system tray. To use the Notifications API, you must declare the "notifications" permission in the manifest.

manifest.json:

{
"name": "Drink Water Event Popup",
...
"permissions": [
"alarms",
"notifications",
"storage"
],
...
}

Once the permission is declared, you can display a notification by calling notifications.create().

service-worker.js:

function showStayHydratedNotification() {
chrome.notifications.create({
type: 'basic',
iconUrl: 'stay_hydrated.png',
title: 'Time to Hydrate',
message: 'Everyday I\'m Guzzlin\'!',
buttons: [
{ title: 'Keep it Flowing.' }
],
priority: 0
});
}
Mac OS notification
Notification on macOS.

Internationalize the user interface

You can use the I18n API to internationalize your extension. Create directories to house language specific messages within a folder called _locales/, like this:

  • _locales/en/messages.json
  • _locales/es/messages.json

Format messages inside of each language's messages.json. For example, the following code localizes the tooltip:

_locales/en/messages.json:

{
"__MSG_tooltip__": {
"message": "Hello!",
"description": "Tooltip"
}
}

_locales/es/messages.json:

{
"__MSG_tooltip__": {
"message": "Hola!",
"description": "Tooltip"
}
}

Specify the name of the message in the "default_title" field of the manifest. The "default_locale" field must be defined.

manifest.json:

{
"name": "Tab Flipper",
...
"action": {
"default_title": "__MSG_tooltip__"
},
"default_locale": "en"
...
}

Continue exploring

See the Action API example for a complete demonstration of the action APIs capabilities.

Updated on Improve article

This site uses cookies to deliver and enhance the quality of its services and to analyze traffic. If you agree, cookies are also used to serve advertising and to personalize the content and advertisements that you see. Learn more about our use of cookies.