/* This Source Code Form is subject to the terms of the Creative Commons * Attribution-NonCommercial-ShareAlike International License, v. 4.0. * If a copy of the CC BY-NC-SA 4.0 was not distributed with this * file, You can obtain one at http://creativecommons.org/licenses/by-nc-sa/4.0/ * or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA. */ /* controls the appearance of individual tabs and elements inside a tab. */ #TabsToolbar .tabbrowser-tab { background-color: var(--lwt-accent-color) !important; } .tab-content { overflow: hidden !important; } /* different tab background colors in various states */ .tabbrowser-tab:not([selected]):is(:hover, [open]) .tab-background { background: var(--uc-tab-hover) !important; } .tabbrowser-tab:is([visuallyselected], [selected]) .tab-background { background: var(--uc-tab-selected) !important; } .tabbrowser-tab:not([selected], [multiselected], :hover, [open]) .tab-background { background: var(--uc-tab-background) !important; } .tabbrowser-tab[multiselected]:not([selected], :hover, [open]) .tab-background { background: var(--uc-tab-multi) !important; } .tabbrowser-tab[multiselected]:not([selected]):is(:hover, [open]) .tab-background { background: var(--uc-tab-multi-hover) !important; } #tabbrowser-tabs:focus-within .tabbrowser-tab.tablist-keyboard-focus { &:not([selected]) > .tab-stack > .tab-background { background: var(--uc-tab-hover) !important; } &[selected] > .tab-stack > .tab-background { background: var(--uc-tab-focused-hover) !important; } &[multiselected]:not([selected]) > .tab-stack > .tab-background { background: var(--uc-tab-multi-hover) !important; } } /* block our animations while tabs are being dragged & dropped */ #tabbrowser-tabs[movingtab] .tabbrowser-tab * { transform: none !important; } .tab-background { border: none !important; outline: none !important; opacity: 1 !important; } /* different tab shadows in various states. to produce the illusion of modulated depth */ /* .tabbrowser-tab .tab-background { box-shadow: 0px 0px 15px 0px hsla(0, 0%, 0%, 0.2), 0px 0px 5px 0px hsla(0, 0%, 0%, 0.1); } */ .tabbrowser-tab:not([selected], [multiselected]):is(:hover, [open]) .tab-background, .tabbrowser-tab[multiselected] .tab-background, #tabbrowser-tabs:focus-within .tabbrowser-tab.tablist-keyboard-focus:not([selected], [multiselected]) .tab-background { box-shadow: 0 0 20px 1px rgba(0, 0, 0, 0.1), 0 0 15px 0 hsla(0, 0%, 0%, 0.25) !important; } .tabbrowser-tab[selected] .tab-background, .tabbrowser-tab[multiselected][selected] .tab-background { box-shadow: 0 0 20px 1px rgba(0, 0, 0, 0.1), 0 0 15px 0 hsla(0, 0%, 0%, 0.35) !important; } .tabbrowser-tab .tab-context-line { display: flex !important; order: 2 !important; height: 1px !important; margin: 0 !important; opacity: 1 !important; transition: none !important; } /* colored lines on container tabs */ .tabbrowser-tab[usercontextid] .tab-context-line { background-color: var(--identity-tab-color) !important; } /* purple line on multiselected tabs */ .tabbrowser-tab[multiselected] .tab-context-line { background-color: var(--multiselected-color) !important; } .tabbrowser-tab:not([usercontextid], [multiselected]) .tab-context-line { display: none !important; } .tabbrowser-tab.identity-icon-on-multiselect[usercontextid][multiselected] .tab-content::after { content: ""; display: flex; height: 12px; width: 12px; margin-inline: 3px; background: var(--identity-icon) center/contain no-repeat; fill: var(--identity-icon-color); -moz-context-properties: fill; } .tab-label-container { height: revert !important; pointer-events: none !important; opacity: revert !important; } .tab-label { font-weight: revert !important; } /* highlight unread tabs; requires unreadTabMods.uc.js */ :root[italic-unread-tabs] .tabbrowser-tab[notselectedsinceload]:not([pending]), :root[italic-unread-tabs] .tabbrowser-tab[notselectedsinceload][pending][busy] { font-style: italic !important; } .tabbrowser-tab[pinned] .tab-icon-stack { margin: 0 !important; } .tab-content[pinned] { padding: 0 var(--tab-inline-padding) !important; } /* style the loading burst that triggers when tab loading finishes */ .tab-loading-burst { pointer-events: none; } #TabsToolbar .tab-loading-burst::before { backface-visibility: hidden; } :root[sessionrestored] .tab-loading-burst[pinned]::before { margin-inline-start: calc((var(--pinned-tab-width, 36px) / 2) - 2.5%) !important; } /* pinned tabs should style just like regular tabs except without labels and buttons */ #tabbrowser-tabs[positionpinnedtabs] > #tabbrowser-arrowscrollbox > .tabbrowser-tab[pinned] > .tab-stack { border-inline: none !important; } #tabbrowser-tabs[positionpinnedtabs] > .tabbrowser-arrowscrollbox > .tabbrowser-tab[pinned] > .tab-stack { border: none !important; } /* hide the sound icon while moving a pinned tab. does nothing without restoreTabSoundButton.uc.js since sound icon no longer exists in vanilla firefox. */ .tabbrowser-tab[pinned] .tab-icon-sound { display: none !important; } /* we don't need the icon overlay since we restore the sound icon with javascript & manifest */ .tab-icon-overlay { display: none !important; } /* tab buttons are generally styled the same */ .tab-close-button, .tab-icon-sound { width: 16px !important; height: 16px !important; min-width: 16px !important; min-height: 16px !important; padding: 0 !important; opacity: 0 !important; fill: currentColor !important; border-radius: var(--tab-button-border-radius, 2px) !important; } .tab-close-button { order: 0; display: block !important; -moz-context-properties: fill, fill-opacity, stroke, stroke-opacity !important; position: relative; margin-inline: 0 -16px !important; list-style-image: url(chrome://userchrome/content/textbox-clear.svg) !important; fill-opacity: 0 !important; stroke-opacity: 0.6 !important; } .tab-icon-sound { --tab-icon-end-margin: 0 !important; display: block !important; list-style-image: none !important; background-image: url(chrome://userchrome/content/audioUnmutedButton.svg) !important; background-size: 12px !important; background-position: center !important; background-repeat: no-repeat !important; -moz-context-properties: fill, fill-opacity !important; order: 2 !important; fill-opacity: 0.6 !important; } .tab-icon-sound[muted] { background-image: url(chrome://userchrome/content/audioMutedButton.svg) !important; background-size: 12px !important; background-position: center !important; background-repeat: no-repeat !important; list-style-image: none !important; } .tab-icon-sound[activemedia-blocked], .tab-icon-sound[activemedia-blocked]:hover { padding: 0 !important; background-image: url(chrome://userchrome/content/glyph-play-12.svg) !important; background-size: 8px !important; background-position: 4.5px center !important; background-repeat: no-repeat !important; } .tab-close-button:hover { background-color: var(--arrowpanel-dimmed) !important; stroke-opacity: 1 !important; } .tab-icon-sound:hover { background-color: var(--arrowpanel-dimmed) !important; fill-opacity: 1 !important; } .tabbrowser-tab[pending] .tab-content .tab-icon-sound { color: var(--uc-menu-semi-disabled-color) !important; } .tabbrowser-tab:is(:hover, [open]) :is(.tab-icon-sound, .tab-close-button), #tabbrowser-tabs:focus-within .tabbrowser-tab.tablist-keyboard-focus :is(.tab-icon-sound, .tab-close-button) { opacity: 1 !important; } .tabbrowser-tab:is(:hover, [open]) :is(.tab-icon-sound, .tab-close-button):hover:active, #tabbrowser-tabs:focus-within .tabbrowser-tab.tablist-keyboard-focus :is(.tab-icon-sound, .tab-close-button):hover:active { background-color: var(--arrowpanel-dimmed-further) !important; } /* for the picture in picture button to mute/unmute tabs with proton, you need to follow the restore tab sound button instructions on my repo's readme */ #tabbrowser-tabs:not(:focus-within) .tabbrowser-tab:not(:hover, [open]) .tab-icon-sound[pictureinpicture], #tabbrowser-tabs:focus-within .tabbrowser-tab:not(.tablist-keyboard-focus) .tab-icon-sound[pictureinpicture] { background-image: url(chrome://userchrome/content/tab-picture-in-picture.svg) !important; background-size: 12px !important; background-position: center !important; background-repeat: no-repeat !important; border-radius: revert !important; } .tab-icon-sound:is([soundplaying], [muted], [activemedia-blocked], [pictureinpicture]) { opacity: 1 !important; } .tabbrowser-tab:is(:hover, [open]) .tab-icon-sound[pictureinpicture][soundplaying], #tabbrowser-tabs:focus-within .tabbrowser-tab.tablist-keyboard-focus .tab-icon-sound[pictureinpicture][soundplaying], .tabbrowser-tab .tab-icon-sound[pictureinpicture][muted], .tabbrowser-tab .tab-icon-sound[pictureinpicture]:hover { background-size: 12px !important; background-position: center !important; background-repeat: no-repeat !important; list-style-image: none !important; border-radius: var(--tab-button-border-radius, 2px) !important; } .tabbrowser-tab:is(:hover, [open]) .tab-icon-sound[pictureinpicture][soundplaying], #tabbrowser-tabs:focus-within .tabbrowser-tab.tablist-keyboard-focus .tab-icon-sound[pictureinpicture][soundplaying] { background-image: url(chrome://userchrome/content/audioUnmutedButton.svg) !important; } .tabbrowser-tab:is(:hover, [open]) .tab-icon-sound, #tabbrowser-tabs:focus-within .tabbrowser-tab.tablist-keyboard-focus .tab-icon-sound { &[pictureinpicture][muted], &[pictureinpicture][soundplaying][muted] { background-image: url(chrome://userchrome/content/audioMutedButton.svg) !important; } } .tab-icon-sound { transition: 0.12s transform ease-in-out, 0.12s opacity ease-in-out, 0.12s margin ease-in-out !important; } #tabbrowser-tabs .tab-content > .tab-icon-sound:not([soundplaying], [muted], [activemedia-blocked], [pictureinpicture]) { opacity: 0 !important; pointer-events: none !important; transform: translateX(16px) scale(0.5) !important; margin-right: -16px !important; } /* uncomment the line below if you want to hide the sound button on the selected tab until the tab container is hovered. e.g. if your tab min size is small and you want more room to see the tab title. by default the tab sound button shows on every tab if sound is playing or muted. with the following line uncommented, the tab sound button shows on every non-selected tab if sound is playing or muted, but only shows on the selected tab if 1) the tab is muted, or 2) the tabs area is hovered. so in other words it won't show if audio is playing until you hover the general area of the tabs, but will show if audio is muted. */ /* #tabbrowser-tabs:not(:hover, :focus-within) .tabbrowser-tab[selected] .tab-content > .tab-icon-sound:not([pictureinpicture], [muted]), */ #tabbrowser-tabs:not(:hover, :focus-within) .tabbrowser-tab:not([open]) .tab-content > .tab-icon-sound:not([soundplaying], [muted], [activemedia-blocked], [pictureinpicture]) { opacity: 0 !important; pointer-events: none !important; transform: translateX(16px) scale(0.5) !important; margin-right: -16px !important; } /* when tab is being dragged/dropped, style it like it's hovered */ #tabbrowser-tabs[movingtab] .tabbrowser-tab[selected]:not([pinned]) .tab-icon-image { opacity: 0 !important; } #tabbrowser-tabs[movingtab] .tabbrowser-tab[selected]:not([pinned]) .tab-close-button { order: 0 !important; display: flex !important; position: relative !important; margin-right: -16px !important; visibility: visible !important; opacity: 1 !important; } /* attention indicator */ .tabbrowser-tab:is([image], [pinned]) > .tab-stack > .tab-content[attention]:not([selected]), .tabbrowser-tab > .tab-stack > .tab-content[pinned][titlechanged]:not([selected]) { background-image: url(chrome://userchrome/content/indicator-tab-attention-purple.svg) !important; background-position: right 4px top 4px !important; background-size: 10px !important; background-repeat: no-repeat; } /* tab crashed indicator */ .tabbrowser-tab[crashed] > .tab-stack > .tab-content::after { top: 4px; right: 4px; content: ""; display: block; position: absolute; pointer-events: none; width: 10px; height: 10px; z-index: 2; -moz-context-properties: fill, stroke; stroke: var(--warning-icon-detail); fill: var(--warning-icon-background); background-image: url(chrome://userchrome/content/devtools/error-small-two-tone.svg); background-size: contain; background-repeat: no-repeat; background-position: center; } /* tab buttons are animated with opacity and transformation */ #tabbrowser-tabs:not(:focus-within) .tabbrowser-tab:not(:hover, [tabdrop-samewindow], [open]) .tab-close-button, #tabbrowser-tabs:focus-within .tabbrowser-tab:not(.tablist-keyboard-focus) .tab-close-button { transform: translateX(-15px) scale(0.5) !important; } #tabbrowser-tabs:not([movingtab]) .tabbrowser-tab:not([tabdrop-samewindow]) :is(.tab-close-button, .tab-icon-image, .tab-sharing-icon-overlay, .tab-throbber) { transition: 0.12s transform ease-in-out, 0.12s opacity ease-in-out !important; } .tab-icon-pending[pendingicon] { pointer-events: none !important; display: block !important; margin-right: -16px !important; } .tab-icon-image { display: block !important; position: relative !important; } .tabbrowser-tab:is(:hover, [busy], [open]) :is(.tab-icon-image, .tab-sharing-icon-overlay), #tabbrowser-tabs:focus-within .tabbrowser-tab.tablist-keyboard-focus :is(.tab-icon-image, .tab-sharing-icon-overlay) { opacity: 0 !important; pointer-events: none !important; transform: translateX(25px) scale(0.5) !important; } .tabbrowser-tab .tab-label:not([fadein]), .tabbrowser-tab .tab-throbber:not([fadein]) { display: none !important; } .tabbrowser-tab .tab-throbber:not([busy]) { opacity: 0 !important; pointer-events: none !important; transform: translateX(-15px) scale(0.5) !important; } .tabbrowser-tab:is(:hover, [tabdrop-samewindow], [open]) .tab-throbber, #tabbrowser-tabs:focus-within .tabbrowser-tab.tablist-keyboard-focus .tab-throbber { opacity: 0 !important; pointer-events: none !important; transform: translateX(25px) scale(0.5) !important; } .tab-throbber[busy] { fill: var(--busy-throbber-fill) !important; } .tab-throbber[progress] { fill: var(--loading-throbber-fill) !important; } .tab-throbber[busy]::before { opacity: 0.8 !important; } .tab-throbber[progress]::before { opacity: 1 !important; } :root[sessionrestored] .tab-throbber[fadein] { display: block !important; position: relative !important; } @media (prefers-reduced-motion: reduce) { :root[sessionrestored] .tab-throbber[fadein] { background-image: url("chrome://browser/skin/tabbrowser/hourglass.svg"); background-position: center; background-repeat: no-repeat; -moz-context-properties: fill, fill-opacity !important; } .tab-throbber[busy] { opacity: 0.8 !important; } } @media (prefers-reduced-motion: no-preference) { /* tabLoadingSpinner.uc.js enables a special loading throbber animation that spins instead of bouncing horizontally */ @keyframes uc-tab-throbber-spinner-css { to { rotate: 360deg; } } @keyframes uc-tab-throbber-spinner-sprite { 0% { transform: translateX(0); } 100% { transform: translateX(-100%); } } @keyframes uc-tab-throbber-spinner-sprite-rtl { 0% { transform: translateX(0); } 100% { transform: translateX(100%); } } /* I made different versions of this animation to circumvent an SVG issue. if you update Firefox and the throbber animation stops working, uncomment one of the 2 alternate rules below. one of the 3 should work. you can do the same thing with the all-tabs-menu loading icons in the next ruleset below. */ :root[sessionrestored] .tab-throbber[throbber-loaded]::before { content: "" !important; display: flex !important; -moz-context-properties: fill, fill-opacity !important; /* stylelint-disable declaration-block-no-duplicate-properties */ width: 16px !important; height: 16px !important; animation: none !important; background-position: center !important; /* stylelint-enable declaration-block-no-duplicate-properties */ background-repeat: no-repeat !important; fill: inherit !important; /* ANIMATION METHOD #1: this version of the animation is implemented by an tag. it's the most efficient method but it has broken once for a couple days due to an erroneous nightly patch. */ /* background-image: url(chrome://userchrome/content/loading-spinner.svg) !important; */ /* ---------------------------------- */ /* ANIMATION METHOD #2: the animation is written in a