dgo
dgo

Reputation: 3937

Gulp create script to inline css to head

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?

Upvotes: 3

Views: 874

Answers (2)

dgo
dgo

Reputation: 3937

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! :)

Upvotes: 1

Chandra Shekhar
Chandra Shekhar

Reputation: 3749

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?

Upvotes: 0

Related Questions