Improved FavIcon Contrast in Tab Bar
-
Status of Mod: ALPHA release *may not be compatible with all themesSometimes the original color of a favicon in the tab bar has poor contrast relative to your theme's colors. I particularly noticed this in regards to Github with their nearly black favicon and my dark theme. In Opera, the favicons automatically get color corrected to deal with the contrast issue, so Vivaldi should have this functionality as well.
This can be accomplished by adding filters to the images with adjustments for brightness and in the case of pure black or white icons, inverting the colors.
To determine if a favicon needs to be lightened or darkened, the average perceived brightness of the favicon image is determined. This then gets scaled to a value that works with the
css
filter brightness attribute. So on a dark browser theme, a black icon could be turned to white, while a dark blue might just get lightened a few shades.This mod might need some tweaking depending on your theme colors. It works well for my theme and I tested in on a few other's. Fairly dark and light theme's should work, but other colors could have issues. A basic guide for tweaking will be in a separate comment in this thread...
Javascript
(function() { // ============================================================================================================ // Improves the contrast of favicons in the tab bar // - made by nomadic on the Vivaldi Forums // ============================================================================================================ function improveFaviconContrast() { // Print statements for debugging let DEBUG = false; // gets the average brightness of an image function getImageBrightness(imageSrc, callback) { let img = document.createElement("img"); img.src = imageSrc; img.style.display = "none"; document.body.appendChild(img); let colorSum = 0; let alphaPixels = 0; img.onload = function() { // create canvas to hold the image for analysis let canvas = document.createElement("canvas"); canvas.width = this.width; canvas.height = this.height; let ctx = canvas.getContext("2d"); ctx.drawImage(this, 0, 0); let imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); let data = imageData.data; let r, g, b, a, avg; // image data holds 4 color attributes (r,g,b, and a) in order in an array for each pixel // go through each pixel and get the perceived brightness and add them up for (var x = 0, len = data.length; x < len; x += 4) { r = data[x]; g = data[x + 1]; b = data[x + 2]; a = data[x + 3]; // correction factors for each color's perceived brightness avg = Math.floor((r * 299 + g * 587 + b * 114) / 1000); // ignore any transparent pixels if (a === 0) { alphaPixels++; avg = 0; } else { avg = Math.floor(((a / 255) * (r * 299 + g * 587 + b * 114)) / 1000); } colorSum += avg; } // average brightness of image correcting for any transparent pixels let brightness = Math.floor(colorSum / (this.width * this.height - alphaPixels)); callback(brightness); }; } // given an image and the color it is displayed infront of, find the contrast function getImageToColorContrast(imageSrc, color, callback) { let contrast, r, g, b, a; // get the components of the background color [r, g, b, a] = color .replace(/^(rgb|rgba)\(/, "") .replace(/\)(.*)/, "") .replace(/\s/g, "") .split(","); // adjust based on alpha value let factor = a ? parseInt(a) / 255 : 1; let colorBrightness = Math.floor((factor * (parseInt(r) * 299 + parseInt(g) * 587 + parseInt(b) * 114)) / 1000); getImageBrightness(imageSrc, function(imageBrightness) { // very simplistic contrast, seems to work well enough contrast = imageBrightness - colorBrightness; callback(contrast, colorBrightness, imageBrightness); }); } // improve contast of favicon and tab background color function improveContrast(tabId, changeInfo) { let imageSrc = changeInfo.favIconUrl; if (imageSrc !== undefined) { let tab = document.querySelector(`#browser .tab-position #tab-${tabId}`); let elementInBackground, property; // switching to dev console was throwing error because tab doesn't exist if (!tab) return; // figure out which element needs to be checked for background color if (tab.classList.contains("active")) { elementInBackground = "#browser .tab-position .tab.active"; property = "background-color"; } else { elementInBackground = "#browser"; property = "background"; } let backgroundColor = window .getComputedStyle(document.querySelector(elementInBackground)) .getPropertyValue(property); getImageToColorContrast(imageSrc, backgroundColor, function(contrast, colorBrightness, imageBrightness) { DEBUG && console.log("----------"); DEBUG && console.log(tabId + ": " + imageSrc); DEBUG && console.log("ColorBrightness: " + colorBrightness); DEBUG && console.log("FaviconBrightness: " + imageBrightness); DEBUG && console.log("Contrast: " + contrast); let brightnessAmount; let inverted = ""; if (colorBrightness < 128) { // For Dark background colors // These values may need tweaking ================== let oldMax = 10; let oldMin = -50; // ======================================== let newMax = 1; let newMin = 31; // scale the contrast value onto a new range for filter values that work better brightnessAmount = ((contrast - oldMin) * (newMax - newMin)) / (oldMax - oldMin) + newMin; // constrain the filter values to stay within the bounds brightnessAmount = brightnessAmount > newMin ? newMin : brightnessAmount < newMax ? newMax : brightnessAmount; // invert the color if it is too dark for a brightness filter to work if (imageBrightness < 10) { inverted = "invert(1) "; brightnessAmount = 1; } } else { // for light background colors // These values may need tweaking ================== let oldMax = -60; let oldMin = 0; // ======================================== let newMax = 1; let newMin = 0; // scale the contrast value onto a new range for filter values that work better brightnessAmount = ((contrast - oldMin) * (newMax - newMin)) / (oldMax - oldMin) + newMin; // constrain the filter values to stay within the bounds brightnessAmount = brightnessAmount > newMax ? newMax : brightnessAmount < newMin ? newMin : brightnessAmount; // invert the color if it is too light for a brightness filter to work if (imageBrightness > 245) { inverted = "invert(1) "; brightnessAmount = 1; } } // add the filters to the favicon tab .querySelector("img") .setAttribute("style", `filter: brightness(${brightnessAmount}) ${inverted}!important`); DEBUG && console.log("Filter: " + brightnessAmount); DEBUG && console.log("Inverted: " + (inverted === "" ? "False" : "True")); }); } } // loop through all tabs of the current window to update the filters on the favicons function updateContrastOnAllTabs() { DEBUG && console.log("==========================================="); DEBUG && console.log("updating all tab favicons..."); let queryInfo = { currentWindow: true }; chrome.tabs.query(queryInfo, function(tabs) { tabs.forEach(function(tab) { let wrapper = { favIconUrl: tab.favIconUrl }; improveContrast(tab.id, wrapper); }); }); } // when a tab updates the favicon, re-evaluate the contrast chrome.tabs.onUpdated.addListener(improveContrast); // if your Vivaldi theme has the setting "Accent Color from Active Page" selected, // this will update all the tabs when the tab bar background color changes var observer = new MutationObserver(updateContrastOnAllTabs); var body = document.getElementById("browser").parentElement.parentElement; observer.observe(body, { attributes: true, attributeFilter: ["style"] }); updateContrastOnAllTabs(); } // Loop waiting for the browser to load the UI let intervalID = setInterval(function() { const browser = document.getElementById("browser"); if (browser) { improveFaviconContrast(); clearInterval(intervalID); } }, 300); })();
Optional CSS
/* Removes the white outline around the active tab's favicon*/ .tab-position .tab.active .tab-header .favicon { filter: none !important; }
Known Bugs- The settings favicon doesn't get filtered on the initial load
- Cause: Can't get info from chrome:// urls
- Solution: Uncertain. Might need to add a special case to handle it or figure out if adding something to Vivaldi's global manifest is possible.
- The startpage favicon doesn't get filtered
- Cause: Unknown. No error thrown, but probably related to chrome:// urls issue
- Solution: Add a special case in the
javascript
or just set the icon to a new image with a color that better matches your theme incss
- Example:
/* ONLY FOR DARK THEMES: Makes the startpage favicon white because the mod can't get the favicon from the startpage*/ .tab-position .tab[title="Start Page"] .tab-header .favicon img { content: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAABMSURBVFhH7ZQxCgAgDANTH+hj/WBd4uaggxThbgk4HTQxMjNUSHOWgQACCJz8A8O56M7b9y2c4IsOPIUVUEJWwAooISvgBAggUCwgTSL8HixilnmfAAAAAElFTkSuQmCC); }
- Example:
* Please let me know if you have issues with this mod working with your theme or any other bugs you may find
- The settings favicon doesn't get filtered on the initial load
-
@nomadic It's a good idea, github is indeed an issue.
-
@nomadic I really want to use this, but it seems that JS mods get removed on every update...
-
@nomadic said in Improved FavIcon Contrast in Tab Bar:
so Vivaldi should have this functionality as well.
I have upvoted your post, but I would not like this feature without a turn off switch. In turn, I would like to have a box behind the favicon with the front color of the given theme.
-
seems like this mod doesn't work anymore I've had some issue with it and cause I don't know any js I can't really fix it tho I've gotten the output of the error from console which might help you out
-
@nish7009 Sorry, I will have to take a look at it later.
I stopped using this mod as GitHub finally started serving me the correct white favicon, so I didn't need to continue working on the mod for my usage.
Is there a site in particular you are having issues with favicon contrast? It would be useful for me to know when I have a chance to do some testing.
-
@nomadic said in Improved FavIcon Contrast in Tab Bar:
Is there a site in particular you are having issues with favicon contrast? It would be useful for me to know when I have a chance to do some testing.
These site icons are dark and almost invisible when using a dark theme:
https://www.atlanticcouncil.org
https://www.cfr.org
https://www.heritage.org
https://www.cato.org
https://www.brookings.edu
https://carnegieendowment.org
https://csbaonline.org
https://www.military.com
https://www.navytimes.comI fully agree it would be great if Vivaldi dealt with these natively. To your knowledge has anyone filed a feature request on the forum? I'm sure this affects many people using many different theme colors since favicons come in all colors and shades.
-
@codic I found a script here in the forum, with which at least in Linux the .js file is reactivated after a vivaldi update in a simple way.
First you create a new folder
vivaldi-modding
in the /home - directory.Then save the following script as
stable.sh
in this new folder:#!/bin/bash stable=/opt/vivaldi/resources/vivaldi moddir=$HOME/vivaldi-modding/ sudo cp $moddir/custom.js $stable sudo sed -i -e 's/<\/body>/ <script src="custom.js"><\/script>\n <\/body>/' "$stable/browser.html" sudo chgrp rainer $stable/custom.js sudo chmod g+rw $stable/custom.js echo "vivaldi patched"
Finally, create a starter
stable-bash
stored in ~/.local/share/applications asstable-bash.desktop
Command:bash /home/rainer/vivaldi-modding/stable.sh
Run in Terminal.[Desktop Entry] Name=stable-bash Exec=bash /home/rainer/vivaldi-modding/stable.sh Comment= Terminal=true Icon=vivaldi Type=Application
You might chose any icon other than vivaldi to not mix up with your browser icon.
Usage:
After any update just click on this starter. A terminal will open asking for your password.
Type it in and press ENTER.
That's it.
Vivaldi will start with your .js activated.
Do this short process only once, otherwise Vivaldi won't work and you would have to edit the program subfolder. -
Said:
These site icons are dark and almost invisible when using a dark theme
Use:
.tab[title*="Council"] .favicon img {border: 1px solid #d8d8d8 !important; border-radius: 4px !important; background: #adadad !important;}
-
@g_bartsch Which is just a "lite" version of the vivaldi stock filter for the active tab:
.tab-position .tab:not(.active) .tab-header .favicon { filter: drop-shadow(1px 0 0 rgba(246, 246, 246, 0.25)) drop-shadow(-1px 0 0 rgba(246, 246, 246, 0.25)) drop-shadow(0 1px 0 rgba(246, 246, 246, 0.25)) drop-shadow(0 -1px 0 rgba(246, 246, 246, 0.25)); }
-
@barbudo2005 Thank you. I like this solution - particularly the fact that it can target specific icons only and apply different effects to them - but for some reason the code isn’t working for me. I'll keep trying a few things.
-
@Hadden89 Thank you. Hmm? I'm not sure what is wrong with my install but this code also isn’t working.
-
@g_bartsch if you used the code with
filter: none !important
you probably have to remove the !important
-
If you feel lazy to modify the code for different favicons, use this general code for all:
.tab .favicon img {border-radius: 5px !important; background: #adadad !important;}
The influence on the "good" favicons is minimal, rather imperceptible.
-
@barbudo2005 This doesn't mean is a good idea. Often is better to avoid it.
Tl;Dr:
!Important
may break ancillary CSS. -
@barbudo2005 and @Hadden89 Thank you. Maybe it's my simple mistake; do I need to install that JavaScript for the CSS code to work?
-
@g_bartsch
Said:do I need to install that JavaScript for the CSS code to work?
No. The code is simple CSS and work perfect in custom.css.
The code by @nomadic is other solution with Javascript.
Please post the code you are using.
-
@barbudo2005 said in Improved FavIcon Contrast in Tab Bar:
Please post the code you are using.
I've used these two sections of code (not simultaneously).
/* add background behind icon in Tab Bar */ .tab[title*="Council"] .favicon img {border: 1px solid #d8d8d8 !important; border-radius: 4px !important; background: #adadad !important;}
/* add background behind icon in Tab Bar */ .tab[title*="Council"] .favicon img {border: 1px solid #d8d8d8; border-radius: 4px; background: #adadad;}
-
@barbudo2005 said in Improved FavIcon Contrast in Tab Bar:
No. The code is simple CSS and work perfect in custom.css.
The code you gave me for the Web Panel side bar icons works perfectly.
-
Said:
The code you gave me for the Web Panel side bar icons works perfectly.
So the "system" of CSS is Ok.
Maybe there is another code with .favicon that is interfering. Look in your custom.css for this.