I have an addon that changes the look of a website completely by injecting a CSS file. It works but for a split second before the new look appear the old look is there, thus causing the "flicker" each time a page loads. The new look changes the background color etc. so the switch is very noticeable. (I only notice this on my desktop, not on my laptop. I don't know why but other users report it as well, perhaps the faster computer makes the page show faster than it takes to get the CSS injected?). The CSS injection need to happen so the injected CSS is the most important (as in last).
What I've tried that cause this issue (code afterwards):
Code Examples:
Manifest:
{
"manifest_version": 2,
"name": "foo",
"short_name": "bar",
"description": "baz",
"options_page": "options.html",
"version": "2.1.1",
"homepage_url": "http://google.com/",
"permissions": ["storage", "*://google.com/*", "webNavigation", "tabs", "activeTab"],
"browser_action": {
"default_icon": "icon16.png",
"default_title": "title",
"default_popup": "popup.html"
},
"icons": {
"16": "icon16.png",
"48": "icon48.png",
"128": "icon128.png"
},
"content_scripts": [
{
"matches": ["*://google.com/*"],
"js": ["carbonicEditionScript.js"],
"all_frames": true,
"run_at": "document_start"
}
],
"background": {
"page": "popup.html"
},
"web_accessible_resources": ["carbonicEditionStyle.css"]
}
carbonicEditionScript.js
document.addEventListener('DOMSubtreeModified', injectStyle, false);
function injectStyle(){
document.removeEventListener('DOMSubtreeModified', injectStyle, false);
var style = document.createElement('style');
style.setAttribute("id", "CarbonicEditionStyle");
style.setAttribute("class", "CarbonicEditionStyle");
style.setAttribute("type", "text/css");
style.appendChild(document.createTextNode(css));
document.getElementsByTagName("html")[0].appendChild(style);
}
carbonicEditionScriptAlternative.js
document.addEventListener('DOMSubtreeModified', injectCSS, false);
function injectCSS(){
var style = document.createElement('link');
style.rel = 'stylesheet';
style.type = 'text/css';
style.href = chrome.extension.getURL('carbonicEditionStyle.css');
if(document.head){
document.removeEventListener('DOMSubtreeModified', injectCSS, false);
(document.head||document.documentElement).appendChild(style);
}}
background.js
chrome.webNavigation.onCommitted.addListener(function(o) {
chrome.tabs.executeScript(o.tabId, {
code: "var css = 'body{background-color: green !important;}'; var style = document.createElement('style'); style.setAttribute('id', 'CarbonicEditionStyle'); style.setAttribute('class', 'CarbonicEditionStyle'); style.setAttribute('type', 'text/css'); style.appendChild(document.createTextNode(css)); document.getElementsByTagName('html')[0].appendChild(style);"
});
}, {
url: [{hostContains: 'google.com'}]
});
Does anyone know what's going on? All the solutions above work but the flicker is still happening.
Stylish-chrome extension fixed the flicker just by using webNavigation.onCommited event so you should've been already able to fix the issue. However, the problem you experience might be caused by asynchronous reading of the css code from the extension package since you mention web_accessible_resources. In this case cache it in chrome.storage.local or sessionStorage or localStorage. Or consider embedding the CSS inside your content script.
Some [probably redundant] notes on the code you've posted:
Don't use DOMSubtreeModified event because it's a) not actually needed - (you can inject elements even before the webpage is parsed) and b) it's ancient/deprecated/slow/bad.
So the entire content script might be:
var style = document.createElement('style');
style.id = "CarbonicEditionStyle";
style.className = "CarbonicEditionStyle";
style.type = "text/css";
style.textContent = "body{background-color: green !important;}";
(document.body || document.head || document.documentElement).appendChild(style);
Use runAt: "document_start" in executeScript as by default it's document_idle which occurs usually only when the DOM is loaded and parsed:
chrome.tabs.executeScript(o.tabId, {runAt: "document_start", code: "......"});
Consider injecting the CSS directly via insertCSS (not really needed to eliminate the flicker and it won't allow you to disable the injected style but for the sake of completeness):
chrome.tabs.insertCSS(o.tabId, {runAt: "document_start", code: "body{background....."});
"matches": ["*://google.com/*"], won't match www.google.com which is used by default so it should be "matches": ["*://*.google.com/*"],If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With