Zoom Controls in Address Bar with Slide Out Animation
-
Every once and awhile, I wonder about the zoom level I have set for a website. It would be helpful to have a quick way to check, but having the status bar forever displayed across the bottom of the screen seems like a bad solution for a rarely encountered issue. So, I made a small indicator to live in the address bar, complete with a slide out panel to house the controls.
Because Vivaldi is a highly customizable browser and I accidentally made some interesting alternative versions of the zoom controls as I was trying to make the version I wanted, I decided to make some easy configurations settings available for this modification.
Configurations
All configuration settings can be found at the top of the Javascript file- Reset Zoom Level:
- The zoom percentage that is used when clicking the Reset Button
- If you want to use Vivaldi's default page zoom level setting, leave this value at 100
- The zoom percentage that is used when clicking the Reset Button
- Zoom Increment Amount:
- How big a step the zoom in and out buttons have.
- How big a step the zoom in and out buttons have.
- Mode 0:
const MODE = 0;
Only clicking the button opens and closes the zoom panel
- Mode 1:
const MODE = 1;
Clicking the button opens the panel and the panel auto closes if not hovered over
- Mode 2:
const MODE = 2;
Just hovering over the button will open the panel and the panel auto closes if not hovered over. You can also make the address bar the hover trigger instead of the button- Without Address Bar Hover Trigger Option:
const IS_AUTO_OPENED_ON_ADDRESSBAR = false;
- With Address Bar Hover Trigger Option:
const IS_AUTO_OPENED_ON_ADDRESSBAR = true;
- Without Address Bar Hover Trigger Option:
- Fade Out Time:
The amount of seconds the cursor can be away from the panel before it auto hides. The cursor can leave hovering and come back and the timer should reset. Only used in modes 1 and 2- Set to 0 seconds:
- Set to 3 seconds:
- Set to 0 seconds:
***Disclaimer:
This was only tested on a 1080p laptop screen, so I am not sure how nicely the absolute sizes and positions of some elements play with different resolution screens. Let me know if there are issues and include some pictures.
I am relatively new to Javascript and CSS, so if you see any improvements I should make, let me know. Thanks.Javascript
Buckle up, this one is gonna be a doozy...(function () { // ============================================================================================================ // Gives Zoom Interface in the Address Bar // - made by nomadic on the Vivaldi Forums // ============================================================================================================ function zoomControl() { // CONFIGURATION: --------------------------------------------------------------- // - in Vivaldi's settings you can set the default page zoom, this // will follow that if RESET_ZOOM_LEVEL is set to 100 const RESET_ZOOM_LEVEL = 100; // 100 % -> the zoom that hitting the reset button will default to const ZOOM_INCREMENT_AMOUNT = 10; // 10 % -> the amount the zoom is either raised or lowered // MODES---------------- // Mode 0: only clicking button opens and closes the panel // Mode 1: clicking the button opens the panel and the panel auto closes if not hovered over // Option for mode 1: // FADE_OUT_TIME -> the number of seconds the panel goes without hover before closing // Mode 2: just hovering over the button will open the panel and the panel auto closes if not hovered over // Options for mode 2: // FADE_OUT_TIME -> the number of seconds the panel goes without hover before closing // IS_AUTO_OPENED_ON_ADDRESSBAR -> instead of only the button being hovered, the whole address bar is used const MODE = 1; // --------------------- // Option for modes 1 and 2: const FADE_OUT_TIME = 3; // 3 seconds -> can be set to any positive half second increment (ex. 0, 0.5, 1, 1.5 ...) // Option for mode 2: const IS_AUTO_OPENED_ON_ADDRESSBAR = false; // ------------------------------------------------------------------------------ // Creates the zoom button and panel initially, and then updates the icon depending on the zoom level function updateZoomIcon(zoomInfo) { let newZoom = zoomInfo.newZoomFactor; let zoomIconPath; let zoomIconState; const isMailBar = document.querySelector(".toolbar-mailbar"); if (isMailBar) return; // create the button if it isn't already there let alreadyExists = document.getElementById("zoom-hover-target"); if (!alreadyExists) { // CHANGE: Added in Update #4 // a guaranteed div to the left of the button let elementToTheLeft = document.createElement("div"); elementToTheLeft.style.transition = "0.5s"; elementToTheLeft.id = "el2left"; let zoomBtn = document.createElement("div"); zoomBtn.id = "zoom-hover-target"; zoomBtn.innerHTML = ` <div class="zoom-parent"> <div class="zoom-panel"> <div class="page-zoom-controls-c"> <div class="button-toolbar button-toolbar-c reset-zoom-c" title="Reset Zoom"> <button tabindex="-1" class="button-textonly-c" id="zoom-reset-c"> <span class="button-title-c">Reset</span> </button> </div> <div class="button-toolbar button-toolbar-c"> <button tabindex="-1" title="Zoom Out" type="button" class="ToolbarButton-Button" id="zoom-out-c"> <span class="button-icon"> <svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> <path d="M4 8C4 8.55228 4.44772 9 5 9H11C11.5523 9 12 8.55228 12 8C12 7.44772 11.5523 7 11 7H5C4.44772 7 4 7.44772 4 8Z"></path> </svg> </span> </button> </div> <span id="zoom-percent-c"></span> <div class="button-toolbar button-toolbar-c"> <button tabindex="-1" title="Zoom In" type="button" class="ToolbarButton-Button" id="zoom-in-c"> <span class="button-icon"> <svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> <path d="M7 7V5C7 4.44772 7.44772 4 8 4C8.55228 4 9 4.44772 9 5V7H11C11.5523 7 12 7.44772 12 8C12 8.55228 11.5523 9 11 9H9V11C9 11.5523 8.55228 12 8 12C7.44772 12 7 11.5523 7 11V9H5C4.44772 9 4 8.55228 4 8C4 7.44772 4.44772 7 5 7H7Z"></path> </svg> </span> </button> </div> </div> </div> </div> <div class="button-toolbar ZoomButton-Button"> <button tabindex="-1" title="Adjust Zoom" id="zoom-panel-btn" type="button" class="ToolbarButton-Button"> <span> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewbox="0 0 16 16" id="zoomIcon-c"> </svg> </span> </button> </div> `; // inserts the button to the left of the bookmark icon const addressBarEnd = document.querySelector(".UrlBar-AddressField .toolbar-insideinput:last-of-type"); const bookmarkBtn = addressBarEnd.getElementsByClassName("BookmarkButton")[0]; console.log(bookmarkBtn); if (!bookmarkBtn) { addressBarEnd.appendChild(zoomBtn); } else { addressBarEnd.insertBefore(zoomBtn, bookmarkBtn); } // CHANGE:Added in Update #4 // divs next to the button aren't static,so created my own div to push addressBarEnd.insertBefore(elementToTheLeft, zoomBtn); // listener for the magnifying glass button to expand or collapse the control panel document.getElementById("zoom-panel-btn").addEventListener("click", function () { let nav = document.getElementsByClassName("zoom-panel")[0]; navToggle(nav, elementToTheLeft); }); // listener for the zoom in button in the zoom control panel document.getElementById("zoom-in-c").addEventListener("click", incrementPercent); // listener for the zoom out button in the zoom control panel document.getElementById("zoom-out-c").addEventListener("click", decrementPercent); // listener for the zoom reset button in the zoom control panel document.getElementById("zoom-reset-c").addEventListener("click", resetZoom); // starts esentially a hover listener that modes 1 and 2 need if (MODE === 1 || MODE === 2) { zoomPanelHoverTracker(); } } // set the icon based on the new zoom level if (newZoom < RESET_ZOOM_LEVEL / 100) { // zoomed in zoomIconState = "zoomed-in"; zoomIconPath = ` <path d="M5.83 9.65a.5.5 0 00-.29.13L1.32 14c-.46.47.23 1.17.7.7l4.22-4.22a.5.5 0 00-.42-.83zm3.6-8.5a5.41 5.41 0 00-5.4 5.4 5.4 5.4 0 105.4-5.4zm0 .99a4.4 4.4 0 11-4.41 4.41 4.4 4.4 0 014.42-4.42zM7.16 6.06c-.66 0-.66.98 0 .98h4.57c.65 0 .65-.98 0-.98z"/> `; } else if (newZoom > RESET_ZOOM_LEVEL / 100) { // zoomed out zoomIconState = "zoomed-out"; zoomIconPath = ` <path d="M5.83 9.65a.5.5 0 00-.3.13L1.31 14c-.46.47.23 1.17.7.7l4.22-4.22a.5.5 0 00-.4-.84zm3.6-8.5a5.41 5.41 0 00-5.4 5.4 5.4 5.4 0 0010.81 0 5.4 5.4 0 00-5.4-5.4zm0 .98a4.4 4.4 0 014.42 4.41 4.41 4.41 0 11-4.41-4.4zm-.06 1.63a.5.5 0 00-.43.5v1.79h-1.8c-.65 0-.65.98 0 .98h1.8v1.81c0 .66.99.66.99 0v-1.8h1.79c.65 0 .65-.99 0-1h-1.8V4.27a.5.5 0 00-.55-.5z"/> `; } else { // default zoom icon zoomIconState = "default-zoom"; zoomIconPath = ` <path d="M5.87 9.71c-.11.01-.2.06-.29.14l-4.37 4.37c-.46.45.23 1.14.7.68l4.36-4.37a.48.48 0 00-.41-.82zm3.55-8.36A5.33 5.33 0 004.1 6.67a5.32 5.32 0 105.32-5.32zm0 .97a4.33 4.33 0 11-4.34 4.34 4.33 4.33 0 014.34-4.35z"/> `; } // insert the new icon let zoomSVG = document.getElementById("zoomIcon-c"); zoomSVG.setAttribute("data-zoomState", zoomIconState); zoomSVG.innerHTML = zoomIconPath; // make the percent in the controls match the current zoom level updatePercent(newZoom); } // Makes the zoom controls slide out function openNav(nav, elToLeft) { nav.classList.add("expanded-nav-c"); nav.parentElement.parentElement.classList.add("zoom-hover-target--active"); elToLeft.classList.add("expanded-left-c"); } // Hides the zoom controls function closeNav(nav, elToLeft) { nav.classList.remove("expanded-nav-c"); nav.parentElement.parentElement.classList.remove("zoom-hover-target--active"); elToLeft.classList.remove("expanded-left-c"); } // Toggles the zoom controls open or closed depending on the current state function navToggle(nav, elToLeft) { if (nav.offsetWidth === 0) { return openNav(nav, elToLeft); } else { return closeNav(nav, elToLeft); } } // Puts the zoom level percentage in the zoom controls panel function updatePercent(zoomLevel) { let zoomPercent = Math.round(zoomLevel * 100); let percentageSpan = document.getElementById("zoom-percent-c"); percentageSpan.innerHTML = zoomPercent + " %"; } // Zooms in the page by the specified increment function incrementPercent() { chrome.tabs.getZoom(function (zoomLevel) { let newZoomLevel = zoomLevel + ZOOM_INCREMENT_AMOUNT / 100; // Max zoom that Vivaldi allows is 500 % if (newZoomLevel <= 5) { chrome.tabs.setZoom(newZoomLevel, updatePercent(newZoomLevel)); } }); } // Zooms out the page by the specified increment function decrementPercent() { chrome.tabs.getZoom(function (zoomLevel) { let newZoomLevel = zoomLevel - ZOOM_INCREMENT_AMOUNT / 100; // Min zoom that Vivaldi allows is 20 % if (newZoomLevel >= 0.2) { chrome.tabs.setZoom(newZoomLevel, updatePercent(newZoomLevel)); } }); } // Sets the zoom back to the default zoom level // - in Vivaldi's settings you can set the default page zoom, this // will follow that if RESET_ZOOM_LEVEL is set to "100" function resetZoom() { let zoomLevel = RESET_ZOOM_LEVEL / 100; chrome.tabs.setZoom(zoomLevel, updatePercent(zoomLevel)); } // For modes 1 and 2: // Tracks if you are hovering over the zoom controls function zoomPanelHoverTracker() { let zoomPanel = document.getElementsByClassName("zoom-panel")[0]; let elementToTheLeft = zoomPanel.parentElement.parentElement.previousElementSibling; let isHovered = false; let intervalID = null; let count = 0; // selects which element must be hovered to trigger action let hoverElement; if (MODE === 2 && IS_AUTO_OPENED_ON_ADDRESSBAR) { let addressBar = document.querySelector(".UrlBar-AddressField"); hoverElement = addressBar; } else { let zoomBtnAndPanel = document.getElementById("zoom-hover-target"); hoverElement = zoomBtnAndPanel; } // when the element is hovered, reset the interval counter and opens the controls if needed hoverElement.onmouseover = function () { count = 0; isHovered = true; if (MODE !== 1) { openNav(zoomPanel, elementToTheLeft); } }; // when the element loses hover, closes the controls if enough time has passed hoverElement.onmouseout = function () { // removes any previous counters (needed for if hover is lost and regained multiple times) if (intervalID) { clearInterval(intervalID); } isHovered = false; // start a counter to see how long it has been since the element was last hovered intervalID = setInterval(function () { // only increment the counter as long as hover isn't regained if (isHovered === false) { count++; } // once the correct amount of time has ellapsed, close the controls panel if (count >= FADE_OUT_TIME * 2) { closeNav(zoomPanel, elementToTheLeft); clearInterval(intervalID); } }, 500); }; } // CHANGE: Added in Update #1 // updates zoom percentage on tab change function tabChangeUpdateZoomWrapper() { chrome.tabs.getZoom(function (zoomLevel) { let zoomInfo = { newZoomFactor: zoomLevel, }; updateZoomIcon(zoomInfo); }); } // zoom change listener chrome.tabs.onZoomChange.addListener(updateZoomIcon); // CHANGE: Added in Update #1 // Listener for active tab change chrome.tabs.onActivated.addListener(tabChangeUpdateZoomWrapper); // CHANGE: Added in Update #4 // Initially load icon, stopped getting added on startup in 3.5 chrome.tabs.getZoom(function (zoomLevel) { let zoomInfo = { newZoomFactor: zoomLevel, }; updateZoomIcon(zoomInfo); }); // mutation Observer for Address Bar Changes let main = document.getElementsByClassName("mainbar")[0]; // get the initial state of the addressbar as either urlbar or mailbar let oldIsMailBarActive = main.firstChild.classList.contains("toolbar-mailbar"); let addressBarObserver = new MutationObserver(function (mutations) { mutations.forEach(function (mutation) { // only re-add on new nodes added. The list addedNodes will only have a // length attribute when it contains added nodes if (mutation.addedNodes.length) { // get the new state of the addressbar let isMailBarActive = mutation.addedNodes[0].classList.contains("toolbar-mailbar"); // if it is different from the previous state, we need to act on it if (oldIsMailBarActive !== isMailBarActive) { // update the old value for comparisons on future mutations oldIsMailBarActive = isMailBarActive; // if the addressbar isn't the mailbar, we can re-add the button if (!isMailBarActive) { // Run all changes that are only in the url bar and not the mail bar tabChangeUpdateZoomWrapper(); } } } }); }); addressBarObserver.observe(main, { childList: true }); } // Loop waiting for the browser to load the UI let intervalID = setInterval(function () { const browser = document.getElementById("browser"); if (browser) { clearInterval(intervalID); zoomControl(); } }, 300); })();
CSS
/* ================================================== * Zoom indicator * ================================================== */ #zoom-hover-target { transition: 0.5s; } #zoom-hover-target { height: 22px; --BorderRadius: 4px; font-size: 11.5px; display: flex; } .ZoomButton-Button { height: 100%; border-radius: var(--BorderRadius); border: 1px solid transparent; } .ZoomButton-Button:hover, .zoom-hover-target--active { background-color: var(--colorBgDark); } .ZoomButton-Button:hover { border-color: var(--colorBorder); } .ZoomButton-Button .ToolbarButton-Button { border: none; width: auto; height: 100%; margin: 0; padding: 0 6px; margin: auto -3px; } /* ================================================== * Zoom slide out controls * ================================================== */ .zoom-parent { position: relative; } .zoom-panel { background: linear-gradient(90deg, var(--colorBgDark) 0%, var(--colorBgDark) 96%, rgba(0, 0, 0, 0) 100%); border-radius: var(--radiusHalf); height: 100%; overflow-x: hidden; overflow-y: hidden; position: absolute; right: 0; transition: 0.5s; /* hide */ width: 0; opacity: 0; } .page-zoom-controls-c { height: 100%; } .button-toolbar-c > button { border-radius: var(--radiusHalf); border: unset !important; display: inline-block; height: 100%; } .button-toolbar-c { display: inline-block; height: 100%; } .button-toolbar-c > button:hover { background-color: var(--colorFgAlpha); } #zoom-percent-c { text-align: center; vertical-align: middle; width: 40px; display: inline-block; } .expanded-nav-c { width: 150px !important; opacity: 1; } .expanded-left-c { margin-right: 150px !important; }
Things You May Need To Fix
- Depending on your theme, you may need to adjust some colors if you want the panel to have a visible background.
- The "bottom" value of "zoom-panel" also may need to be tweaked to center the panel in the address bar. (-11.5px worked for me but when I loaded it in a fresh Vivaldi install it was slightly off)
Random Notes
- "Your browser looks like Opera?"
- Yes, that is my overall goal. I am slowly making Vivaldi look similar to the modern Opera Browser. It just looks sort of nice to me. I know I could just use Opera, but there are a few things I would like to change, and Vivaldi lets me do that, so I am team Vivaldi all the way!
- Eventually, I will get around to posting some more about the transformation, but it is still in progress as I keep edging closer to 1000 lines of CSS and a few Javascript Mods as well...
- "Where did you get the SVG icons?"
- They were made in Inkscape. Then to simplify them into more manageable objects, I ran them through SVGO using this link: SVGOMG - SVGO's Missing GUI
This gets rid of all the junk Inkscape packs on, and also simplifies the paths. You just have to make sure you don't get unwanted distortion by lowering the precision too much.
- They were made in Inkscape. Then to simplify them into more manageable objects, I ran them through SVGO using this link: SVGOMG - SVGO's Missing GUI
- "How did you figure out how to make this mod?"
- Lots of trial and error and Googling... I do have coding experience, but other than a simple landing page website and an all night fever coding session to get something made for a school project, I haven't ever really touched Javascript. If you want to see some of my basic prototypes for some of the key aspects of this mod, you can check out these JSFiddle projects I made (a good way to quickly prototype): Slide Out Menu and Fading Element After Time Interval
Updates
-
Update #1: Edited on March 12, 2020 - Zoom percent was not updating on tab change, so fixed with an additional listener and function wrapper. This change is also propagated to alternate versions of this mod in comments below.
-
Update #2: Edited on October 11, 2020 - Classes on elements were changed with a new Vivaldi release, so code needed updating to the new names. Thanks to @sjudenim for saving me the work of finding the new selector.
-
Update #3: Edited on November 20, 2020 - Needed to add another
.parentElement
to find the element to the left of the slide out panel.Known Bug: pageload ticker and reader view are being added inbetween the zoom button and bookmark button. Causes annoying jumps in movement while page is loading. -
Update #4: Edited on December 10, 2020 - Made compatible with version 3.5, fixed known bug from last version, and made some small changes in usage of classes vs ids (affects JS and CSS).
-
Update #5: Edited on June 1, 2021 - Made compatible with version 3.8, classnames and structure updated. Also updated colors to follow theme settings. Thanks to @NNickolov for discovering it was broken. (affects JS and CSS).
-
Update #6: Edited on June 9, 2022 - Made compatible with version 5.3. Thanks to @stardepp for discovering it was broken. (affects JS only).
-
Update #7: Edited on September 1, 2023 - Partial fix for version 6.2. + and - icons work, but clicking them causes the slide out menu to collapse. Will require more work to fix. Thanks to @rafiki for discovering it was broken. (affects JS only).
-
Update #8: Edited on September 16, 2023 - Stopped the slide out menu from collapsing on zoom button clicks. Not positioned correctly relative to the bookmark icon, but will have to investigate later (affects JS only).
- Reset Zoom Level:
-
like this a lot but i prefer simple so is it possible to have it permanently expanded
-
@adacom yeah, that is another good option. I will work on it later today.
Would you be alright with it still being in the address bar?
-
address bar is fine or tab bar - either really - i have it at end of tabbar now with another mod but its not consistent - it always loads and shows and then disappears for no reason - am hoping yours would be more reliable
-
@adacom It was different enough for me to not want to add a bunch of if-else statements, so it is it's own separate mod now.
Preview
* Ignore the magnifying glass in the address bar, that is just the previous mod in the thread. I can put an indicator there if you want it. Just let me know.
Because this isn't stealing buttons from another part of the interface, it should hopefully not have the same problems as the last mod you used.Javascript
(function () { // ============================================================================================================ // Gives Zoom Interface in the Extensions Toolbar // - made by nomadic on the Vivaldi Forums // ============================================================================================================ function zoomControlStatic() { // CONFIGURATION: --------------------------------------------------------------- // - in Vivaldi's settings you can set the default page zoom, this // will follow that if RESET_ZOOM_LEVEL is set to 100 const RESET_ZOOM_LEVEL = 100; // 100 % -> the zoom that hitting the reset button will default to const ZOOM_INCREMENT_AMOUNT = 10; // 10 % -> the amount the zoom is either raised or lowered // ------------------------------------------------------------------------------ // Creates the zoom controls initially, and then updates the percent depending on the zoom level function updatePercent(zoomInfo) { let newZoom = zoomInfo.newZoomFactor; // create the controls if they aren't already there let alreadyExists = document.querySelector(".page-zoom-controls-s"); if (!alreadyExists) { let zoomControls = document.createElement("div"); zoomControls.setAttribute("class", "button-toolbar"); zoomControls.innerHTML = ` <div class="page-zoom-controls-s"> <div class="button-toolbar-s" title="Zoom Out"> <button tabindex="-1" id="zoom-out-s"> <svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> <path d="M4 8C4 8.55228 4.44772 9 5 9H11C11.5523 9 12 8.55228 12 8C12 7.44772 11.5523 7 11 7H5C4.44772 7 4 7.44772 4 8Z"></path> </svg> </button> </div> <div class="button-toolbar-s reset-zoom-s" title="Reset Zoom"> <button tabindex="-1" class="button-textonly-s" id="zoom-reset-s"> <span class="button-title" id="zoom-percent-s"></span> </button> </div> <div class="button-toolbar-s" title="Zoom In"> <button tabindex="-1" id="zoom-in-s"> <svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> <path d="M7 7V5C7 4.44772 7.44772 4 8 4C8.55228 4 9 4.44772 9 5V7H11C11.5523 7 12 7.44772 12 8C12 8.55228 11.5523 9 11 9H9V11C9 11.5523 8.55228 12 8 12C7.44772 12 7 11.5523 7 11V9H5C4.44772 9 4 8.55228 4 8C4 7.44772 4.44772 7 5 7H7Z"></path> </svg> </button> </div> </div> `; // inserts the controls to the beginning of the extensions area let extensionsArea = document.querySelector(".toolbar-extensions"); extensionsArea.prepend(zoomControls); // listener for the zoom in button in the zoom control panel document.getElementById("zoom-in-s").addEventListener("click", incrementPercent); // listener for the zoom out button in the zoom control panel document.getElementById("zoom-out-s").addEventListener("click", decrementPercent); // listener for the zoom reset button in the zoom control panel document.getElementById("zoom-reset-s").addEventListener("click", resetZoom); } // Puts the zoom level percentage in the zoom controls let zoomPercent = Math.round(newZoom * 100); let percentageSpan = document.getElementById("zoom-percent-s"); percentageSpan.innerHTML = zoomPercent + " %"; } // Zooms in the page by the specified increment function incrementPercent() { chrome.tabs.getZoom(function (zoomLevel) { let newZoomLevel = zoomLevel + ZOOM_INCREMENT_AMOUNT / 100; // Max zoom that Vivaldi allows is 500 % if (newZoomLevel <= 5) { chrome.tabs.setZoom(newZoomLevel, updatePercent(newZoomLevel)); } }); } // Zooms out the page by the specified increment function decrementPercent() { chrome.tabs.getZoom(function (zoomLevel) { let newZoomLevel = zoomLevel - ZOOM_INCREMENT_AMOUNT / 100; // Min zoom that Vivaldi allows is 20 % if (newZoomLevel >= 0.2) { chrome.tabs.setZoom(newZoomLevel, updatePercent(newZoomLevel)); } }); } // Sets the zoom back to the default zoom level // - in Vivaldi's settings you can set the default page zoom, this // will follow that if RESET_ZOOM_LEVEL is set to "100" function resetZoom() { let zoomLevel = RESET_ZOOM_LEVEL / 100; chrome.tabs.setZoom(zoomLevel, updatePercent(zoomLevel)); } // CHANGE: Added in Update #1 (see original post for details) // updates zoom percentage on tab change function tabChangeUpdateZoomWrapper() { chrome.tabs.getZoom(function (zoomLevel) { let zoomInfo = { newZoomFactor: zoomLevel, }; updatePercent(zoomInfo); }); } // zoom change listener chrome.tabs.onZoomChange.addListener(updatePercent); // CHANGE: Added in Update #1 (see original post for details) // Listener for active tab change chrome.tabs.onActivated.addListener(tabChangeUpdateZoomWrapper); // CHANGE: Added in Alternative Version Update #1 // Re-add the zoom controls after exiting fullscreen let browser = document.getElementById("browser"); let oldState = browser.classList.contains("fullscreen") || browser.classList.contains("minimal-ui"); let browserObserver = new MutationObserver(function (mutations) { mutations.forEach(function (mutation) { if (mutation.attributeName == "class") { let isFullscreen = mutation.target.classList.contains("fullscreen") || mutation.target.classList.contains("minimal-ui"); if (oldState !== isFullscreen) { oldState = isFullscreen; if (!isFullscreen) { tabChangeUpdateZoomWrapper(); } } } }); }); browserObserver.observe(browser, { attributes: true }); } // Loop waiting for the browser to load the UI let intervalID = setInterval(function () { const browser = document.getElementById("browser"); if (browser) { clearInterval(intervalID); zoomControlStatic(); } }, 300); })();
CSS
.page-zoom-controls-s { display: inline-block; height: 34px; } .button-toolbar-s > button { background-color: transparent; height: 100%; border-radius: var(--radiusHalf); border: unset !important; padding-top: unset !important; padding-bottom: unset !important; color: inherit; align-items: center; justify-content: center; } /* SVG's were slightly too high, couldn't figure out a better solution */ .button-toolbar-s > button svg { padding-top: 5px; /* Edited to avoid confusion in the future */ height: 16px; width: 16px; } .button-toolbar-s > button:hover { background-color: var(--colorAccentBgDark); } .button-toolbar-s { display: inline-block; height: 100%; } .button-textonly-s { width: 100% !important; padding-right: 0 !important; padding-left: 0 !important; } #zoom-percent-s { display: inline-block; width: 40px; }
- Update #1: Edited on December 21, 2020 - Made it so zoom controls are re-added on exiting fullscreen.
-
thanks - that looks excellent - is it a big job to move it to the right of the tab bar - not sure where i would have it but nice to have choice
-
just installed this and the reset button is not showing - also the +/- buttons do not show - they are there and work but they do not show
-
i thought that and you may well be correct but its a clean install and i tried a few different themes from light to dark
-
Thanks for sharing.
I haven't tested it yet but judging from those images, the elements within the container could use some alignment
-
@adacom Sorry, I am still new to sharing mods. Should have tested it on a clean install first...
Button Icons Not Showing Up
The easiest way to get the +/- buttons to show up is to change the css to this:.page-zoom-controls-s { display: inline-block; height: 34px; } .button-toolbar-s > button { background-color: transparent; height: 100%; border-radius: var(--radiusHalf); border: unset !important; padding-top: unset !important; padding-bottom: unset !important; color: inherit; align-items: center; justify-content: center; } /* SVG's were slightly too high, couldn't figure out a better solution */ .button-toolbar-s > button svg { /* Changes Here */ padding-top: 2px; height: 16px; width: 16px; } .button-toolbar-s > button:hover { background-color: var(--colorAccentBgDark); } .button-toolbar-s { display: inline-block; height: 100%; } .button-textonly-s { width: 100% !important; padding-right: 0 !important; padding-left: 0 !important; } .zoom-percent-s { display: inline-block; width: 40px; }
The only real change is to give the SVGs a height and a width. (I also adjusted the padding for alignment.)
Reset Button
The reset button was removed and put into clicking the percentage instead. This is to help the other post about copying Firefox's zoom controls.If you really want a reset button instead of clicking the percentage area, I can change that for you too.
Adding to the Right of the Tab Bar
In the JavaScript you can change where the controls are located fairly easily. There was an additional issue created by this when clicking rapidly because double clicking in the tab bar makes the window maximize/go to windowed mode.I think I fixed it, but who knows...
(function() { // ============================================================================================================ // Gives Zoom Interface in the Tab Bar // - made by nomadic on the Vivaldi Forums // ============================================================================================================ function zoomControlStatic() { // CONFIGURATION: --------------------------------------------------------------- // - in Vivaldi's settings you can set the default page zoom, this // will follow that if RESET_ZOOM_LEVEL is set to 100 const RESET_ZOOM_LEVEL = 100; // 100 % -> the zoom that hitting the reset button will default to const ZOOM_INCREMENT_AMOUNT = 10; // 10 % -> the amount the zoom is either raised or lowered // ------------------------------------------------------------------------------ // Creates the zoom controls initially, and then updates the percent depending on the zoom level function updatePercent(zoomInfo) { let newZoom = zoomInfo.newZoomFactor; // create the controls if they aren't already there let alreadyExists = document.querySelector(".page-zoom-controls-s"); if (!alreadyExists) { let zoomControls = document.createElement("div"); zoomControls.setAttribute("class", "button-toolbar"); zoomControls.innerHTML = ` <div class="page-zoom-controls-s"> <div class="button-toolbar-s" title="Zoom Out"> <button tabindex="-1" id="zoom-out-s"> <svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> <path d="M4 8C4 8.55228 4.44772 9 5 9H11C11.5523 9 12 8.55228 12 8C12 7.44772 11.5523 7 11 7H5C4.44772 7 4 7.44772 4 8Z"></path> </svg> </button> </div> <div class="button-toolbar-s reset-zoom-s" title="Reset Zoom"> <button tabindex="-1" class="button-textonly-s" id="zoom-reset-s"> <span class="zoom-percent-s button-title"></span> </button> </div> <div class="button-toolbar-s" title="Zoom In"> <button tabindex="-1" id="zoom-in-s"> <svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> <path d="M7 7V5C7 4.44772 7.44772 4 8 4C8.55228 4 9 4.44772 9 5V7H11C11.5523 7 12 7.44772 12 8C12 8.55228 11.5523 9 11 9H9V11C9 11.5523 8.55228 12 8 12C7.44772 12 7 11.5523 7 11V9H5C4.44772 9 4 8.55228 4 8C4 7.44772 4.44772 7 5 7H7Z"></path> </svg> </button> </div> </div> `; // CHANGES ================================================================================================= // inserts the controls to the beginning of the extensions area // let extensionsArea = document.querySelector(".toolbar-extensions"); // extensionsArea.prepend(zoomControls); // inserts the controls to the end of the tab bar let tabBar = document.querySelector("#tabs-container"); let trashCan = tabBar.querySelector(".sync-and-trash-container"); tabBar.insertBefore(zoomControls, trashCan); // prevents double clicks from resizing the window document .getElementById("zoom-in-s") .addEventListener("dblclick", function(e) { e.stopPropagation(); }); // prevents double clicks from resizing the window document .getElementById("zoom-out-s") .addEventListener("dblclick", function(e) { e.stopPropagation(); }); // prevents double clicks from resizing the window document .getElementById("zoom-reset-s") .addEventListener("dblclick", function(e) { e.stopPropagation(); }); // END CHANGES ================================================================================================= // listener for the zoom in button in the zoom control panel document .getElementById("zoom-in-s") .addEventListener("click", incrementPercent); // listener for the zoom out button in the zoom control panel document .getElementById("zoom-out-s") .addEventListener("click", decrementPercent); // listener for the zoom reset button in the zoom control panel document .getElementById("zoom-reset-s") .addEventListener("click", resetZoom); } // Puts the zoom level percentage in the zoom controls let zoomPercent = Math.round(newZoom * 100); let percentageSpan = document.querySelector(".zoom-percent-s"); percentageSpan.innerHTML = zoomPercent + " %"; } // Zooms in the page by the specified increment function incrementPercent() { chrome.tabs.getZoom(function(zoomLevel) { let newZoomLevel = zoomLevel + ZOOM_INCREMENT_AMOUNT / 100; // Max zoom that Vivaldi allows is 500 % if (newZoomLevel <= 5) { chrome.tabs.setZoom(newZoomLevel, updatePercent(newZoomLevel)); } }); } // Zooms out the page by the specified increment function decrementPercent() { chrome.tabs.getZoom(function(zoomLevel) { let newZoomLevel = zoomLevel - ZOOM_INCREMENT_AMOUNT / 100; // Min zoom that Vivaldi allows is 20 % if (newZoomLevel >= 0.2) { chrome.tabs.setZoom(newZoomLevel, updatePercent(newZoomLevel)); } }); } // Sets the zoom back to the default zoom level // - in Vivaldi's settings you can set the default page zoom, this // will follow that if RESET_ZOOM_LEVEL is set to "100" function resetZoom() { let zoomLevel = RESET_ZOOM_LEVEL / 100; chrome.tabs.setZoom(zoomLevel, updatePercent(zoomLevel)); } // CHANGE: Added in Update #1 (see original post for details) // updates zoom percentage on tab change function tabChangeUpdateZoomWrapper() { chrome.tabs.getZoom(function(zoomLevel) { let zoomInfo = { newZoomFactor: zoomLevel }; updatePercent(zoomInfo); }); } // zoom change listener chrome.tabs.onZoomChange.addListener(updatePercent); // CHANGE: Added in Update #1 (see original post for details) // Listener for active tab change chrome.tabs.onActivated.addListener(tabChangeUpdateZoomWrapper); } // Loop waiting for the browser to load the UI setTimeout(function wait() { const browser = document.getElementById("browser"); if (browser) { zoomControlStatic(); } else { setTimeout(wait, 300); } }, 300); })();
I put comments where the changes were made if you want to learn some more about how it works.
Hope it is bug free now (jinxed myself for sure)
-
@nomadic thats great thanks - will compare the 2 css files and learn
if its easy to add the reset button then i think its useful and makes things clearer
-
I just edited the post with the +/- icons not showing up in case someone comes along and copies it without looking at the other posts below it.
-
I've taken the liberty of adjusting the original version (inside the address field). This will work if using the
js
from the first post.Changes
- adjusted alignment
- moved the reset button to the percentage area
- themed colouring
CSS
.zoom-parent { display: inline-block; position: relative; } .zoom-panel { background: var(--colorBgDark); position: absolute; width: 0; height: 24px; bottom: -11.5px; right: 0; padding-top: 2px; overflow-x: hidden; overflow-y: hidden; transition: 0.5s !important; z-index: 1; opacity: .5; } .expanded-nav-c { border-radius: var(--radiusHalf); width: 100px !important; padding-left: 5px; opacity: 1; } .expanded-left-c {margin-right: 100px !important} .page-zoom-controls-c, .button-toolbar-c {display: inline-block} #zoomBtn.active {fill: var(--colorHighlightBg)} .button-toolbar-c > button { height: 22px; color: inherit; align-items: center; justify-content: center; } .button-toolbar-c > button svg { margin-top: -1px; height: 18px; width: 18px; } .button-toolbar-c > button:hover { background-color: transparent; fill: var(--colorHighlightBg) } .button-textonly-c { width: 100% !important; padding-right: 8px !important; padding-left: 8px !important; } .zoom-percent-c { align-self: center; text-align: center; width: 40px; display: inline-block; } .zoom-hover-target {transition: 0.5s !important} .reset-zoom-c { display: inline-block; position: absolute; margin-left: 20px; margin-top: -2px; z-index: 5; opacity: 0; }
-
@sjudenim Looks great! I think I will go back and put the theme colors in the original post. Definitely a better solution.
Also, it looks like the margin/transition aren't working properly on the url in the address field of your window (the url jumps to the left suddenly.) In the
js
, there is the line:elementToTheLeft.style.transition = "0.5s";
Does adding an !important to that line help?
elementToTheLeft.style.transition = "0.5s !important";
There also could be some conflict from another mod that is breaking it. I can't reproduce it with my setup or a clean install.
-
That's my fault, there is nothing wrong with your code. It jumps because I don't have animations enabled in the settings. I don't like Vivaldi's animations for the side panel or speed dial. That's why I use
!important
for the transition to animate just the things I want.Unfortunately your fix doesn't work since I need to override Vivaldi's
common.css
. I can't find the selector for that either -
@sjudenim @adacom @Stardust and anyone else that might be using this modification. I just updated the
js
in all versions of this mod.Changes are labeled with "
// CHANGE: Added in Update #1
" above the chunk of code that was added.This is a bug fix for the percentage not updating when the active tab changes.
All the posts have been edited to include this change.
**** YOU DO NOT NEED TO FIGURE OUT WHERE THE NEW CODE, SHOWN BELOW, GOES. IT IS ALREADY ADDED IN THE CORRECT LOCATION IN THE PREVIOUS POSTS.****The added code should look like this for the version in the original post:
// updates zoom percentage on tab change function tabChangeUpdateZoomWrapper() { chrome.tabs.getZoom(function(zoomLevel) { let zoomInfo = { newZoomFactor: zoomLevel }; updateZoomIcon(zoomInfo); }); } // Listener for active tab change chrome.tabs.onActivated.addListener(tabChangeUpdateZoomWrapper);
And this for the versions that are static in the Extensions Area and in the Tab Bar:
// updates zoom percentage on tab change function tabChangeUpdateZoomWrapper() { chrome.tabs.getZoom(function(zoomLevel) { let zoomInfo = { newZoomFactor: zoomLevel }; updatePercent(zoomInfo); }); } // Listener for active tab change chrome.tabs.onActivated.addListener(tabChangeUpdateZoomWrapper);
-
@nomadic this is very cool but I am waiting for the native implementation
-
Thanks for the update.
I've actually done a little one myself. I noticed that the zoom icon was 1px bigger than my bookmark (which is the same size as the default one as you can see in your image). Resizing it was the simplest thing to do but the zoom in and zoom out icons didn't render nice, so I made some new ones. I also added a theme based fill for when it is active (which matches bookmarked pages).
If interested,
// set the icon based on the new zoom level if (newZoom < RESET_ZOOM_LEVEL / 100) { // zoomed out zoomIconPath = ` <path d="M9.17 1.5c-2.94 0-5.33 2.39-5.33 5.33 0 1.287.458 2.47 1.22 3.393l-3.56 3.56.719.717 3.558-3.56a5.306 5.306 0 003.393 1.22 5.337 5.337 0 005.33-5.33A5.337 5.337 0 009.17 1.5zM6.355 6.186h5.579a.614.614 0 110 1.229H6.355a.615.615 0 110-1.23z" fill="var(--colorHighlightBg)"/> `; } else if (newZoom > RESET_ZOOM_LEVEL / 100) { // zoomed in zoomIconPath = ` <path d="M9.17 1.5c-2.94 0-5.33 2.39-5.33 5.33 0 1.287.458 2.47 1.22 3.393l-3.56 3.56.719.717 3.558-3.56a5.306 5.306 0 003.393 1.22 5.337 5.337 0 005.33-5.33A5.337 5.337 0 009.17 1.5zm-.006 1.916c.341 0 .615.274.615.615v2.153h2.155a.614.614 0 110 1.23H9.78V9.61a.614.614 0 01-.615.616.614.614 0 01-.615-.616V7.414H6.355a.614.614 0 110-1.229h2.196V4.032c0-.34.272-.615.613-.615z" fill="var(--colorHighlightBg)"/> `; } else { // default zoom icon zoomIconPath = ` <path d="M9.17 1.5a5.336 5.336 0 00-5.331 5.331c0 1.287.458 2.469 1.221 3.392l-3.56 3.56.718.717 3.56-3.561a5.305 5.305 0 003.392 1.222A5.337 5.337 0 0014.5 6.83 5.337 5.337 0 009.17 1.5zm0 9.646c-2.38 0-4.315-1.937-4.315-4.315S6.79 2.515 9.17 2.515c2.379 0 4.314 1.936 4.314 4.315s-1.935 4.316-4.314 4.316z"/> `; }
-
just come back to this as the controls moved from the status bar dont show more than they do
as far as i can see the reset button never got added - is this possible - its not 100% necessary but would be nice to have to make the mod complete
-
@adacom Will work on it later today. Sorry I forgot about that request. This is for the tab bar version, right?