Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Firefox 57 Windows 10 UWP Style Overlay Scrollbars

Preview

Installation

  • Save each file to your Firefox profile's chrome folder, creating one if the folder does not already exist. More information: http://kb.mozillazine.org/UserChrome.css
    • If userChrome.css has already been modified in your profile add the userChrome.css rules below to that existing file. Note there should only be one xul namespace declaration, which should be the first line in the file.
  • Restart Firefox.

Notes

  • Behavior is changed. The up/down/left/right buttons are removed, and by default the feature to click a location on the scrollbar to scroll to it is disabled so that the scroll bar can be clicked through when it overlays an element on the page. Remove the pointer-events rules to restore.
  • The styles can be toggled at any time by going to the Tools menu in firefox and toggling the Windows 10 Style Scrollbars option. The page must be refreshed for the window scrollbars to update, but on-page elements should change instantly.
  • Style may be edited in userChrome.js. For changes to take hold, clear your cache in ...\AppData\Local\Mozilla\Firefox\Profiles by deleting the folder for your profile.
  • Live debugging may be performed via Browser Toolbox console https://developer.mozilla.org/en-US/docs/Tools/Browser_Toolbox
    • Make edits to userChrome.js in a text editor and copy/paste the entire contents of the file into the console. Execute and refresh a page to see changes. Rules are cached so if you set a rule you need to clear your profile cache to if you want to remove the rule.
  • Known issue with hover states for window scrollbars cause transition flashing. This prevents full replication of windows 10 style scrollbar behavior, with the workaround being a simpler fade in/out rather than a full scaling animation. On-page elements do not have the hover state issues.

Changelog

  • 0.0.7
    • Lack of testing meant I did not catch the 0.0.6 released version did not work due to caching while I implemented it. Please comment if you know a better way to solve this issue, eg with z-index sorting or only having the hidden state be active during a fullscreen state.
    • On youtube.com the scrollbar will be invisible except when being hovered over.
  • 0.0.6
    • Added a special case to hide scrollbars on youtube.com because google forgot what Fullscreen is supposed to be.
  • 0.0.5
    • Added z-index rule to fix compositing/click issues that came about some time after FF 57 (thanks @joshieecs)
    • Added rules to address linux/gtk compatability (thanks @axel668)
  • 0.0.4
    • Modified css string to use backticks and so not require formatting chars
  • 0.0.3
    • New transition animations
  • 0.0.2
    • Removed unused rules
    • Scrollbar width changed to 12px from 16px to better match native style

License

Reference the @notes in userChrome.js for licensing information of sourced parts. The css content provided by me is licensed as follows:

ISC License (ISC)

Copyright 2018 @MrKwatz

Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
toolbarbutton#alltabs-button {
-moz-binding: url("userChrome.xml#js");
}
// ==UserScript==
// @name userChrome.js
// @namespace scrollbars_win10
// @version 0.0.7
// @note Windows 10 style by /u/mrkwatz https://www.reddit.com/r/FirefoxCSS/comments/7fkha6/firefox_57_windows_10_uwp_style_overlay_scrollbars/
// @note Brought to Firefox 57 by /u/Wiidesire https://www.reddit.com/r/firefox/comments/7f6kc4/floating_scrollbar_finally_possible_in_firefox_57/
// @note userChrome.js https://github.com/nuchi/firefox-quantum-userchromejs
// @note Forked from https://github.com/Endor8/userChrome.js/blob/master/floatingscrollbar/FloatingScrollbar.uc.js
// ==/UserScript==
(function () {
var prefs = Services.prefs,
enabled;
if (prefs.prefHasUserValue('userChromeJS.floating_scrollbar.enabled')) {
enabled = prefs.getBoolPref('userChromeJS.floating_scrollbar.enabled')
} else {
prefs.setBoolPref('userChromeJS.floating_scrollbar.enabled', true);
enabled = true;
}
var css = `
@namespace url(http: //www.mozilla.org/keymaster/gatekeeper/there.is.only.xul);
:not(select):not(hbox) > scrollbar {
-moz-appearance: none!important;
position: relative!important;
background-color: transparent;
pointer-events: none;
z-index: 2147483647;
}
:not(select):not(hbox) > scrollbar * {
-moz-appearance: none!important;
background-color: transparent!important;
pointer-events: none;
}
:not(select):not(hbox) > scrollbar thumb {
-moz-appearance: none!important;
background-color: transparent;
pointer-events: auto;
}
:not(select):not(hbox) > scrollbar[orient = "vertical"] {
min-width: 12px!important;
-moz-margin-start: -12px;/*margin to fill the whole render window with content and overlay the scrollbars*/
}
:not(select):not(hbox) > scrollbar[orient = "horizontal"] {
height: 12px!important;
margin-top: -12px;
}
:not(select):not(hbox) > scrollbar[orient = "vertical"] thumb {
border-right: 2px solid rgba(133, 132, 131, 1);
width: 12px;
min-height: 12px;
transition: border 0.1s ease-in;
}
:not(select):not(hbox) > scrollbar[orient = "horizontal"] thumb {
border-bottom: 2px solid rgba(133, 132, 131, 1);
min-width: 12px;
transition: border 0.1s ease-in;
}
:not(select):not(hbox) > scrollbar:hover {
background-color: rgba(0, 0, 0, 0.25);
max-width: 12px!important;
point-events: auto;
}
:not(select):not(hbox) > scrollbar:hover thumb {
border-width: 12px;
transition: border 0s linear;
}
:not(select):not(hbox) > scrollbar scrollbarbutton, :not(select):not(hbox) > scrollbar gripper {
display: none;
}
@-moz-document domain("youtube.com") {
:not(select):not(hbox) > scrollbar[orient = "vertical"]:not(:hover) thumb {
opacity: 0 !important;
}
}
`;
var sss = Cc['@mozilla.org/content/style-sheet-service;1'].getService(Ci.nsIStyleSheetService);
var uri = makeURI('data:text/css;charset=UTF=8,' + encodeURIComponent(css));
var p = document.getElementById('devToolsSeparator');
var m = document.createElement('menuitem');
m.setAttribute('label', "Windows 10 Style Scrollbars");
m.setAttribute('type', 'checkbox');
m.setAttribute('autocheck', 'false');
m.setAttribute('checked', enabled);
p.parentNode.insertBefore(m, p);
m.addEventListener('command', command, false);
if (enabled) {
sss.loadAndRegisterSheet(uri, sss.AGENT_SHEET);
}
function command() {
if (sss.sheetRegistered(uri, sss.AGENT_SHEET)) {
prefs.setBoolPref('userChromeJS.floating_scrollbar.enabled', false);
sss.unregisterSheet(uri, sss.AGENT_SHEET);
m.setAttribute('checked', false);
} else {
prefs.setBoolPref('userChromeJS.floating_scrollbar.enabled', true);
sss.loadAndRegisterSheet(uri, sss.AGENT_SHEET);
m.setAttribute('checked', true);
}
let root = document.documentElement;
let display = root.style.display;
root.style.display = 'none';
window.getComputedStyle(root).display; // Flush
root.style.display = display;
}
})();
<?xml version="1.0"?>
<bindings id="generalBindings"
xmlns="http://www.mozilla.org/xbl"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:xbl="http://www.mozilla.org/xbl">
<binding id="js" extends="chrome://global/content/bindings/toolbarbutton.xml#menu">
<implementation>
<constructor><![CDATA[
function makeRelativePathURI(name) {
let absolutePath = Components.stack.filename;
return absolutePath.substring(0, absolutePath.lastIndexOf("/") + 1) + name;
}
// The following code executes in the browser context,
// i.e. chrome://browser/content/browser.xul
Services.scriptloader.loadSubScript(makeRelativePathURI("userChrome.js"), window);
]]></constructor>
</implementation>
</binding>
</bindings>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment