Question

Can I inject a CSS file programmatically using a content script js file?

It is possible for me to inject the css when the js file is linked to my popup.html. The problem is I have to click on the button to open the popup to inject the css. I want it to happen automatically and in the background.

What happens in my code...

  1. Get a variable from a MySQL database through a XMLHttpRequest
  2. Call the function, "processdata()"
  3. "processdata" Will process the data from the XMLHttpRequest. More specifically, split the variable, put it into 2 different variables and make them global
  4. I call the function, "click()"
  5. "click" Then will set the css after 1250 milliseconds using setTimeout
  6. I use chrome.tabs.insertCSS to insert the css. The css name is the variable, "currenttheme"

As I mentioned before it does work using the popup. But the popup has to be opened before the CSS gets injected.

How do I make this all happen automatically, without any user interaction?

Here is my code:

    function getData() {
if (window.XMLHttpRequest)
      {// code for IE7+, Firefox, Chrome, Opera, Safari
      xmlhttp=new XMLHttpRequest();
      }
    else
      {// code for IE6, IE5
      xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
      }
    xmlhttp.onreadystatechange=function()
      {
      if (xmlhttp.readyState==4 && xmlhttp.status==200)
        {
        user_data = xmlhttp.responseText;
        window.user_data = user_data;
        processdata();
        }
      }
    xmlhttp.open("GET","http://localhost:8888/g_dta.php",true);
    xmlhttp.send();
}

getData();

function processdata() {
  var downdata = user_data.split('|||||');
  var installedthemes = downdata[0];
  var currenttheme = downdata[1].toString();
  window.currenttheme = currenttheme;
  click();
  }

function click(e) { 
      function setCSS() {
          chrome.tabs.insertCSS(null, {file:currenttheme + ".css"});
          }
      setTimeout(function(){setCSS()}, 1250);
      document.getElementById('iFrameLocation').innerHTML = "<iframe src='http://localhost:8888/wr_dta.php?newid="+e.target.id+"'></iframe>";
      getData();
}

document.addEventListener('DOMContentLoaded', function () {
  var divs = document.querySelectorAll('div');
  for (var i = 0; i < divs.length; i++) {
    divs[i].addEventListener('click', click);
  }
});
Was it helpful?

Solution

You can programmatically create a new <link> tag and add it to the <head> section just like JS files are loaded dynamically.

var link = document.createElement("link");
link.href = "http://example.com/mystyle.css";
link.type = "text/css";
link.rel = "stylesheet";
document.getElementsByTagName("head")[0].appendChild(link);

Here's an article on the topic.

OTHER TIPS

Extension flicker

A trama to the ecosystem that isn't hard to fix

Preface:

Among many ways to get your css added to a page, most of them cause the screen to flicker - initially showing the page without your css applied, and then later applying it. I've tried several ways, below are my findings.

The gist

You need to append a css <link> or a <style> tag in a Content script injected on document_start

That code looks like this:

var link = document.createElement('link');
link.href =  chrome.runtime.getURL('main.css');
  //chrome-extension://<extension id>/main.css
link.rel = 'stylesheet';
document.documentElement.insertBefore(link);

For some dynamic css code:

var customStyles = document.createElement('style'); 
customStyles.appendChild(document.createTextNode(
   'body { background-color: ' + localStorage.getItem('background-color') + '}'
));
document.documentElement.insertBefore(customStyles); 

Doing this in a script on document_start ensures there is no flicker!

The reasoning

In this JavaScript file you can handle any number of programmatic things. The URL pattern matching offered in manifest.json is very limited, but here you can actually look at all the ?query_string and #hash of a url, and use full regular expressions and string operations to decide whether or not to inject css. That css can also be based on settings, and/or coordinate with messaging to the background page.

Parting words

  • Don't use .insertCSS, you will notice a flicker.

It's to simple you could add to the manifest's permissions field : See web_accessible_resources

 , "web_accessible_resources": [
        "mystyle.css"
    ]

and also add this in content_scripts

"content_scripts": [
    {
        "matches": ["<all_urls>"],
        "css": ["mystyle.css"],
        "js": ["jquery-1.10.2.min.js","content.js","my.min.js"]
    }],

you also add same thing using Programmatic injection and insertCSS().

chrome.tabs.insertCSS(integer tabId, object details, function callback)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top