AutoHide Tab Bar + Address Bar | Show on Hover
-
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? -
thanks for this modification, it's exactly what I've wanted
and sorry to bug you, but I'd like to report that "7.2.3621.71 (Stable channel) (64-bit)" borked the code, the tab and address bar aren't hiding anymore...
-
@masklessdiety nice to hear!
I'm always on the latest Snapshot (
7.2.3641.3
) and there it works fine. Are you sure that you setup the mod correctly? Or did you tried to hit the keyboard shortcut to enable it? -
wow, thanks for the lightning fast reply
I'm sorry, seems like I messed up the directories, even though I managed to apply it after previous updates.
All's fine now, thanks a bunch!!!!
-
@oudstand For me, the address bar is shown at all times, with your unmodified version. For example:
I can repro this with your version from January as well, although that wasn't the case initially, back in February. Something changed in Vivaldi since. It's strange that it doesn't repro for you. There is at least one more report in this thread: https://forum.vivaldi.net/post/805076.
Worth noting that I have no other mods at all. Just your ace one
It's not a problem though. My tweak accomplishes the same thing (see screenshot in my previous reply).
Thanks
-
@masklessdiety I'm preparing a forum post where I'll offer a script that automates the update process entirely. It starts when you boot into Windows (via the Task Scheduler), and then monitors the Vivaldi directory for those versioned subdirectories. When it detects a new/higher version, it prompts you to close Vivaldi, and then it copies your mods from a directory of your choice (together with your modified window.html) into the Vivaldi directory. Then it asks you to restart Vivaldi, and goes back to monitoring for new changes.
This literally happened 20 mins ago
I just need time to prepare the post, with instructions, screenshots, etc
.
Hmm, would you (or anyone else here) like to beta test it for me? I have two alternatives:
- An exe:
This exe will not show a window at all, which is important.
The thing is, I'll offer the exe (via Google Drive, probably), but, no one should be downloading executable files from strangers... I can offer the source code too, if you have the means to compile it. Visual Studio Community Edition, or VSCode, are both free. That might be too much to ask of people, so I also prepared...
- A version of the same thing, written in powershell.
Less dangerous in theory, because people can see what it's doing. The problem is that it will show an annoying window when you run it. Solving that is a bit annoying, though doable.
Anyway, I'll stop here for now. If there is interest, I'll write back. At the weekend, I might track down that big forum post where people discuss their own scripts for this, and I'll post my stuff there.
Really though, I wish Vivaldi will implement a solution
-
I'm okay with trying both versions, though not sure how much I can help, I only know how to copy and paste things into directories, zero programming knowledge
-
For me, the address bar is shown at all times, with your unmodified version.
@kostasvl I didn't tested the old code again. Does it still happen with the latest code that I've provided? I also implemented the
.UrlBar-AddressField:focus-within)
fix there. -
@kostasvl I prefer to patch Vivaldi with a batch script when needed
Since I use Vivaldi on different devices my script even pulls my latest mod changes from git.
-
@oudstand Yes, that IMDB screenshot was taken with your latest version.
-
@kostasvl I can't reproduce it with the latest code. Do you have any other mods enabled which could cause the problem? Just to be clear, this ist my latest version:
/** * 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; } })();
-
@oudstand No other mods.
-
@kostasvl hm... that makes it difficult to fix for me when I can't reproduce the problem...
-
@oudstand No worries, thanks!
-
I am using your mod. It works wonderfully, but the panels don't show anymore (I changed hide panels to false in the JS script) . I just get a little grey bar with an arrow. But panels are invisible. If I toggle them, the little arrow goes from the left to the right and that's it.
I use vertical tabs.
The little grey bar with black arrow in the top right is all that shows for panels.
Am I doing something wrong? I am using the last version of the code on this topic.
-
@Firipu I've tested it with the latest code and it does work. Do you have any other JS or CSS mods that could affect this mod? Did you try to restart your browser?
-
Ok, so just for reference, if anyone else would have the same issue:
Turning on floating panels in your settings solves the issue. The panel bar stays nice and visible now.
edit: restart fixed the transparent tab bar.
script works flawless now. Thx! Leaving this up for future reference if anyone else would have the issue.
-
@Firipu good to know. I've always used floating panels. On my device the color of the side bar didn't disappear, but as long as you're happy with it
-
@oudstand This code runs perfectly on my PC. Will it work on Mac OS X (M-chip) too?