3

I'm having trouble articulating what I want, but I'm sure this has been asked before. I'm looking for a way to use gulp to inject precompiled CSS into a javascript function that executions at runtime. Basically, something like this:

build/index.html

Contents:

<div> <!-- content here --></div>

build/index.css

Contents:

div {
    background:red;
    }
/* more rules */

Compiles to something like this:

dist/index.html

Contents:

<script>(function(){
         var style=document.createElement('style');
             style.innerHTML='div{background:red;} /* all the other rules */';
             document.head.appendChild(style);
      }());</script>

<div></div>

It doesn't have to resemble this exactly, but I hope my meaning is clear. I'm looking for away to avoid the work of converting my css into an inline string capable of being injected into the head at runtime by js.

Is this clear? Do you know of anything that assists in this process?

2
  • This is what i have tried checkout my answer. Commented Apr 6, 2018 at 6:54
  • can i make use of task runner for that, bcoz i have a solution. Commented Apr 9, 2018 at 7:11

2 Answers 2

1

For anyone else having a similar problem, this is how I solved the problem.
Starting with the gulp-css-to-js-style plugin by spacerockzero, I made some minor modifications to his code and achieve exactly what I wanted. As it stood in the beginning, the plugin was a single file with no dependencies. You can see his original code on Github. This is what I came up with:

'use strict';

var through = require('through2');

/**
 * Inject style tag with my minified, one-line css
 */

module.exports = function injectCSS() {
var stream = through.obj(function(file, enc, cb) {
var template = 'function injectStyles(rule) {\n' +
  'var style = document.createElement("style");\n' +
  'style.innerHTML = rule;\n' +
  'document.head.appendChild(style);\n' +
  '}\n' +
  "injectStyles('" + file.contents + "');\n";

file.contents = new Buffer(template);
    this.push(file);
    cb();
  });

  return stream;
}

The only caveat was that I found that I was unable to include CSS Media Queries and @keyframes anywhere but at the beginning of the CSS files - (I'm sure there is a fix for this, I just didn't dig into it). So, I just created multiple css files, and the script executed multiple times and thus created multiple style elements. Here is an example of what got appended to my HTML on page load.

<script>
(function(){

  function injectStyles(rule) {
    var style = document.createElement("style");
    style.innerHTML = rule;
    document.head.appendChild(style);
  }

  injectStyles('@media(min-width:375px){.visible-content{margin-left:auto !important}}');
}());
</script>

Hope this is useful to someone else! :)

Sign up to request clarification or add additional context in comments.

Comments

0

Here is what i have tried so far,

enter image description here

This is My folder Structure. My SCSS Files get Compiled to CSS using gulp

SCSS File

body{
  background-color: black;
}

CSS File

body{
  background-color: black;
}

script.js

(function(){
  var style = document.createElement("style");
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function(){
    if(this.readyState == 4 && this.status == 200){
      style.innerHTML = this.responseText;
    }
  };
  xhttp.open("GET","../css/style.css",true);
  xhttp.send();
  document.head.appendChild(style);
})();

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>

  <script src="js/script.js"></script>
</body>
</html>

Here is what i have done. I have created a IIFE(immediately-invoked function expression) which creates a style element. I am making a ajax request to my style.css file and fetching its contents. and finally appending it to head section. I haven't included the link tag. I am loading the styles from JS.

Is this what you expected?

1 Comment

Unfortunately not - It all needs to be inline, because there is no place to include external files. I have a solution which I will post in a second. I actually got something working well. You will see what I mean.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.