AutoHide Tab Bar + Address Bar | Show on Hover
-
@oudstand Thank you, i will be waiting to hear from you mate
-
@wjate you can press
F11
to toggle this mod, but you should remove the defaultF11
keyboard shortcut in Vivaldi otherwise you will toggle the mod and the default full screen of Vivaldi. -
@oudstand Thanks. Is there a way to add a button to the status bar that runs this command?
-
@wjate no currently there isn't an option for this. You could adjust the keyboard shortcut for your needs if this helps you. Change in line
44
in this line of code:vivaldi.tabsPrivate.onKeyboardShortcut.addListener((id, combination) => combination === 'F11' && toggleFullScreen());
The
'F11'
to something else. For example to'Ctrl+Alt+F'
or what ever you prefer. -
The Workspace menu is opening behind the top bar
-
@Phobos with this code it should be fixed:
/** * Forum link: https://forum.vivaldi.net/topic/92477/some-javascript-to-automatically-hide-tab-bar-and-address-bar-and-show-them-by-hovering * Hides the tab bar and address bar when not hovering */ (function checkWebViewForFullscreen() { const webView = document.querySelector('#webview-container'), hidePanels = true, // set to false to not hide the panels verticalMargin = '0px', // 'var(--edge-like-border-radius) / 2', // set to '0px' to remove the margin left bookmarkBarPadding = '6px', // set to '0px' to remove the padding around the bookmark bar delay = 125, // set to 0 to remove the delay showAddressBarOnNewTab = true; // shows the address bar on a new tab - set to false to disable the feature if (!webView) { setTimeout(checkWebViewForFullscreen, 1337); return; } const positions = ['top', 'bottom', 'left', 'right'], app = document.querySelector('#app'), browser = document.querySelector('#browser'), header = document.querySelector('#header'), mainBar = document.querySelector('.mainbar'), bookmarkBar = document.querySelector('.bookmark-bar'), panelsContainer = document.querySelector('#panels-container'), tabBarClassList = document.querySelector('#tabs-tabbar-container').classList, panelsLeft = document.querySelector('#panels-container').classList.contains('left'), tabBarPosition = positions.find(cls => tabBarClassList.contains(cls)), addressBarTop = browser.classList.contains('address-top'), bookmarksTop = browser.classList.contains('bookmark-bar-top'); let fullscreenEnabled, showTopTimeout, showLeftTimeout, showRightTimeout, showBottomTimeout; chrome.storage.local.get('fullScreenModEnabled').then((value) => { fullscreenEnabled = value.fullScreenModEnabled || value.fullScreenModEnabled == undefined; if (fullscreenEnabled) { addFullScreenListener(); } }); vivaldi.tabsPrivate.onKeyboardShortcut.addListener((id, combination) => combination === 'F11' && toggleFullScreen()); let style = ` .fullscreen-listener-enabled { ${generalCSS()} ${topCSS()} ${leftCSS()} ${rightCSS()} ${bottomCSS()} } #app:not(.fullscreen-listener-enabled) .hover-div { visibility: hidden; } `; if (bookmarkBarPadding) { style += ` .fullscreen-listener-enabled .bookmark-bar { height: auto; padding-top: ${bookmarkBarPadding}; padding-bottom: calc(${bookmarkBarPadding} / 2); } `; } const styleEl = document.createElement('style'); styleEl.appendChild(document.createTextNode(style)); document.head.appendChild(styleEl); const hoverDivTop = createHorizontalHoverDiv('top'), hoverDivLeft = (hidePanels && panelsLeft) || tabBarPosition === 'left' ? createVerticalHoverDiv('left') : undefined, hoverDivRight = (hidePanels && !panelsLeft) || tabBarPosition === 'right' ? createVerticalHoverDiv('right') : undefined, hoverDivBottom = !addressBarTop || tabBarPosition === 'bottom' || !bookmarksTop ? createHorizontalHoverDiv('bottom') : undefined; function toggleFullScreen() { fullscreenEnabled = !fullscreenEnabled; fullscreenEnabled ? addFullScreenListener() : removeFullScreenListener(); chrome.storage.local.set({fullScreenModEnabled: fullscreenEnabled}); } function addFullScreenListener() { app.classList.add('fullscreen-listener-enabled'); webView.addEventListener('pointerenter', hide); hoverDivTop.addEventListener('pointerenter', showTop); hoverDivTop.addEventListener('pointerleave', clearTimeouts); if (hoverDivLeft) { hoverDivLeft.addEventListener('pointerenter', showLeft); hoverDivLeft.addEventListener('pointerleave', clearTimeouts); } if (hoverDivRight) { hoverDivRight.addEventListener('pointerenter', showRight); hoverDivRight.addEventListener('pointerleave', clearTimeouts); } if (hoverDivBottom) { hoverDivBottom.addEventListener('pointerenter', showBottom); hoverDivBottom.addEventListener('pointerleave', clearTimeouts); } hide(); } function removeFullScreenListener() { app.classList.remove('fullscreen-listener-enabled'); webView.removeEventListener('pointerenter', hide); hoverDivTop.removeEventListener('pointerenter', showTop); hoverDivTop.removeEventListener('pointerleave', clearTimeouts); if (hoverDivLeft) { hoverDivLeft.removeEventListener('pointerenter', showLeft); hoverDivLeft.removeEventListener('pointerleave', clearTimeouts); } if (hoverDivRight) { hoverDivRight.removeEventListener('pointerenter', showRight); hoverDivRight.removeEventListener('pointerleave', clearTimeouts); } if (hoverDivBottom) { hoverDivBottom.removeEventListener('pointerenter', showBottom); hoverDivBottom.removeEventListener('pointerleave', clearTimeouts); } show(); } function clearTimeouts() { if (showTopTimeout) clearTimeout(showTopTimeout); if (showLeftTimeout) clearTimeout(showLeftTimeout); if (showRightTimeout) clearTimeout(showRightTimeout); if (showBottomTimeout) clearTimeout(showBottomTimeout); } function hide() { app.classList.add('hidden-top'); if (hoverDivLeft) app.classList.add('hidden-left'); if (hoverDivRight) app.classList.add('hidden-right'); if (hoverDivBottom) app.classList.add('hidden-bottom'); } function show() { showTop(); showLeft(); showRight(); showBottom(); } function showTop() { showTopTimeout = setTimeout(() => app.classList.remove('hidden-top'), delay); } function showLeft() { if (hoverDivLeft) { showLeftTimeout = setTimeout(() => app.classList.remove('hidden-left'), delay); } } function showRight() { if (hoverDivRight) { showRightTimeout = setTimeout(() => app.classList.remove('hidden-right'), delay); } } function showBottom() { if (hoverDivBottom) { showBottomTimeout = setTimeout(() => app.classList.remove('hidden-bottom'), delay); } } function createHorizontalHoverDiv(position) { const hoverDiv = document.createElement('div'); hoverDiv.style.height = '1.5rem'; hoverDiv.style.width = '100vw'; hoverDiv.style.position = 'fixed'; hoverDiv.style.left = '0'; hoverDiv.style.zIndex = '10'; hoverDiv.style[position] = '0'; hoverDiv.className = 'hover-div'; hoverDiv.classList.add(position); document.querySelector('#app').appendChild(hoverDiv); return hoverDiv; } function createVerticalHoverDiv(position) { const hoverDiv = document.createElement('div'); hoverDiv.style.height = '100%'; hoverDiv.style.width = '1.5rem'; hoverDiv.style.position = 'fixed'; hoverDiv.style.top = '0'; hoverDiv.style.zIndex = '10'; hoverDiv.style[position] = '0'; hoverDiv.className = 'hover-div'; hoverDiv.classList.add(position); document.querySelector('#app').appendChild(hoverDiv); return hoverDiv; } function generalCSS() { return ` #header, .mainbar, .bookmark-bar, #panels-container { transition: transform .5s, opacity .5s ease-in-out !important; } #header, .mainbar { z-index: 8; } .bookmark-bar { z-index: 7; } #header .vivaldi { margin-top: 3px; } #main { padding-top: 0 !important; } #webview-container { position: fixed !important; top: 0; left: 0; right: 0; bottom: 0; } #panels-container { position: fixed !important; } .extensionIconPopupMenu, .button-popup { z-index: 8; } footer { margin-top: auto !important; } .hover-div { transition: visibility 0.5s ease-in-out; } `; } function topCSS() { const topElements = []; let height = 0; if (tabBarPosition === 'top' || !addressBarTop) { topElements.push('#header'); height += header?.offsetHeight || 0; } if (addressBarTop) { topElements.push('.mainbar'); height += mainBar?.offsetHeight || 0; } if (bookmarksTop && bookmarkBar) { topElements.push('.bookmark-bar'); height += bookmarkBar?.offsetHeight || 0; } if (topElements.length === 0) { return ''; } let css = ` &.hidden-top { ${topElements.join(', ')} { transform: translateY(-${height}px); opacity: 0; } } &:not(.hidden-top) .hover-div.top { visibility: hidden; } `; if (showAddressBarOnNewTab && addressBarTop) { css += ` &.hidden-top #browser:has(.internal-page .startpage) { .mainbar { opacity: 1; .UrlBar-AddressField { position: absolute; top: ${height}px; left: 25vw; right: 25vw; width: 50vw !important; } } } `; } if (bookmarksTop && addressBarTop) { css += ` .bookmark-bar-top-off .mainbar { padding-bottom: 5px; background: var(--colorAccentBg); } `; } if (bookmarksTop) { css += ` .bookmark-bar { margin-top: 0; } `; } return css; } function leftCSS() { const leftElements = []; let width = 0, tabbarWrapper; if (tabBarPosition === 'left') { leftElements.push('.tabbar-wrapper'); tabbarWrapper = document.querySelector('.tabbar-wrapper'); width += tabbarWrapper.offsetWidth; } if (hidePanels && panelsLeft) { leftElements.push('#panels-container'); width += panelsContainer.offsetWidth; } if (leftElements.length === 0) { return ''; } let css = ` &.hidden-left { ${leftElements.join(', ')} { transform: translateX(-${width}px); opacity: 0; } } &:not(.hidden-left) .hover-div.left { visibility: hidden; } `; if (tabBarPosition === 'left') { css += ` .tabbar-wrapper { position: fixed; top: 0; left: ${panelsLeft ? panelsContainer.offsetWidth : 0}px; z-index: 1; transition: transform .5s, opacity .5s ease-in-out !important; } `; } if (hidePanels && panelsLeft) { css += ` #webview-container { margin-left: ${verticalMargin}; /*margin-left: calc(-${panelsContainer.offsetWidth}px + ${verticalMargin});*/ } `; } return css; } function rightCSS() { const rightElements = []; let width = 0, tabbarWrapper; if (tabBarPosition === 'right') { rightElements.push('.tabbar-wrapper'); tabbarWrapper = document.querySelector('.tabbar-wrapper'); width += tabbarWrapper.offsetWidth; } if (hidePanels && !panelsLeft) { rightElements.push('#panels-container'); width += panelsContainer.offsetWidth; } if (rightElements.length === 0) { return ''; } let css = ` &.hidden-right { ${rightElements.join(', ')} { transform: translateX(${width}px); opacity: 0; } } &:not(.hidden-right) .hover-div.right { visibility: hidden; } `; if (tabBarPosition === 'right') { css += ` .tabbar-wrapper { position: fixed; top: 0; right: ${!panelsLeft ? panelsContainer.offsetWidth : 0}px; z-index: 1; transition: transform .5s, opacity .5s ease-in-out !important; } `; } if (hidePanels && !panelsLeft) { css += ` #webview-container { margin-right: ${verticalMargin}; /*margin-left: calc(-${panelsContainer.offsetWidth}px + ${verticalMargin});*/ } `; } return css; } function bottomCSS() { const bottomElements = []; let height = 0, tabbarWrapper; if (tabBarPosition === 'bottom') { bottomElements.push('#footer') tabbarWrapper = document.querySelector('#footer'); height += tabbarWrapper?.offsetHeight || 0; } if (!addressBarTop) { bottomElements.push('.mainbar'); height += mainBar?.offsetHeight || 0; } if (!bookmarksTop && bookmarkBar) { bottomElements.push('.bookmark-bar'); height += bookmarkBar?.offsetHeight || 0; } if (bottomElements.length === 0) { return ''; } let css = ` &.hidden-bottom { ${bottomElements.join(', ')} { transform: translateY(${height}px); opacity: 0; } } &:not(.hidden-bottom) .hover-div.bottom { visibility: hidden; } `; if (showAddressBarOnNewTab && !addressBarTop) { css += ` &.hidden-bottom #browser:has(.internal-page .startpage) { .mainbar { opacity: 1; .UrlBar-AddressField { position: absolute; bottom: ${mainBar.offsetHeight + 10}px; left: 25vw; right: 25vw; width: 50vw !important; } } } `; } if (tabBarPosition === 'bottom') { css += ` #footer { transition: transform .5s, opacity .5s ease-in-out !important; } `; } if (!bookmarksTop && !addressBarTop) { css += ` .bookmark-bar-bottom-off .mainbar { padding-bottom: -5px; background: var(--colorAccentBg); } `; } if (!bookmarksTop) { css += ` .bookmark-bar { margin-bottom: 0; } `; } return css; } })();
-
It totally did. Thank you very much.
-
@ekozcifci O wow. Can I get a link to this browser theme? I like the colors.
-
-
This post is deleted! -
Can someone help with a problem like this?
https://www.youtube.com/watch?v=lxTv7zYwe-0&feature=youtu.be -
@Xiean for vertical tabs you have to use this code:
/** * Forum link: https://forum.vivaldi.net/topic/92477/some-javascript-to-automatically-hide-tab-bar-and-address-bar-and-show-them-by-hovering * Hides the tab bar and address bar when not hovering */ (function checkWebViewForFullscreen() { const webView = document.querySelector('#webview-container'), hidePanels = true, // set to false to not hide the panels verticalMargin = '0px', // 'var(--edge-like-border-radius) / 2', // set to '0px' to remove the margin left bookmarkBarPadding = '6px', // set to '0px' to remove the padding around the bookmark bar delay = 125, // set to 0 to remove the delay showAddressBarOnNewTab = true; // shows the address bar on a new tab - set to false to disable the feature if (!webView) { setTimeout(checkWebViewForFullscreen, 1337); return; } const positions = ['top', 'bottom', 'left', 'right'], app = document.querySelector('#app'), browser = document.querySelector('#browser'), header = document.querySelector('#header'), mainBar = document.querySelector('.mainbar'), bookmarkBar = document.querySelector('.bookmark-bar'), panelsContainer = document.querySelector('#panels-container'), tabBarClassList = document.querySelector('#tabs-tabbar-container').classList, panelsLeft = document.querySelector('#panels-container').classList.contains('left'), tabBarPosition = positions.find(cls => tabBarClassList.contains(cls)), addressBarTop = browser.classList.contains('address-top'), bookmarksTop = browser.classList.contains('bookmark-bar-top'); let fullscreenEnabled, showTopTimeout, showLeftTimeout, showRightTimeout, showBottomTimeout; chrome.storage.local.get('fullScreenModEnabled').then((value) => { fullscreenEnabled = value.fullScreenModEnabled || value.fullScreenModEnabled == undefined; if (fullscreenEnabled) { addFullScreenListener(); } }); vivaldi.tabsPrivate.onKeyboardShortcut.addListener((id, combination) => combination === 'F11' && toggleFullScreen()); let style = ` .fullscreen-listener-enabled { ${generalCSS()} ${topCSS()} ${leftCSS()} ${rightCSS()} ${bottomCSS()} } #app:not(.fullscreen-listener-enabled) .hover-div { visibility: hidden; } `; if (bookmarkBarPadding) { style += ` .fullscreen-listener-enabled .bookmark-bar { height: auto; padding-top: ${bookmarkBarPadding}; padding-bottom: calc(${bookmarkBarPadding} / 2); } `; } const styleEl = document.createElement('style'); styleEl.appendChild(document.createTextNode(style)); document.head.appendChild(styleEl); const hoverDivTop = createHorizontalHoverDiv('top'), hoverDivLeft = (hidePanels && panelsLeft) || tabBarPosition === 'left' ? createVerticalHoverDiv('left') : undefined, hoverDivRight = (hidePanels && !panelsLeft) || tabBarPosition === 'right' ? createVerticalHoverDiv('right') : undefined, hoverDivBottom = !addressBarTop || tabBarPosition === 'bottom' || !bookmarksTop ? createHorizontalHoverDiv('bottom') : undefined; function toggleFullScreen() { fullscreenEnabled = !fullscreenEnabled; fullscreenEnabled ? addFullScreenListener() : removeFullScreenListener(); chrome.storage.local.set({fullScreenModEnabled: fullscreenEnabled}); } function addFullScreenListener() { app.classList.add('fullscreen-listener-enabled'); webView.addEventListener('pointerenter', hide); hoverDivTop.addEventListener('pointerenter', showTop); hoverDivTop.addEventListener('pointerleave', clearTimeouts); if (hoverDivLeft) { hoverDivLeft.addEventListener('pointerenter', showLeft); hoverDivLeft.addEventListener('pointerleave', clearTimeouts); } if (hoverDivRight) { hoverDivRight.addEventListener('pointerenter', showRight); hoverDivRight.addEventListener('pointerleave', clearTimeouts); } if (hoverDivBottom) { hoverDivBottom.addEventListener('pointerenter', showBottom); hoverDivBottom.addEventListener('pointerleave', clearTimeouts); } hide(); } function removeFullScreenListener() { app.classList.remove('fullscreen-listener-enabled'); webView.removeEventListener('pointerenter', hide); hoverDivTop.removeEventListener('pointerenter', showTop); hoverDivTop.removeEventListener('pointerleave', clearTimeouts); if (hoverDivLeft) { hoverDivLeft.removeEventListener('pointerenter', showLeft); hoverDivLeft.removeEventListener('pointerleave', clearTimeouts); } if (hoverDivRight) { hoverDivRight.removeEventListener('pointerenter', showRight); hoverDivRight.removeEventListener('pointerleave', clearTimeouts); } if (hoverDivBottom) { hoverDivBottom.removeEventListener('pointerenter', showBottom); hoverDivBottom.removeEventListener('pointerleave', clearTimeouts); } show(); } function clearTimeouts() { if (showTopTimeout) clearTimeout(showTopTimeout); if (showLeftTimeout) clearTimeout(showLeftTimeout); if (showRightTimeout) clearTimeout(showRightTimeout); if (showBottomTimeout) clearTimeout(showBottomTimeout); } function hide() { app.classList.add('hidden-top'); if (hoverDivLeft) app.classList.add('hidden-left'); if (hoverDivRight) app.classList.add('hidden-right'); if (hoverDivBottom) app.classList.add('hidden-bottom'); } function show() { showTop(); showLeft(); showRight(); showBottom(); } function showTop() { showTopTimeout = setTimeout(() => app.classList.remove('hidden-top'), delay); } function showLeft() { if (hoverDivLeft) { showLeftTimeout = setTimeout(() => app.classList.remove('hidden-left'), delay); } } function showRight() { if (hoverDivRight) { showRightTimeout = setTimeout(() => app.classList.remove('hidden-right'), delay); } } function showBottom() { if (hoverDivBottom) { showBottomTimeout = setTimeout(() => app.classList.remove('hidden-bottom'), delay); } } function createHorizontalHoverDiv(position) { const hoverDiv = document.createElement('div'); hoverDiv.style.height = '1.5rem'; hoverDiv.style.width = '100vw'; hoverDiv.style.position = 'fixed'; hoverDiv.style.left = '0'; hoverDiv.style.zIndex = '10'; hoverDiv.style[position] = '0'; hoverDiv.className = 'hover-div'; hoverDiv.classList.add(position); document.querySelector('#app').appendChild(hoverDiv); return hoverDiv; } function createVerticalHoverDiv(position) { const hoverDiv = document.createElement('div'); hoverDiv.style.height = '100%'; hoverDiv.style.width = '1.5rem'; hoverDiv.style.position = 'fixed'; hoverDiv.style.top = '0'; hoverDiv.style.zIndex = '10'; hoverDiv.style[position] = '0'; hoverDiv.className = 'hover-div'; hoverDiv.classList.add(position); document.querySelector('#app').appendChild(hoverDiv); return hoverDiv; } function generalCSS() { return ` #header, .mainbar, .bookmark-bar, #panels-container { transition: transform .5s, opacity .5s ease-in-out !important; } #header, .mainbar { z-index: 8; } .bookmark-bar { z-index: 7; } #header .vivaldi { margin-top: 3px; } #main { padding-top: 0 !important; } #webview-container { position: fixed !important; top: 0; left: 0; right: 0; bottom: 0; } #panels-container { position: fixed !important; } .extensionIconPopupMenu, .button-popup { z-index: 8; } footer { margin-top: auto !important; } .hover-div { transition: visibility 0.5s ease-in-out; } `; } function topCSS() { const topElements = []; let height = 0; if (tabBarPosition === 'top' || !addressBarTop) { topElements.push('#header'); height += header?.offsetHeight || 0; } if (addressBarTop) { topElements.push('.mainbar'); height += mainBar?.offsetHeight || 0; } if (bookmarksTop && bookmarkBar) { topElements.push('.bookmark-bar'); height += bookmarkBar?.offsetHeight || 0; } if (topElements.length === 0) { return ''; } let css = ` &.hidden-top { ${topElements.join(', ')} { transform: translateY(-${height}px); opacity: 0; } } &:not(.hidden-top) .hover-div.top { visibility: hidden; } `; if (showAddressBarOnNewTab && addressBarTop) { css += ` &.hidden-top #browser:has(.internal-page .startpage) { .mainbar { opacity: 1; .UrlBar-AddressField { position: absolute; top: ${height}px; left: 25vw; right: 25vw; width: 50vw !important; } } } `; } if (bookmarksTop && addressBarTop) { css += ` .bookmark-bar-top-off .mainbar { padding-bottom: 5px; background: var(--colorAccentBg); } `; } if (bookmarksTop) { css += ` .bookmark-bar { margin-top: 0; } `; } return css; } function leftCSS() { const leftElements = []; let width = 0, tabbarWrapper; if (tabBarPosition === 'left') { leftElements.push('.tabbar-wrapper'); tabbarWrapper = document.querySelector('.tabbar-wrapper'); width += tabbarWrapper.offsetWidth; } if (hidePanels && panelsLeft) { leftElements.push('#panels-container'); width += panelsContainer.offsetWidth; } if (leftElements.length === 0) { return ''; } let css = ` &.hidden-left { ${leftElements.join(', ')} { transform: translateX(-${width}px); opacity: 0; } } &:not(.hidden-left) .hover-div.left { visibility: hidden; } `; if (tabBarPosition === 'left') { css += ` .tabbar-wrapper { position: fixed; top: 0; left: ${panelsLeft ? panelsContainer.offsetWidth : 0}px; z-index: 1; transition: transform .5s, opacity .5s ease-in-out !important; } `; } if (hidePanels && panelsLeft) { css += ` #webview-container { margin-left: ${verticalMargin}; /*margin-left: calc(-${panelsContainer.offsetWidth}px + ${verticalMargin});*/ } `; } return css; } function rightCSS() { const rightElements = []; let width = 0, tabbarWrapper; if (tabBarPosition === 'right') { rightElements.push('.tabbar-wrapper'); tabbarWrapper = document.querySelector('.tabbar-wrapper'); width += tabbarWrapper.offsetWidth; } if (hidePanels && !panelsLeft) { rightElements.push('#panels-container'); width += panelsContainer.offsetWidth; } if (rightElements.length === 0) { return ''; } let css = ` &.hidden-right { ${rightElements.join(', ')} { transform: translateX(${width}px); opacity: 0; } } &:not(.hidden-right) .hover-div.right { visibility: hidden; } `; if (tabBarPosition === 'right') { css += ` .tabbar-wrapper { position: fixed; top: 0; right: ${!panelsLeft ? panelsContainer.offsetWidth : 0}px; z-index: 1; transition: transform .5s, opacity .5s ease-in-out !important; } `; } if (hidePanels && !panelsLeft) { css += ` #webview-container { margin-right: ${verticalMargin}; /*margin-left: calc(-${panelsContainer.offsetWidth}px + ${verticalMargin});*/ } `; } return css; } function bottomCSS() { const bottomElements = []; let height = 0, tabbarWrapper; if (tabBarPosition === 'bottom') { bottomElements.push('#footer') tabbarWrapper = document.querySelector('#footer'); height += tabbarWrapper?.offsetHeight || 0; } if (!addressBarTop) { bottomElements.push('.mainbar'); height += mainBar?.offsetHeight || 0; } if (!bookmarksTop && bookmarkBar) { bottomElements.push('.bookmark-bar'); height += bookmarkBar?.offsetHeight || 0; } if (bottomElements.length === 0) { return ''; } let css = ` &.hidden-bottom { ${bottomElements.join(', ')} { transform: translateY(${height}px); opacity: 0; } } &:not(.hidden-bottom) .hover-div.bottom { visibility: hidden; } `; if (showAddressBarOnNewTab && !addressBarTop) { css += ` &.hidden-bottom #browser:has(.internal-page .startpage) { .mainbar { opacity: 1; .UrlBar-AddressField { position: absolute; bottom: ${mainBar.offsetHeight + 10}px; left: 25vw; right: 25vw; width: 50vw !important; } } } `; } if (tabBarPosition === 'bottom') { css += ` #footer { transition: transform .5s, opacity .5s ease-in-out !important; } `; } if (!bookmarksTop && !addressBarTop) { css += ` .bookmark-bar-bottom-off .mainbar { padding-bottom: -5px; background: var(--colorAccentBg); } `; } if (!bookmarksTop) { css += ` .bookmark-bar { margin-bottom: 0; } `; } return css; } })();
-
Some problems have surfaced:
- Tabs are now hidden, I want to keep them
- All panels are now transparent
- Problem with opening the address bar in some places
- the address bar is hidden even if the extension window is open or the focus is on the link bar.
-
This post is deleted! -
This post is deleted! -
Hi! I'm new to Vivaldi, but I switched to it (from Chrome) because of this very script
. I recently bought an OLED monitor, and it has the potential for image retention / burn-in, so I wanted a way to auto-hide my Chrome tabs, just like the Windows taskbar. You have my gratitude, @oudstand!
It works really well, but I saw an opportunity to implement some improvements. I'm not a web developer, and in fact I really struggle with JS and especially css, but I gave it a go. Here's the list of changes I made:
- Hiding now has its own delay, and it can be cancelled if the user re-enters the mainBar or the side panel quickly enough.
- Motivation: say I was somewhere within the tab bar, towards the right, but I wanted to quickly move to the left of it, so I can hit the page's Reload button. If I accidentally left the mainBar even for a single pixel during this movement, the whole UI would hide. That felt too punishing to me. I now have a whole second (configurable) to get back in.
- I felt that the hover area/div was too large. Lots of pages hide a search box (or other important elements) near the top, and it was sometimes impossible to click there, because the tab bar would come out of hiding instead. My solution was to make it so if the Vivaldi window is maximized, the hover div becomes only 1 pixel tall. Which means you have to deliberately move the mouse to the very top of the screen, to activate it and show the tab bar. This way, it works like the auto-hidden taskbar in Windows. That feels intuitive to me.
- If the window is not maximized, it retains the old behaviour (since you'd struggle to hit that one pixel in that case - in fact I think it was impossible).
- The url field is now made visible on all pages if it has the focus while the address bar is hidden, not just the start page.
- I didn't see a reason not to have this behaviour on every page, and luckily there was an easy css-based solution.
- Importantly, this seems to solve a bug that your version has in more recent versions of Vivaldi, where the url field remains visible on every page, regardless of focus. Not sure why that happens (something to do with
#browser:has(.internal-page .startpage)
, but beyond that...). Fixing this was a lucky side-effect of my change, but I'll take it!
- I changed the toggle shortcut to Ctrl+F3, since Vivaldi seems to want to own F11.
Not sure if my solutions are in any way mergeable with your official version. I wouldn't blame you if you hate them all
. Also, I'm unlikely to be able to offer support to people here, so I would probably advice everyone to stick with your future versions instead. For example, I didn't really test the right or bottom configurations (only tabbar = top, side panel = left)... Still, I couldn't not share my improvements here
.
Anyway, here is the script:
/** * Forum link: https://forum.vivaldi.net/topic/92477/some-javascript-to-automatically-hide-tab-bar-and-address-bar-and-show-them-by-hovering * Hides the tab bar and address bar when not hovering. * To debug this script, go to vivaldi:inspect#extensions, and press "inspect" on the entry for window.html. */ (function checkWebViewForFullscreen() { const webView = document.querySelector('#webview-container'), hidePanels = true, // set to false to not hide the panels verticalMargin = '0px', // 'var(--edge-like-border-radius) / 2', // set to '0px' to remove the margin left bookmarkBarPadding = '6px', // set to '0px' to remove the padding around the bookmark bar delay = 125, // set to 0 to remove the delay // It makes sense to have a smaller / non-existent delay, when the window is maximized, so it works more like // the Windows taskbar when that's in auto-hide mode. delayWhenWindowsIsMaximized = 0, // It feels better to not hide the tabbar/etc immediately. It's less punishing for the user, if they intended to stay within the tabbar/etc area, but just // happened to move the mouse a bit too fast (perhaps to reach the Refresh button which is near the bottom). // Set to 0 to remove the delay. hideDelay = 1000, showAddressBarWhenFocusedEvenIfHidden = true; // shows the address bar if it's focused when the main bar is hidden - set to false to disable the feature if (!webView) { setTimeout(checkWebViewForFullscreen, 1337); return; } const positions = ['top', 'bottom', 'left', 'right'], app = document.querySelector('#app'), browser = document.querySelector('#browser'), header = document.querySelector('#header'), mainBar = document.querySelector('.mainbar'), bookmarkBar = document.querySelector('.bookmark-bar'), panelsContainer = document.querySelector('#panels-container'), tabBarClassList = document.querySelector('#tabs-tabbar-container').classList, panelsLeft = document.querySelector('#panels-container').classList.contains('left'), tabBarPosition = positions.find(cls => tabBarClassList.contains(cls)), addressBarTop = browser.classList.contains('address-top'), bookmarksTop = browser.classList.contains('bookmark-bar-top'); let fullscreenEnabled, showTopTimeout, showLeftTimeout, showRightTimeout, showBottomTimeout, hideTopTimeout, hideLeftTimeout; chrome.storage.local.get('fullScreenModEnabled').then((value) => { fullscreenEnabled = value.fullScreenModEnabled || value.fullScreenModEnabled == undefined; if (fullscreenEnabled) { addFullScreenListener(); } }); vivaldi.tabsPrivate.onKeyboardShortcut.addListener((id, combination) => combination === 'Ctrl+F3' && toggleFullScreen()); let style = ` .fullscreen-listener-enabled { ${generalCSS()} ${topCSS()} ${leftCSS()} ${rightCSS()} ${bottomCSS()} } #app:not(.fullscreen-listener-enabled) .hover-div { visibility: hidden; } `; if (bookmarkBarPadding) { style += ` .fullscreen-listener-enabled .bookmark-bar { height: auto; padding-top: ${bookmarkBarPadding}; padding-bottom: calc(${bookmarkBarPadding} / 2); } `; } const styleEl = document.createElement('style'); styleEl.appendChild(document.createTextNode(style)); document.head.appendChild(styleEl); const hoverDivTop = createHorizontalHoverDiv('top'), hoverDivLeft = (hidePanels && panelsLeft) || tabBarPosition === 'left' ? createVerticalHoverDiv('left') : undefined, hoverDivRight = (hidePanels && !panelsLeft) || tabBarPosition === 'right' ? createVerticalHoverDiv('right') : undefined, hoverDivBottom = !addressBarTop || tabBarPosition === 'bottom' || !bookmarksTop ? createHorizontalHoverDiv('bottom') : undefined; function toggleFullScreen() { fullscreenEnabled = !fullscreenEnabled; fullscreenEnabled ? addFullScreenListener() : removeFullScreenListener(); chrome.storage.local.set({fullScreenModEnabled: fullscreenEnabled}); } function addFullScreenListener() { app.classList.add('fullscreen-listener-enabled'); webView.addEventListener('pointerenter', hide); // If the user re-enters these UI elements before the hideDelay expires, the hide will be cancelled. mainBar.addEventListener('pointerenter', clearHideTopTimeout); panelsContainer.addEventListener('pointerenter', clearHideLeftTimeout); hoverDivTop.addEventListener('pointerenter', showTop); hoverDivTop.addEventListener('pointerleave', clearTimeouts); if (hoverDivLeft) { hoverDivLeft.addEventListener('pointerenter', showLeft); hoverDivLeft.addEventListener('pointerleave', clearTimeouts); } if (hoverDivRight) { hoverDivRight.addEventListener('pointerenter', showRight); hoverDivRight.addEventListener('pointerleave', clearTimeouts); } if (hoverDivBottom) { hoverDivBottom.addEventListener('pointerenter', showBottom); hoverDivBottom.addEventListener('pointerleave', clearTimeouts); } hide(); } function removeFullScreenListener() { app.classList.remove('fullscreen-listener-enabled'); webView.removeEventListener('pointerenter', hide); mainBar.removeEventListener('pointerenter', clearHideTopTimeout); panelsContainer.removeEventListener('pointerenter', clearHideLeftTimeout); hoverDivTop.removeEventListener('pointerenter', showTop); hoverDivTop.removeEventListener('pointerleave', clearTimeouts); if (hoverDivLeft) { hoverDivLeft.removeEventListener('pointerenter', showLeft); hoverDivLeft.removeEventListener('pointerleave', clearTimeouts); } if (hoverDivRight) { hoverDivRight.removeEventListener('pointerenter', showRight); hoverDivRight.removeEventListener('pointerleave', clearTimeouts); } if (hoverDivBottom) { hoverDivBottom.removeEventListener('pointerenter', showBottom); hoverDivBottom.removeEventListener('pointerleave', clearTimeouts); } show(); } function clearHideTopTimeout() { if (hideTopTimeout) clearTimeout(hideTopTimeout); } function clearHideLeftTimeout() { if (hideLeftTimeout) clearTimeout(hideLeftTimeout); } function clearTimeouts() { if (showTopTimeout) clearTimeout(showTopTimeout); if (showLeftTimeout) clearTimeout(showLeftTimeout); if (showRightTimeout) clearTimeout(showRightTimeout); if (showBottomTimeout) clearTimeout(showBottomTimeout); clearHideTopTimeout(); clearHideLeftTimeout(); } function hide() { hideTopTimeout = setTimeout(() => app.classList.add('hidden-top'), hideDelay); if (hoverDivLeft) { hideLeftTimeout = setTimeout(() => app.classList.add('hidden-left'), hideDelay); } if (hoverDivRight) app.classList.add('hidden-right'); if (hoverDivBottom) app.classList.add('hidden-bottom'); } function getDelayForCurrentWindowState() { if (isWindowMaximized()) { return delayWhenWindowsIsMaximized; } else { return delay; } } function show() { showTop(); showLeft(); showRight(); showBottom(); } function showTop() { showTopTimeout = setTimeout(() => app.classList.remove('hidden-top'), getDelayForCurrentWindowState()); } function showLeft() { if (hoverDivLeft) { showLeftTimeout = setTimeout(() => app.classList.remove('hidden-left'), getDelayForCurrentWindowState()); } } function showRight() { if (hoverDivRight) { showRightTimeout = setTimeout(() => app.classList.remove('hidden-right'), getDelayForCurrentWindowState()); } } function showBottom() { if (hoverDivBottom) { showBottomTimeout = setTimeout(() => app.classList.remove('hidden-bottom'), getDelayForCurrentWindowState()); } } function isWindowMaximized() { return window.outerWidth === screen.availWidth && window.outerHeight === screen.availHeight; } function adjustHorizontalHoverDivHeight(horizontalHoverDiv) { if (isWindowMaximized()) { // Normally, we want to be able to interact with elements near the top or bottom edges of the page, so the // hover div needs to be as thin as possible. When the window is maximized, the div can be reached with a // deliberately fast movement of the mouse towards the top or bottom edge of the screen. This way, the div // behaves like the auto-hidden taskbar in Windows. horizontalHoverDiv.style.height = '1px'; } else { // When the window is not maximized, the hover div cannot easily be reached with a simple deliberately fast // movement of the mouse. There needs to be a larger area where the user needs to hover, to trigger the // corresponding show() function. horizontalHoverDiv.style.height = '1.5rem'; } } function createHorizontalHoverDiv(position) { const hoverDiv = document.createElement('div'); adjustHorizontalHoverDivHeight(hoverDiv); hoverDiv.style.width = '100vw'; hoverDiv.style.position = 'fixed'; hoverDiv.style.left = '0'; hoverDiv.style.zIndex = '10'; hoverDiv.style[position] = '0'; hoverDiv.className = 'hover-div'; hoverDiv.classList.add(position); document.querySelector('#app').appendChild(hoverDiv); return hoverDiv; } addEventListener("resize", (event) => { adjustHorizontalHoverDivHeight(hoverDivTop); if (hoverDivBottom) { adjustHorizontalHoverDivHeight(hoverDivBottom); } }); function createVerticalHoverDiv(position) { const hoverDiv = document.createElement('div'); hoverDiv.style.height = '100%'; hoverDiv.style.width = '1.5rem'; hoverDiv.style.position = 'fixed'; hoverDiv.style.top = '0'; hoverDiv.style.zIndex = '10'; hoverDiv.style[position] = '0'; hoverDiv.className = 'hover-div'; hoverDiv.classList.add(position); document.querySelector('#app').appendChild(hoverDiv); return hoverDiv; } function generalCSS() { return ` #header, .mainbar, .bookmark-bar, #panels-container { transition: transform .5s, opacity .5s ease-in-out !important; } #header, .mainbar { z-index: 8; } .bookmark-bar { z-index: 7; } #header .vivaldi { margin-top: 3px; } #main { padding-top: 0 !important; } #webview-container { position: fixed !important; top: 0; left: 0; right: 0; bottom: 0; } #panels-container { position: fixed !important; } .extensionIconPopupMenu, .button-popup { z-index: 8; } footer { margin-top: auto !important; } .hover-div { transition: visibility 0.5s ease-in-out; } `; } function topCSS() { const topElements = []; let height = 0; if (tabBarPosition === 'top' || !addressBarTop) { topElements.push('#header'); height += header?.offsetHeight || 0; } if (addressBarTop) { topElements.push('.mainbar'); height += mainBar?.offsetHeight || 0; } if (bookmarksTop && bookmarkBar) { topElements.push('.bookmark-bar'); height += bookmarkBar?.offsetHeight || 0; } if (topElements.length === 0) { return ''; } let css = ` &.hidden-top { ${topElements.join(', ')} { transform: translateY(-${height}px); opacity: 0; } } &:not(.hidden-top) .hover-div.top { visibility: hidden; } `; if (showAddressBarWhenFocusedEvenIfHidden && addressBarTop) { css += ` &.hidden-top { .mainbar { opacity: 1; .UrlBar-AddressField:focus-within { position: absolute; top: ${height}px; left: 25vw; right: 25vw; width: 50vw !important; } } } `; } if (bookmarksTop && addressBarTop) { css += ` .bookmark-bar-top-off .mainbar { padding-bottom: 5px; background: var(--colorAccentBg); } `; } if (bookmarksTop) { css += ` .bookmark-bar { margin-top: 0; } `; } return css; } function leftCSS() { const leftElements = []; let width = 0, tabbarWrapper; if (tabBarPosition === 'left') { leftElements.push('.tabbar-wrapper'); tabbarWrapper = document.querySelector('.tabbar-wrapper'); width += tabbarWrapper.offsetWidth; } if (hidePanels && panelsLeft) { leftElements.push('#panels-container'); width += panelsContainer.offsetWidth; } if (leftElements.length === 0) { return ''; } let css = ` &.hidden-left { ${leftElements.join(', ')} { transform: translateX(-${width}px); opacity: 0; } } &:not(.hidden-left) .hover-div.left { visibility: hidden; } `; if (tabBarPosition === 'left') { css += ` .tabbar-wrapper { position: fixed; top: 0; left: ${panelsLeft ? panelsContainer.offsetWidth : 0}px; z-index: 1; transition: transform .5s, opacity .5s ease-in-out !important; } `; } if (hidePanels && panelsLeft) { css += ` #webview-container { margin-left: ${verticalMargin}; /*margin-left: calc(-${panelsContainer.offsetWidth}px + ${verticalMargin});*/ } `; } return css; } function rightCSS() { const rightElements = []; let width = 0, tabbarWrapper; if (tabBarPosition === 'right') { rightElements.push('.tabbar-wrapper'); tabbarWrapper = document.querySelector('.tabbar-wrapper'); width += tabbarWrapper.offsetWidth; } if (hidePanels && !panelsLeft) { rightElements.push('#panels-container'); width += panelsContainer.offsetWidth; } if (rightElements.length === 0) { return ''; } let css = ` &.hidden-right { ${rightElements.join(', ')} { transform: translateX(${width}px); opacity: 0; } } &:not(.hidden-right) .hover-div.right { visibility: hidden; } `; if (tabBarPosition === 'right') { css += ` .tabbar-wrapper { position: fixed; top: 0; right: ${!panelsLeft ? panelsContainer.offsetWidth : 0}px; z-index: 1; transition: transform .5s, opacity .5s ease-in-out !important; } `; } if (hidePanels && !panelsLeft) { css += ` #webview-container { margin-right: ${verticalMargin}; /*margin-left: calc(-${panelsContainer.offsetWidth}px + ${verticalMargin});*/ } `; } return css; } function bottomCSS() { const bottomElements = []; let height = 0, tabbarWrapper; if (tabBarPosition === 'bottom') { bottomElements.push('#footer') tabbarWrapper = document.querySelector('#footer'); height += tabbarWrapper?.offsetHeight || 0; } if (!addressBarTop) { bottomElements.push('.mainbar'); height += mainBar?.offsetHeight || 0; } if (!bookmarksTop && bookmarkBar) { bottomElements.push('.bookmark-bar'); height += bookmarkBar?.offsetHeight || 0; } if (bottomElements.length === 0) { return ''; } let css = ` &.hidden-bottom { ${bottomElements.join(', ')} { transform: translateY(${height}px); opacity: 0; } } &:not(.hidden-bottom) .hover-div.bottom { visibility: hidden; } `; if (showAddressBarWhenFocusedEvenIfHidden && !addressBarTop) { css += ` &.hidden-bottom { .mainbar { opacity: 1; .UrlBar-AddressField:focus-within { position: absolute; bottom: ${mainBar.offsetHeight + 10}px; left: 25vw; right: 25vw; width: 50vw !important; } } } `; } if (tabBarPosition === 'bottom') { css += ` #footer { transition: transform .5s, opacity .5s ease-in-out !important; } `; } if (!bookmarksTop && !addressBarTop) { css += ` .bookmark-bar-bottom-off .mainbar { padding-bottom: -5px; background: var(--colorAccentBg); } `; } if (!bookmarksTop) { css += ` .bookmark-bar { margin-bottom: 0; } `; } return css; } })();
Thanks again!
- Hiding now has its own delay, and it can be cancelled if the user re-enters the mainBar or the side panel quickly enough.
-
Hey @kostasvl, thanks for sharing this!
I think the delay for hiding the elements is a good idea and also that you adjust the size of the hover area. I was just wondering why you want to have a different delay when the window is maximized?I noticed there is a bit optimization potential, but I'll add the changes to the code.
I picked
F11
as shortcut, because it feels more familiar to me. In the keyboard shortcut settings you can remove Vivalids implementation of the Fullscreen to avoid problems. -
@kostasvl I've implemented your changes, but adjusted them a little bit. The reduction of the
hoverDiv
size is now optional and controllable by the propertyupdateHoverDivSize
and also works for thehoverDiv
on the left and right./** * Forum link: https://forum.vivaldi.net/topic/92477/some-javascript-to-automatically-hide-tab-bar-and-address-bar-and-show-them-by-hovering * Hides the tab bar and address bar when not hovering */ (function checkWebViewForFullscreen() { const webView = document.querySelector('#webview-container'), hidePanels = true, // set to false to not hide the panels verticalMargin = '0px', // 'var(--edge-like-border-radius) / 2', // set to '0px' to remove the margin left bookmarkBarPadding = '6px', // set to '0px' to remove the padding around the bookmark bar showDelay = 125, // set to 0 to remove the delay hideDelay = 500, // set to 0 to remove the delay showAddressBarOnFocus = true, // shows the address bar on a new tab or if in focus - set to false to disable the feature updateHoverDivSize = true; // decreases the size for the hover divs in fullscreen mode - set ti false to disable the feature if (!webView) { setTimeout(checkWebViewForFullscreen, 1337); return; } const positions = ['top', 'bottom', 'left', 'right'], app = document.querySelector('#app'), browser = document.querySelector('#browser'), header = document.querySelector('#header'), mainBar = document.querySelector('.mainbar'), bookmarkBar = document.querySelector('.bookmark-bar'), panelsContainer = document.querySelector('#panels-container'), tabBarClassList = document.querySelector('#tabs-tabbar-container').classList, panelsLeft = document.querySelector('#panels-container').classList.contains('left'), tabBarPosition = positions.find(cls => tabBarClassList.contains(cls)), addressBarTop = browser.classList.contains('address-top'), bookmarksTop = browser.classList.contains('bookmark-bar-top'); let fullscreenEnabled, showTopTimeout, showLeftTimeout, showRightTimeout, showBottomTimeout, hideTimeout; chrome.storage.local.get('fullScreenModEnabled').then((value) => { fullscreenEnabled = value.fullScreenModEnabled || value.fullScreenModEnabled == undefined; if (fullscreenEnabled) { addFullScreenListener(); } }); vivaldi.tabsPrivate.onKeyboardShortcut.addListener((id, combination) => combination === 'F11' && toggleFullScreen()); let style = ` .fullscreen-listener-enabled { ${generalCSS()} ${topCSS()} ${leftCSS()} ${rightCSS()} ${bottomCSS()} } #app:not(.fullscreen-listener-enabled) .hover-div { visibility: hidden; } `; if (bookmarkBarPadding) { style += ` .fullscreen-listener-enabled .bookmark-bar { height: auto; padding-top: ${bookmarkBarPadding}; padding-bottom: calc(${bookmarkBarPadding} / 2); } `; } const styleEl = document.createElement('style'); styleEl.appendChild(document.createTextNode(style)); document.head.appendChild(styleEl); const hoverDivTop = createHorizontalHoverDiv('top'), hoverDivLeft = (hidePanels && panelsLeft) || tabBarPosition === 'left' ? createVerticalHoverDiv('left') : undefined, hoverDivRight = (hidePanels && !panelsLeft) || tabBarPosition === 'right' ? createVerticalHoverDiv('right') : undefined, hoverDivBottom = !addressBarTop || tabBarPosition === 'bottom' || !bookmarksTop ? createHorizontalHoverDiv('bottom') : undefined; function toggleFullScreen() { fullscreenEnabled = !fullscreenEnabled; fullscreenEnabled ? addFullScreenListener() : removeFullScreenListener(); chrome.storage.local.set({fullScreenModEnabled: fullscreenEnabled}); } function addFullScreenListener() { app.classList.add('fullscreen-listener-enabled'); webView.addEventListener('pointerenter', hide); if (hideDelay) { webView.addEventListener('pointerleave', clearHideTimeout); } hoverDivTop.addEventListener('pointerenter', showTop); hoverDivTop.addEventListener('pointerleave', clearTimeouts); if (hoverDivLeft) { hoverDivLeft.addEventListener('pointerenter', showLeft); hoverDivLeft.addEventListener('pointerleave', clearTimeouts); } if (hoverDivRight) { hoverDivRight.addEventListener('pointerenter', showRight); hoverDivRight.addEventListener('pointerleave', clearTimeouts); } if (hoverDivBottom) { hoverDivBottom.addEventListener('pointerenter', showBottom); hoverDivBottom.addEventListener('pointerleave', clearTimeouts); } if (updateHoverDivSize) addEventListener('resize', updateHoverDivs); hide(); } function removeFullScreenListener() { app.classList.remove('fullscreen-listener-enabled'); webView.removeEventListener('pointerenter', hide); if (hideDelay) { webView.removeEventListener('pointerleave', clearHideTimeout); } hoverDivTop.removeEventListener('pointerenter', showTop); hoverDivTop.removeEventListener('pointerleave', clearTimeouts); if (hoverDivLeft) { hoverDivLeft.removeEventListener('pointerenter', showLeft); hoverDivLeft.removeEventListener('pointerleave', clearTimeouts); } if (hoverDivRight) { hoverDivRight.removeEventListener('pointerenter', showRight); hoverDivRight.removeEventListener('pointerleave', clearTimeouts); } if (hoverDivBottom) { hoverDivBottom.removeEventListener('pointerenter', showBottom); hoverDivBottom.removeEventListener('pointerleave', clearTimeouts); } if (updateHoverDivSize) removeEventListener('resize', updateHoverDivs); show(); } function clearTimeouts() { if (showTopTimeout) clearTimeout(showTopTimeout); if (showLeftTimeout) clearTimeout(showLeftTimeout); if (showRightTimeout) clearTimeout(showRightTimeout); if (showBottomTimeout) clearTimeout(showBottomTimeout); } function clearHideTimeout() { if (hideTimeout) clearTimeout(hideTimeout); } function hide() { hideTimeout = setTimeout(() => { app.classList.add('hidden-top'); if (hoverDivLeft) app.classList.add('hidden-left'); if (hoverDivRight) app.classList.add('hidden-right'); if (hoverDivBottom) app.classList.add('hidden-bottom'); }, hideDelay); } function show() { showTop(); showLeft(); showRight(); showBottom(); } function showTop() { showTopTimeout = setTimeout(() => app.classList.remove('hidden-top'), showDelay); } function showLeft() { if (hoverDivLeft) { showLeftTimeout = setTimeout(() => app.classList.remove('hidden-left'), showDelay); } } function showRight() { if (hoverDivRight) { showRightTimeout = setTimeout(() => app.classList.remove('hidden-right'), showDelay); } } function showBottom() { if (hoverDivBottom) { showBottomTimeout = setTimeout(() => app.classList.remove('hidden-bottom'), showDelay); } } function isWindowMaximized() { return browser.classList.contains('maximized'); } function setHorizontalHoverDivHeight(hoverDiv) { hoverDiv.style.height = updateHoverDivSize && isWindowMaximized() ? '1px' : '1.5rem'; } function setVerticalHoverDivWidth(hoverDiv) { hoverDiv.style.width = updateHoverDivSize && isWindowMaximized() ? '1px' : '1.5rem' } function updateHoverDivs() { setTimeout(() => { setHorizontalHoverDivHeight(hoverDivTop); if (hoverDivLeft) setVerticalHoverDivWidth(hoverDivLeft); if (hoverDivRight) setVerticalHoverDivWidth(hoverDivRight); if (hoverDivBottom) setHorizontalHoverDivHeight(hoverDivBottom); }, 150); } function createHorizontalHoverDiv(position) { const hoverDiv = document.createElement('div'); setHorizontalHoverDivHeight(hoverDiv); hoverDiv.style.width = '100vw'; hoverDiv.style.position = 'fixed'; hoverDiv.style.left = '0'; hoverDiv.style.zIndex = '10'; hoverDiv.style[position] = '0'; hoverDiv.className = 'hover-div'; hoverDiv.classList.add(position); document.querySelector('#app').appendChild(hoverDiv); return hoverDiv; } function createVerticalHoverDiv(position) { const hoverDiv = document.createElement('div'); hoverDiv.style.height = '100%'; setVerticalHoverDivWidth(hoverDiv); hoverDiv.style.position = 'fixed'; hoverDiv.style.top = '0'; hoverDiv.style.zIndex = '10'; hoverDiv.style[position] = '0'; hoverDiv.className = 'hover-div'; hoverDiv.classList.add(position); document.querySelector('#app').appendChild(hoverDiv); return hoverDiv; } function generalCSS() { return ` #header, .mainbar, .bookmark-bar, #panels-container { transition: transform .5s, opacity .5s ease-in-out !important; } #header, .mainbar { z-index: 8; } .bookmark-bar { z-index: 7; } #header .vivaldi { margin-top: 3px; } #main { padding-top: 0 !important; } #webview-container { position: fixed !important; top: 0; left: 0; right: 0; bottom: 0; } #panels-container { position: fixed !important; } .extensionIconPopupMenu, .button-popup { z-index: 8; } footer { margin-top: auto !important; } .hover-div { transition: visibility 0.5s ease-in-out; } `; } function topCSS() { const topElements = []; let height = 0; if (tabBarPosition === 'top' || !addressBarTop) { topElements.push('#header'); height += header?.offsetHeight || 0; } if (addressBarTop) { topElements.push('.mainbar'); height += mainBar?.offsetHeight || 0; } if (bookmarksTop && bookmarkBar) { topElements.push('.bookmark-bar'); height += bookmarkBar?.offsetHeight || 0; } if (topElements.length === 0) { return ''; } let css = ` &.hidden-top { ${topElements.join(', ')} { transform: translateY(-${height}px); opacity: 0; } } &:not(.hidden-top) .hover-div.top { visibility: hidden; } `; if (showAddressBarOnFocus && addressBarTop) { css += ` &.hidden-top { #browser:has(.internal-page .startpage), #browser:has(.UrlBar-AddressField:focus-within) { .mainbar { opacity: 1; .UrlBar-AddressField { position: absolute; top: ${height}px; left: 25vw; right: 25vw; width: 50vw !important; } } } } `; } if (bookmarksTop && addressBarTop) { css += ` .bookmark-bar-top-off .mainbar { padding-bottom: 5px; background: var(--colorAccentBg); } `; } if (bookmarksTop) { css += ` .bookmark-bar { margin-top: 0; } `; } return css; } function leftCSS() { const leftElements = []; let width = 0, tabbarWrapper; if (tabBarPosition === 'left') { leftElements.push('.tabbar-wrapper'); tabbarWrapper = document.querySelector('.tabbar-wrapper'); width += tabbarWrapper.offsetWidth; } if (hidePanels && panelsLeft) { leftElements.push('#panels-container'); width += panelsContainer.offsetWidth; } if (leftElements.length === 0) { return ''; } let css = ` &.hidden-left { ${leftElements.join(', ')} { transform: translateX(-${width}px); opacity: 0; } } &:not(.hidden-left) .hover-div.left { visibility: hidden; } `; if (tabBarPosition === 'left') { css += ` .tabbar-wrapper { position: fixed; top: 0; left: ${panelsLeft ? panelsContainer.offsetWidth : 0}px; z-index: 1; transition: transform .5s, opacity .5s ease-in-out !important; } `; } if (hidePanels && panelsLeft) { css += ` #webview-container { margin-left: ${verticalMargin}; /*margin-left: calc(-${panelsContainer.offsetWidth}px + ${verticalMargin});*/ } `; } return css; } function rightCSS() { const rightElements = []; let width = 0, tabbarWrapper; if (tabBarPosition === 'right') { rightElements.push('.tabbar-wrapper'); tabbarWrapper = document.querySelector('.tabbar-wrapper'); width += tabbarWrapper.offsetWidth; } if (hidePanels && !panelsLeft) { rightElements.push('#panels-container'); width += panelsContainer.offsetWidth; } if (rightElements.length === 0) { return ''; } let css = ` &.hidden-right { ${rightElements.join(', ')} { transform: translateX(${width}px); opacity: 0; } } &:not(.hidden-right) .hover-div.right { visibility: hidden; } `; if (tabBarPosition === 'right') { css += ` .tabbar-wrapper { position: fixed; top: 0; right: ${!panelsLeft ? panelsContainer.offsetWidth : 0}px; z-index: 1; transition: transform .5s, opacity .5s ease-in-out !important; } `; } if (hidePanels && !panelsLeft) { css += ` #webview-container { margin-right: ${verticalMargin}; /*margin-left: calc(-${panelsContainer.offsetWidth}px + ${verticalMargin});*/ } `; } return css; } function bottomCSS() { const bottomElements = []; let height = 0, tabbarWrapper; if (tabBarPosition === 'bottom') { bottomElements.push('#footer') tabbarWrapper = document.querySelector('#footer'); height += tabbarWrapper?.offsetHeight || 0; } if (!addressBarTop) { bottomElements.push('.mainbar'); height += mainBar?.offsetHeight || 0; } if (!bookmarksTop && bookmarkBar) { bottomElements.push('.bookmark-bar'); height += bookmarkBar?.offsetHeight || 0; } if (bottomElements.length === 0) { return ''; } let css = ` &.hidden-bottom { ${bottomElements.join(', ')} { transform: translateY(${height}px); opacity: 0; } } &:not(.hidden-bottom) .hover-div.bottom { visibility: hidden; } `; if (showAddressBarOnFocus && !addressBarTop) { css += ` &.hidden-bottom { #browser:has(.internal-page .startpage), #browser:has(.UrlBar-AddressField:focus-within) { .mainbar { opacity: 1; .UrlBar-AddressField { position: absolute; bottom: ${mainBar.offsetHeight + 10}px; left: 25vw; right: 25vw; width: 50vw !important; } } } } `; } if (tabBarPosition === 'bottom') { css += ` #footer { transition: transform .5s, opacity .5s ease-in-out !important; } `; } if (!bookmarksTop && !addressBarTop) { css += ` .bookmark-bar-bottom-off .mainbar { padding-bottom: -5px; background: var(--colorAccentBg); } `; } if (!bookmarksTop) { css += ` .bookmark-bar { margin-bottom: 0; } `; } return css; } })();
-
That's how the pros do it!
Thanks for tidying up my messy attempts. CSS has a way of making me long for C++, I swear.
You are a hero of the OLED community my friend!
To answer your questions:
- I agree that F11 is more familiar, and I had removed it from Vivaldi's settings. However, apparently a recent version (maybe 7.2?) silently brought it back, and that caused me some head scratching. After I realised what happened, I thought that I'm not going to win this fight, so I went for the shortcut that seemed the least likely to conflict with existing stuff. If no one else had this problem, then sticking with F11 makes sense.
- "...why you want to have a different delay when the window is maximized?" I thought that if I'm deliberately moving my mouse to the top of the screen, I want to see the tabs, so why wait at all? Such mouse movement never happens accidentally, at least to me. Also, it doesn't seem like the auto-hidden Windows taskbar has a show delay either, so imitating it makes sense. It's ok though, since the default delay (125ms) seems to work well enough in all cases.
As for AddressField:focus-within, I'm still affected by that issue that our friend also reported here: https://forum.vivaldi.net/post/805076 ("adress bar shows up in every tab"). Your previous version from 23 Jan 2025 (page 6 here) didn't initially have this issue, so I assume something changed in a later version of Vivaldi. Either way, I wanted this behaviour (a visible address field if it's focused) on every page, not just the start page, so I stumbled upon that solution (:focus-within), which allowed me to remove the requirement of checking for the active page being the start page. Here's my motivation: Say I'm done with some tab I was reading, and I want to reuse it to open another page. I go up to the tab bar to click the tab, and then I go down to the address field to click it. At this point, my mouse is already very close to the edge. As I take my hand off the mouse, to start typing, the mouse can drift below the address field, and now the whole thing auto-hides, and I can't see what I'm typing. First world problems
. Anyway, this can still be a matter of preference, so of course I'm happy to make the below quick change on top of your shiny new version.
Thanks again!
-
@kostasvl thank you very much for your nice words!
Of course you can take what ever shortcut you want to use, since you're able to change it.Regarding the problem with the address bar:
In the line that you've removed:
#browser:has(.internal-page .startpage), #browser:has(.UrlBar-AddressField:focus-within)
the CSS code checks, if thebrowser
has anUrlBar-AddressField
which is focused. So it should work, but without changingmainbar
sopacity
all the time, but just, when we are on a start page or when the address bar is in focus. I liked the idea and added the change. It didn't work for you like this?