Source code
Revision control
Copy as Markdown
Other Tools
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
:root {
--toolbar-start-end-padding: 8px;
--toolbarbutton-outer-padding: 2px;
--toolbarbutton-inner-padding: 8px;
--toolbarbutton-hover-background: color-mix(in srgb, currentColor 17%, transparent);
--toolbarbutton-active-background: color-mix(in srgb, currentColor 30%, transparent);
--toolbarbutton-outline-color: transparent;
--toolbarbutton-hover-outline-color: transparent;
--toolbarbutton-active-outline-color: transparent;
--toolbarbutton-selected-outline-color: var(--toolbarbutton-active-outline-color);
--toolbarbutton-outline: 1px solid var(--toolbarbutton-outline-color);
--toolbarbutton-outline-offset: -1px;
@media (prefers-contrast) {
--toolbarbutton-hover-outline-color: currentColor;
--toolbarbutton-active-outline-color: currentColor;
}
@media (forced-colors) {
--toolbarbutton-outline-color: ButtonText;
--toolbarbutton-hover-outline-color: SelectedItem;
--toolbarbutton-active-outline-color: ButtonText;
--toolbarbutton-selected-outline-color: SelectedItem;
&[lwtheme] {
--toolbarbutton-outline-color: currentColor;
}
}
--toolbarseparator-color: color-mix(in srgb, currentColor 60%, transparent);
--bookmark-block-padding: 4px;
&[uidensity=compact] {
--toolbarbutton-outer-padding: 3px;
--toolbarbutton-inner-padding: 6px;
--bookmark-block-padding: 1px;
}
&[uidensity=touch] {
--toolbarbutton-inner-padding: 9px;
--bookmark-block-padding: 7px;
}
}
#TabsToolbar {
/* Override the inner padding to ensure the dimensions match the tabs, but also making sure
different types of buttons (combined-buttons-dropmarker or text) still look correct. */
--toolbarbutton-inner-padding: calc((var(--tab-min-height) - 16px) / 2);
}
/* Primary toolbar buttons */
.toolbarbutton-1 {
:root:not([customizing]) &[disabled] {
opacity: var(--toolbarbutton-disabled-opacity);
}
/* Special-case the overflow and the hamburger button so they show up disabled
in customize mode. */
&:is(#nav-bar-overflow-button, #PanelUI-menu-button)[disabled] {
fill-opacity: var(--toolbarbutton-disabled-opacity);
}
> .toolbarbutton-icon,
> .toolbarbutton-badge-stack > .toolbarbutton-icon {
width: 16px;
}
}
toolbar .toolbarbutton-1 {
appearance: none;
margin: 0;
padding: 0 var(--toolbarbutton-outer-padding);
justify-content: center;
> .toolbarbutton-icon,
> .toolbarbutton-text,
> .toolbarbutton-badge-stack {
padding: var(--toolbarbutton-inner-padding);
border-radius: var(--toolbarbutton-border-radius);
outline: var(--toolbarbutton-outline);
outline-offset: var(--toolbarbutton-outline-offset);
}
&:focus-visible {
outline: none;
> .toolbarbutton-icon,
> .toolbarbutton-text,
> .toolbarbutton-badge-stack {
outline: var(--focus-outline);
outline-offset: var(--focus-outline-inset);
}
}
> .toolbarbutton-icon {
/* horizontal padding + actual icon width */
width: calc(2 * var(--toolbarbutton-inner-padding) + 16px);
height: calc(2 * var(--toolbarbutton-inner-padding) + 16px);
}
> .toolbarbutton-text {
padding-top: calc(var(--toolbarbutton-inner-padding) - 1px);
padding-bottom: 0;
/* To make the hover feedback line up with sibling buttons, it needs the same
* height as the button icons and the same vertical padding, but as a minimum,
* because otherwise an increase in text sizes would break things.
*/
min-height: calc(16px + 2 * var(--toolbarbutton-inner-padding));
@media (-moz-platform: macos) {
padding-top: calc(var(--toolbarbutton-inner-padding) + 1px);
}
}
&:not([disabled]) {
&:hover > :is(.toolbarbutton-icon, .toolbarbutton-text, .toolbarbutton-badge-stack) {
background-color: var(--toolbarbutton-hover-background);
color: inherit;
outline-color: var(--toolbarbutton-hover-outline-color);
}
&:is(:hover:active, [open], [checked]) > :is(.toolbarbutton-icon, .toolbarbutton-text, .toolbarbutton-badge-stack) {
background-color: var(--toolbarbutton-active-background);
color: inherit;
outline-color: var(--toolbarbutton-active-outline-color);
}
&:is([open], [checked]) > :is(.toolbarbutton-icon, .toolbarbutton-text, .toolbarbutton-badge-stack) {
outline-color: var(--toolbarbutton-selected-outline-color);
}
}
}
#TabsToolbar .toolbarbutton-1 {
margin: 0;
> .toolbarbutton-icon,
> .toolbarbutton-text,
> .toolbarbutton-badge-stack {
border-radius: var(--tab-border-radius);
}
}
#PanelUI-menu-button {
/* Adds padding to end of toolbar while making that space click the first button */
padding-inline-end: var(--toolbar-start-end-padding);
}
toolbar .toolbaritem-combined-buttons {
margin-inline: 2px;
> .toolbarbutton-1 {
padding-inline: 0;
}
> .toolbarbutton-combined-buttons-dropmarker > .toolbarbutton-icon {
/* same height as regular buttons, but narrower, and for a 12x12 image */
padding-inline: 2px;
padding-block: calc(var(--toolbarbutton-inner-padding) + (16px - 12px) / 2);
width: calc(2 * 2px + 12px);
}
> separator {
width: 1px;
height: 16px;
margin-inline-end: -1px;
background-image: linear-gradient(currentColor 0, currentColor 100%);
background-position: center;
background-repeat: no-repeat;
background-size: 1px 16px;
opacity: .2;
}
&:hover > separator {
display: none;
}
}
toolbar[brighttext] .toolbaritem-combined-buttons > separator {
opacity: .3;
}
/* Toolbar button animations */
.toolbarbutton-animatable-box {
display: block;
position: absolute;
overflow: hidden;
z-index: 2;
pointer-events: none;
> .toolbarbutton-animatable-image {
animation-fill-mode: forwards;
animation-iteration-count: 1;
list-style-image: none;
}
}
/* Navigation toolbar overflow button with animation */
#nav-bar-overflow-button {
list-style-image: url("chrome://global/skin/icons/chevron.svg");
#nav-bar:not([overflowing], [nonemptyoverflow], [customizing]) > & {
display: none;
}
/* The button should look both disabled and open in customize mode. */
#nav-bar[customizing] > & > .toolbarbutton-icon {
background-color: var(--toolbarbutton-active-background);
}
> .toolbarbutton-animatable-box {
visibility: hidden;
top: calc(50% - 8px); /* Vertically center the 16px tall animatable image */
width: 16px; /* Width of each frame within the SVG sprite */
height: 16px; /* Height of each frame within the SVG sprite */
-moz-context-properties: fill, stroke;
fill: var(--toolbarbutton-icon-fill);
stroke: var(--toolbarbutton-icon-fill-attention);
> .toolbarbutton-animatable-image {
background-image: url("chrome://browser/skin/chevron-animation.svg");
width: 848px;
height: 16px;
transform: translateX(0);
}
}
&[animate] {
> .toolbarbutton-icon {
fill: transparent;
}
> .toolbarbutton-animatable-box {
visibility: visible;
> .toolbarbutton-animatable-image {
animation-name: overflow-animation;
animation-timing-function: steps(52);
animation-duration: calc(52 * 16.667ms);
}
}
}
}
@keyframes overflow-animation {
from {
transform: translateX(0);
}
/* stylelint-disable-next-line keyframe-block-no-duplicate-selectors */
from {
transform: translateX(-832px);
}
}
/* Combined Stop and Reload button with animation */
#reload-button:not([displaystop]) + #stop-button,
#reload-button[displaystop] {
display: none;
}
/* The reload-button is only disabled temporarily when it becomes visible
to prevent users from accidentally clicking it. We don't however need
to show this disabled state, as the flicker that it generates is short
enough to be visible but not long enough to explain anything to users. */
#reload-button[disabled]:not(:-moz-window-inactive) > .toolbarbutton-icon {
opacity: 1 !important;
}
@keyframes stop-to-reload {
/* pause on the first frame (step 0) for 6 frames of time */
from {
/* 0 */
transform: translateX(0);
}
/* resume at 7/35 and animate across the next 14 frames */
17.14% {
animation-timing-function: steps(14);
transform: translateX(calc(0 * -20px));
}
/* pause on the last frame for the remainder of the duration */
54.29% {
transform: translateX(calc(14 * -20px));
}
to {
/* end state for animation: */
transform: translateX(calc(var(--anim-frames) * -20px));
}
}
@keyframes reload-to-stop {
/* pause on the first frame (step 0) for 6 frames of time */
from {
/* 0 */
transform: translateX(0);
animation-timing-function: steps(12);
}
/* pause at 13/15 for 3 frames */
86.67% {
transform: translateX(calc(var(--anim-frames) * -20px));
}
to {
/* end state for animation: */
transform: translateX(calc(var(--anim-frames) * -20px));
}
}
:is(#reload-button, #stop-button) > .toolbarbutton-animatable-box {
top: calc(50% - 10px); /* Vertically center the 20px tall animatable image */
width: 20px; /* Width of each frame within the SVG sprite */
height: 20px; /* Height of each frame within the SVG sprite */
/* The animations for the reload-button and stop-button are disabled
:not(#nav-bar-customization-target) > #stop-reload-button > & {
display: none;
}
}
#stop-reload-button[animate] {
> #reload-button > .toolbarbutton-icon,
> #reload-button[displaystop] + #stop-button > .toolbarbutton-icon {
fill: transparent;
}
> #reload-button,
> #stop-button {
position: relative;
}
> #reload-button > .toolbarbutton-animatable-box > .toolbarbutton-animatable-image {
background-image: url("chrome://browser/skin/stop-to-reload.svg");
/* transition from stop icon to reload icon
pause at frame 0 for 6 ticks,
pause at frame 15 for 16 ticks
total 35 steps */
--anim-frames: 14;
--anim-steps: calc(var(--anim-frames) + 21); /* Add steps for doing the pause at the start and end */
width: calc(20px * (var(--anim-frames) + 1));
height: 20px;
/* initial state for animation */
transform: translateX(0);
}
> #reload-button:not([displaystop]) > .toolbarbutton-animatable-box > .toolbarbutton-animatable-image {
animation-name: stop-to-reload;
}
> #reload-button[displaystop] + #stop-button > .toolbarbutton-animatable-box > .toolbarbutton-animatable-image {
background-image: url("chrome://browser/skin/reload-to-stop.svg");
/* transition from reload icon to stop icon
pause at end for 3 frames of time
pause at ...
total 15 steps */
--anim-frames: 12;
--anim-steps: calc(var(--anim-frames) + 3); /* Add steps for doing the pause at the start and end */
width: calc(20px * (var(--anim-frames) + 1));
height: 20px;
/* initial state for animation */
transform: translateX(0);
animation-name: reload-to-stop;
animation-duration: calc(var(--anim-steps) * 16.667ms);
}
}
#reload-button:not([displaystop]) > .toolbarbutton-animatable-box > .toolbarbutton-animatable-image {
animation-duration: calc(var(--anim-steps) * 16.667ms);
}
#reload-button > .toolbarbutton-animatable-box > .toolbarbutton-animatable-image {
transform: translateX(-700px);
}
#reload-button[displaystop] + #stop-button > .toolbarbutton-animatable-box > .toolbarbutton-animatable-image {
animation-timing-function: steps(15);
animation-duration: 0.25s;
transform: translateX(-300px);
}
/* Bookmark buttons */
#personal-toolbar-empty-description,
toolbarbutton.bookmark-item:not(.subviewbutton) {
margin: 2px;
padding: var(--bookmark-block-padding) 4px;
}
#PersonalToolbar {
/* These should match the sizing of the bookmark-items in the inline axis
* (padding and margin, respectively) */
--toolbarbutton-inner-padding: 4px;
--toolbarbutton-outer-padding: 2px;
:root[uidensity=compact] & {
--toolbarbutton-outer-padding: 1px;
}
.toolbarbutton-1 {
margin-block: 2px;
/* Allow icons to grow with the toolbar to match bookmark item heights
*
* NOTE(emilio): This matches pre-existing behavior but it's inconsistent with
* how e.g. combined items work, and maybe we should just remove this.
*/
align-items: stretch;
> .toolbarbutton-icon {
height: auto;
}
> .toolbarbutton-badge-stack {
align-items: center;
}
}
}
toolbarbutton.bookmark-item:not(.subviewbutton) {
border-radius: var(--toolbarbutton-border-radius);
max-width: 13em;
appearance: none;
outline: var(--toolbarbutton-outline);
outline-offset: var(--toolbarbutton-outline-offset);
&:not([disabled], [open]):hover {
background-color: var(--toolbarbutton-hover-background);
color: inherit;
outline-color: var(--toolbarbutton-hover-outline-color);
}
&:hover:active:not([disabled]),
&[open="true"] {
background-color: var(--toolbarbutton-active-background);
color: inherit;
outline-color: var(--toolbarbutton-active-outline-color);
}
&:focus-visible {
outline: var(--focus-outline);
outline-offset: var(--focus-outline-inset);
}
:root[uidensity=compact] & {
margin-inline: 1px;
}
}
.bookmark-item > .toolbarbutton-icon {
width: 16px;
height: 16px;
#PlacesToolbarItems > & {
margin-inline-end: 0;
}
}
/* This rule applies to bookmark menu items too */
.bookmark-item > label {
/* Ensure we use the direction of the bookmarks label instead of the
browser locale. */
unicode-bidi: plaintext;
/* Preserve whitespace in bookmark names. */
white-space: pre;
}
#personal-toolbar-empty-description {
-moz-window-dragging: no-drag;
/* Ensure that the description is always at least as big as a bookmarks item,
* where its icon is 16px (which may be more than inline text height); */
min-height: calc(16px + 2 * var(--bookmark-block-padding));
}
#bookmarks-toolbar-placeholder {
max-width: unset;
}
#bookmarks-toolbar-placeholder,
#bookmarks-toolbar-button {
display: none;
}
toolbarpaletteitem[place="toolbar"] > #personal-bookmarks > #bookmarks-toolbar-placeholder,
toolbarpaletteitem[place="palette"] > #personal-bookmarks > #bookmarks-toolbar-button,
#personal-bookmarks:is([overflowedItem=true], [cui-areatype="panel"]) > #bookmarks-toolbar-button {
display: flex;
}
#nav-bar-customization-target > #personal-bookmarks,
toolbar:not(#TabsToolbar) > #wrapper-personal-bookmarks,
toolbar:not(#TabsToolbar) > #personal-bookmarks {
flex: 1 auto;
}
/* Force the display of the label for bookmarks */
.bookmark-item > .toolbarbutton-text {
display: flex !important;
}
#PlacesToolbar,
#PlacesToolbarItems {
min-width: 0;
}
#personal-bookmarks {
/* Make sure there's at least space for the chevron */
min-width: calc(16px + 2 * var(--toolbarbutton-inner-padding) + 2 * var(--toolbarbutton-outer-padding));
}
#managed-bookmarks > .toolbarbutton-icon,
#bookmarks-toolbar-placeholder > .toolbarbutton-icon,
#PlacesToolbarItems > .bookmark-item > .toolbarbutton-icon[label]:not([label=""]),
#PersonalToolbar #import-button > .toolbarbutton-icon,
#PersonalToolbar #aboutwelcome-button > .toolbarbutton-icon,
#PersonalToolbar .fxms-bmb-button > .toolbarbutton-icon,
#OtherBookmarks.bookmark-item[container] > .toolbarbutton-icon {
margin-inline-end: 4px;
}
/* Separators */
/* Override the toolkit styles, and make sure separators are draggable by
* making them wider, and using a pseudo-element for the visual separator. */
#PlacesToolbarItems > toolbarseparator {
margin: 0;
padding-inline: 4px;
appearance: none;
/* When adjacent to the bookmarks items, give the bookmarks items a leading separator. */
&::before {
content: "";
display: block;
border-inline-start: 1px solid;
border-image-source: linear-gradient(
transparent 3.75px,
var(--toolbarseparator-color) 3.75px,
var(--toolbarseparator-color) calc(100% - 3.75px),
transparent calc(100% - 3.75px) );
border-image-slice: 1;
}
@media (resolution >= 2x) {
&::before {
border-inline-start-width: 0.5px;
}
}
}
/* Toolbarbutton badge */
.toolbarbutton-badge {
/* The bookmarks toolbar is smaller than the other toolbars, so we
* need to override the badge position to not be cut off. */
#PersonalToolbar & {
margin-top: -1px !important;
:root[uidensity=touch] & {
margin-top: -4px !important;
}
}
/* Remove a pixel of margin on the end so that the badge doesn't
* overflow the toolbar and push the button into the overflow menu. */
:root[uidensity=compact] & {
margin-inline-end: -7px !important;
}
/* Alternative style for .toolbarbutton-badge used by CFR notifications */
&.feature-callout {
width: 14px;
height: 14px;
min-width: auto;
box-shadow: none;
border: none;
padding: 0;
display: block;
margin: -7px 0 0 !important;
margin-inline-end: -6px !important;
background: url(chrome://global/skin/icons/badge-blue.svg);
}
}
/* Flexible spacer sizing */
toolbarpaletteitem[place=toolbar][id^=wrapper-customizableui-special-spring],
toolbarspring {
flex: 1;
min-width: 28px;
max-width: 112px;
#nav-bar & {
flex: 80 80;
/* Ensure flexible spacers don't shrink to nothing so they can be
* manipulated in customize mode. */
min-width: 10px;
}
}
#nav-bar:not([customizing]) toolbarspring {
/* Allow flexible spacers to shrink further outside of customize mode. */
min-width: 1px;
}
/* Keyboard navigation */
toolbar[keyNav]:not([collapsed=true], [customizing]) toolbartabstop,
#tabbrowser-tabs[orient="vertical"] #tabs-newtab-button,
#vertical-tabs-newtab-button {
-moz-user-focus: normal;
}