title | slug | page-type | browser-compat | |||||
---|---|---|---|---|---|---|---|---|
Browser styles |
Mozilla/Add-ons/WebExtensions/user_interface/Browser_styles |
guide |
|
{{AddonSidebar}}
Your extension can include user interface components - browser and page action popups, sidebars, and options pages - that are specified by:
- creating an HTML file defining the structure of the UI element.
- adding a manifest.json key (
action
,browser_action
,page_action
,sidebar_action
, oroptions_ui
) pointing to that HTML file.
You can style these elements to match the browser's style. The manifest.json keys include an optional property to help with this: browser_style
. If this is included and set to true
, your document gets one or more extra stylesheets that help make it look consistent with the browser's UI and with other extensions that use the browser_style
property.
Note: Support for
browser_style
in Manifest V3 has been deprecated and, from Firefox 115,options_ui.browser_style
andsidebar_action.browser_style
default tofalse
.page_action.browser_style
,browser_action.browser_style
, andaction.browser_style
already defaults tofalse
. If your Manifest V3 extension depends on thebrowser_style: true
styles, bundle this stylesheet in the extension: extension.css. See (Firefox bug 1827910) for more information.
When considering whether to use browser_style: true, test your extension with various themes (built-in or from AMO) to ensure that the extension UI behaves the way you expect it to.
Warning: When
browser_style: true
is included in your web extension's manifest, text selection in your extension's UI is disabled except in input controls. If this causes a problem, includebrowser_style:false
instead.
Note: Google Chrome and Opera use
chrome_style
instead ofbrowser_style
, so you need to add both keys to support them.
In Firefox, the stylesheet can be seen at chrome://browser/content/extension.css
. The extra stylesheet at chrome://browser/content/extension-mac.css
is also included on macOS.
Most styles are automatically applied, but some elements require you to add the non-standard browser-style
class to get their styling, as detailed in the table below:
Element | Example |
---|---|
<button>
|
<button class="browser-style">Click me</button> |
<select class="browser-style" name="select"> <option value="value1">Value 1</option> <option value="value2" selected>Value 2</option> <option value="value3">Value 3</option> </select> |
|
<textarea>
|
<textarea class="browser-style">Write here</textarea> |
Parent of an
<input>
|
<div class="browser-style"> <input type="radio" id="op1" name="choices" value="op1"/> <label for="op1">Option 1</label> |
Note: See Firefox bug 1465256 for removal of this unnecessary requirement.
{{Compat}}
Note: This feature is non-standard and only works in Firefox.
The chrome://browser/content/extension.css
stylesheet also contains the styles for the Firefox Panel Components.
The legacy Firefox Style Guide documents proper usage.
Element | Example |
---|---|
Header |
<header class="panel-section panel-section-header"> <div class="icon-section-header"><img src="image.svg"/></div> <div class="text-section-header">Header</div> </header> |
Footer |
<footer class="panel-section panel-section-footer"> <button class="panel-section-footer-button">Cancel</button> <div class="panel-section-footer-separator"></div> <button class="panel-section-footer-button default">Confirm</button> </footer> |
Tabs |
<div class="panel-section panel-section-tabs"> <button class="panel-section-tabs-button selected">Tab</button> <div class="panel-section-tabs-separator"></div> <button class="panel-section-tabs-button">Tab</button> <div class="panel-section-tabs-separator"></div> <button class="panel-section-tabs-button">Tab</button> </div> |
Form |
<div class="panel-section panel-section-formElements"> <div class="panel-formElements-item"> <label for="name01">Label:</label> <input type="text" value="Name" id="name01" /> </div> <div class="panel-formElements-item"> <label for="picker01">Label:</label> <select id="picker01"> <option value="value1" selected="true">Dropdown</option> <option value="value2">List Item</option> <option value="value3">List Item</option> </select> </div> <div class="panel-formElements-item"> <label for="placeholder01">Label:</label> <input type="text" placeholder="Placeholder" id="placeholder01" /> <button name="expander" class="expander"></button> </div> </div> |
Menu |
<div class="panel-section panel-section-list"> <div class="panel-list-item"> <div class="icon"></div> <div class="text">List Item</div> <div class="text-shortcut">Ctrl-L</div> </div> |
<header class="panel-section panel-section-header">
<div class="icon-section-header"><!-- An image goes here. --></div>
<div class="text-section-header">Header</div>
</header>
<div class="panel-section panel-section-list">
<div class="panel-list-item">
<div class="icon"></div>
<div class="text">List Item</div>
<div class="text-shortcut">Ctrl-L</div>
</div>
<div class="panel-list-item">
<div class="icon"></div>
<div class="text">List Item</div>
<div class="text-shortcut"></div>
</div>
<div class="panel-section-separator"></div>
<div class="panel-list-item disabled">
<div class="icon"></div>
<div class="text">Disabled List Item</div>
<div class="text-shortcut"></div>
</div>
<div class="panel-section-separator"></div>
<div class="panel-list-item">
<div class="icon"></div>
<div class="text">List Item</div>
<div class="text-shortcut"></div>
</div>
<div class="panel-list-item">
<div class="icon"></div>
<div class="text">List Item</div>
<div class="text-shortcut"></div>
</div>
</div>
<footer class="panel-section panel-section-footer">
<button class="panel-section-footer-button">Cancel</button>
<div class="panel-section-footer-separator"></div>
<button class="panel-section-footer-button default">Confirm</button>
</footer>
/* Global */
html,
body {
background: white;
box-sizing: border-box;
color: #222426;
cursor: default;
display: flex;
flex-direction: column;
font: caption;
margin: 0;
padding: 0;
-moz-user-select: none;
}
body * {
box-sizing: border-box;
text-align: start;
}
button.panel-section-footer-button,
button.panel-section-tabs-button {
color: inherit;
background-color: unset;
font: inherit;
text-shadow: inherit;
appearance: none;
border: none;
}
/* Panel Section */
.panel-section {
display: flex;
flex-direction: row;
}
.panel-section-separator {
background-color: rgba(0, 0, 0, 0.15);
min-height: 1px;
}
/* Panel Section - Header */
.panel-section-header {
border-bottom: 1px solid rgba(0, 0, 0, 0.15);
padding: 16px;
}
.panel-section-header > .icon-section-header {
background-position: center center;
background-repeat: no-repeat;
height: 32px;
margin-right: 16px;
position: relative;
width: 32px;
}
.panel-section-header > .text-section-header {
align-self: center;
font-size: 1.385em;
font-weight: lighter;
}
/* Panel Section - List */
.panel-section-list {
flex-direction: column;
padding: 4px 0;
}
.panel-list-item {
align-items: center;
display: flex;
flex-direction: row;
height: 24px;
padding: 0 16px;
}
.panel-list-item:not(.disabled):hover {
background-color: rgba(0, 0, 0, 0.06);
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
border-top: 1px solid rgba(0, 0, 0, 0.1);
}
.panel-list-item:not(.disabled):hover:active {
background-color: rgba(0, 0, 0, 0.1);
}
.panel-list-item.disabled {
color: #999;
}
.panel-list-item > .icon {
flex-grow: 0;
flex-shrink: 0;
}
.panel-list-item > .text {
flex-grow: 10;
}
.panel-list-item > .text-shortcut {
color: #808080;
font-family: "Lucida Grande", caption;
font-size: 0.847em;
justify-content: flex-end;
}
.panel-section-list .panel-section-separator {
margin: 4px 0;
}
/* Panel Section - Footer */
.panel-section-footer {
background-color: rgba(0, 0, 0, 0.06);
border-top: 1px solid rgba(0, 0, 0, 0.15);
color: #1a1a1a;
display: flex;
flex-direction: row;
height: 41px;
margin-top: -1px;
padding: 0;
}
.panel-section-footer-button {
flex: 1 1 auto;
height: 100%;
margin: 0 -1px;
padding: 12px;
text-align: center;
}
.panel-section-footer-button > .text-shortcut {
color: #808080;
font-family: "Lucida Grande", caption;
font-size: 0.847em;
}
.panel-section-footer-button:hover {
background-color: rgba(0, 0, 0, 0.06);
}
.panel-section-footer-button:hover:active {
background-color: rgba(0, 0, 0, 0.1);
}
.panel-section-footer-button.default {
background-color: #0996f8;
box-shadow: 0 1px 0 #0670cc inset;
color: #fff;
}
.panel-section-footer-button.default:hover {
background-color: #0670cc;
box-shadow: 0 1px 0 #005bab inset;
}
.panel-section-footer-button.default:hover:active {
background-color: #005bab;
box-shadow: 0 1px 0 #004480 inset;
}
.panel-section-footer-separator {
background-color: rgba(0, 0, 0, 0.1);
width: 1px;
z-index: 99;
}
/* Example specific – not part of chrome://browser/content/extension.css */
body {
background: #fcfcfc;
background-clip: padding-box;
border: 1px solid rgba(24, 26, 27, 0.2);
box-shadow: 0 3px 5px rgba(24, 26, 27, 0.1), 0 0 7px rgba(24, 26, 27, 0.1);
box-sizing: content-box;
margin: 2em auto 0.5em;
width: 384px;
}
html {
min-height: 100vh;
}
html > body {
margin: auto;
}
.icon-section-header {
background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiIgdmlld0JveD0iMCAwIDMyIDMyIj48Y2lyY2xlIGZpbGw9IiMzNjM5NTkiIGN4PSIxNSIgY3k9IjE1IiByPSIxNSIvPjwvc3ZnPg==");
}
{{EmbedLiveSample("Example","640","360")}}