Search code examples
javascripthtmlcssimporterror

Import CSS from an HTML-file as external CSS


As the title reads, I want to import an HTML-file as external CSS to a website. Just hear me out: my problem is that I'm working with a very inconvenient CMS that doesn't let me upload CSS-files no matter what.

I'm able to write CSS inside the page directly via HTML-style-tag but that generates a lot of text on every site and also makes maintaining CSS tedious.

As I can't upload CSS-files, I thought maybe I can create a dummy-site inside the CMS with only CSS in it and then later import that site as CSS. The idea was: when parsed, the HTML of the site (header, body, etc.) will just be skipped (as when CSS has i.e. type-errors) while any valid CSS found is going to be imported.

Now when I try importing this website with

<style type="text/css">   @import url(dummyCSSWebsiteURL); </style>

(as the CMS also doesn't grant me access to the header of a page), I - of course - get the error:

"Resource interpreted as Stylesheet but transferred with MIME type text/html"

as I am obviously requesting an HTML-file and not CSS.

I also tried jQuery to simply include all the dummy-HTML into an element (that I would have just not displayed):

$("#cssDummy").load(dummyCSSWebsiteURL);

but I get 2 errors that are probably just showing what a horribly inefficient idea this is:

Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience

A parser-blocking, cross site (i.e. different eTLD+1) script, ["..."], is invoked via document.write. The network request for this script MAY be blocked by the browser in this or a future page load due to poor network connectivity. If blocked in this page load, it will be confirmed in a subsequent console message.

maybe I am just disregarding (or not understanding) things on a conceptual level at all but I still wonder if there is a workaround for this problem?


EDIT: I found a workaround

Definitely don't recommend. Try using different server as pointed out in the comments if you can. I used an XMLHttpRequest to get the external site's HTML, then used regEx to match the content of the div on the page that contains the css and - with added style-tags - inserted the matched css into a div on the page.

Code for external site that contains the CSS:

<div id="generalCode">.testBox{background-color: red; min-height: 200px;}</div>

Code on site that imports the external CSS:

<div class="testBox">
</div>  
<div id="cssCodeOnPage">
</div>

<script>
// use onload if you want
getCssCode();

function getCssCode(){
  // send request to page where div #generalCode contains css
  var xhr = new XMLHttpRequest();
  xhr.open('GET', dummyCSSWebsiteURL);

  xhr.onload = function(){
     // use regex to separate css from rest of html
     var re = /<div id="generalCode">([\s\S]*?)<\/div>/;
     var cssString = xhr.response.match(re)[1];
     cssString = "<style>" + cssString +"</style>";
     // insert css into div
     var cssDivOnPage = document.getElementById('cssCodeOnPage');
     cssDivOnPage.innerHTML = cssString;
} 
  xhr.send();  
}
(sorry for this monstrosity of a question..)

Solution

  • I think the best option is to load that HTML page into an iframe, query the styles out of hte iframe, and then attach that to the current document. I created a live example on Glitch here.

    Nothing but the <style> block will be copied from the HTML. The external HTML document does need to be an actual HTML document though (<html><head><style>....), otherwise the page won't be queryable to retrieve the CSS.

    This is an example in plain JavaScript:

    // Create an iframe
    const iframe = document.createElement("iframe");
    
    // Make it not visible
    iframe.style.visibility = "hidden";
    
    // This will run once the HTML page has loaded in the <iframe>
    iframe.onload = () => {
      // Find the <style> element in the HTML document
      const style = iframe.contentDocument.querySelector("style");
    
      // Take that <style> element and append it to the current document's <head>
      document.querySelector("head").appendChild(style);
    
      // Remove the <iframe> after we are done.
      iframe.parentElement.removeChild(iframe);
    };
    
    // Setting a source starts the loading process
    iframe.src = "css.html";
    
    // The <iframe> doesn't actually load until it is appended to a document
    document.querySelector("body").appendChild(iframe);