Optimize CSS asynchronous load

One of way to make website loading faster is CSS async load.
It need to use Javascript to load CSS after loading.

There’s a few steps to make it work.

1. Make css file to Json data format.
Let’s take this css file for example.
http://file.myfontastic.com/eNzJBJA24QdpMtRZDEqjmX/icons.css
It contains css code like this.

@charset "UTF-8";

/* untitled-font-1 */
@font-face {
  font-family: "untitled-font-1";
  src:url("https://file.myfontastic.com/eNzJBJA24QdpMtRZDEqjmX/fonts/1491933871.eot");
  src:url("https://file.myfontastic.com/eNzJBJA24QdpMtRZDEqjmX/fonts/1491933871.eot?#iefix") format("embedded-opentype"),
    url("https://file.myfontastic.com/eNzJBJA24QdpMtRZDEqjmX/fonts/1491933871.woff") format("woff"),
    url("https://file.myfontastic.com/eNzJBJA24QdpMtRZDEqjmX/fonts/1491933871.ttf") format("truetype"),
    url("https://file.myfontastic.com/eNzJBJA24QdpMtRZDEqjmX/fonts/1491933871.svg#1491933871") format("svg");
  font-weight: normal;
  font-style: normal;
}

[data-icon]:before {
  font-family: "untitled-font-1" !important;
  content: attr(data-icon);
  font-style: normal !important;
  font-weight: normal !important;
  font-variant: normal !important;
  text-transform: none !important;
  speak: none;
  line-height: 1;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
.
.
.

 

Let’s minify it from cssminifier.com

@charset "UTF-8";[class*=" icon-"]:before,[class^=icon-]:before,[data-icon]:before{font-family:untitled-font-1!important;font-style:normal!important;font-weight:400!important;font-variant:normal!important;text-transform:none!important;speak:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}@font-face{font-family:untitled-font-1;src:url(https://file.myfontastic.com/eNzJBJA24QdpMtRZDEqjmX/fonts/1491933871.eot);src:url(https://file.myfontastic.com/eNzJBJA24QdpMtRZDEqjmX/fonts/1491933871.eot?#iefix) format("embedded-opentype"),url(https://file.myfontastic.com/eNzJBJA24QdpMtRZDEqjmX/fonts/1491933871.woff) format("woff"),url(https://file.myfontastic.com/eNzJBJA24QdpMtRZDEqjmX/fonts/1491933871.ttf) format("truetype"),url(https://file.myfontastic.com/eNzJBJA24QdpMtRZDEqjmX/fonts/1491933871.svg#1491933871) format("svg");font-weight:400;font-style:normal}[data-icon]:before{content:attr(data-icon)}.icon-chevron-right:before{content:"\61"}.icon-chevron-left:before{content:"\62"}.icon-twitter-alt:before{content:"\64"}.icon-youtube:before{content:"\63"}.icon-facebook:before{content:"\65"}.icon-pinterest-circled:before{content:"\66"}.icon-search:before{content:"\69"}.icon-star-1:before{content:"\6b"}.icon-instagram:before{content:"\6c"}.icon-rss:before{content:"\68"}.icon-googleplus:before{content:"\67"}.icon-pinterest:before{content:"\6a"}.icon-remove:before{content:"\6d"}.icon-arrow-circle-right:before{content:"\6e"}.icon-bars:before{content:"\6f"}.icon-share-alt:before{content:"\70"}

It became much smaller.
Using editor, escape backslash (\) like this (\\). And then escape double quote (“) to (\”). Also escape slash (/) to (\/)

Then it will look like this.

@charset \"UTF-8\";[class*=\" icon-\"]:before,[class^=icon-]:before,[data-icon]:before{font-family:untitled-font-1!important;font-style:normal!important;font-weight:400!important;font-variant:normal!important;text-transform:none!important;speak:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}@font-face{font-family:untitled-font-1;src:url(https:\/\/file.myfontastic.com\/eNzJBJA24QdpMtRZDEqjmX\/fonts\/1491933871.eot);src:url(https:\/\/file.myfontastic.com\/eNzJBJA24QdpMtRZDEqjmX\/fonts\/1491933871.eot?#iefix) format(\"embedded-opentype\"),url(https:\/\/file.myfontastic.com\/eNzJBJA24QdpMtRZDEqjmX\/fonts\/1491933871.woff) format(\"woff\"),url(https:\/\/file.myfontastic.com\/eNzJBJA24QdpMtRZDEqjmX\/fonts\/1491933871.ttf) format(\"truetype\"),url(https:\/\/file.myfontastic.com\/eNzJBJA24QdpMtRZDEqjmX\/fonts\/1491933871.svg#1491933871) format(\"svg\");font-weight:400;font-style:normal}[data-icon]:before{content:attr(data-icon)}.icon-chevron-right:before{content:\"\\61\"}.icon-chevron-left:before{content:\"\\62\"}.icon-twitter-alt:before{content:\"\\64\"}.icon-youtube:before{content:\"\\63\"}.icon-facebook:before{content:\"\\65\"}.icon-pinterest-circled:before{content:\"\\66\"}.icon-search:before{content:\"\\69\"}.icon-star-1:before{content:\"\\6b\"}.icon-instagram:before{content:\"\\6c\"}.icon-rss:before{content:\"\\68\"}.icon-googleplus:before{content:\"\\67\"}.icon-pinterest:before{content:\"\\6a\"}.icon-remove:before{content:\"\\6d\"}.icon-arrow-circle-right:before{content:\"\\6e\"}.icon-bars:before{content:\"\\6f\"}.icon-share-alt:before{content:\"\\70\"}

Let’s wrap this with this javascript function. callbackCSS({"data":"json content goes here"})

Final myfontastic.json file look like this.

callbackCSS({"data":"@charset \"UTF-8\";[class*=\" icon-\"]:before,[class^=icon-]:before,[data-icon]:before{font-family:untitled-font-1!important;font-style:normal!important;font-weight:400!important;font-variant:normal!important;text-transform:none!important;speak:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}@font-face{font-family:untitled-font-1;src:url(https:\/\/file.myfontastic.com\/eNzJBJA24QdpMtRZDEqjmX\/fonts\/1491933871.eot);src:url(https:\/\/file.myfontastic.com\/eNzJBJA24QdpMtRZDEqjmX\/fonts\/1491933871.eot?#iefix) format(\"embedded-opentype\"),url(https:\/\/file.myfontastic.com\/eNzJBJA24QdpMtRZDEqjmX\/fonts\/1491933871.woff) format(\"woff\"),url(https:\/\/file.myfontastic.com\/eNzJBJA24QdpMtRZDEqjmX\/fonts\/1491933871.ttf) format(\"truetype\"),url(https:\/\/file.myfontastic.com\/eNzJBJA24QdpMtRZDEqjmX\/fonts\/1491933871.svg#1491933871) format(\"svg\");font-weight:400;font-style:normal}[data-icon]:before{content:attr(data-icon)}.icon-chevron-right:before{content:\"\\61\"}.icon-chevron-left:before{content:\"\\62\"}.icon-twitter-alt:before{content:\"\\64\"}.icon-youtube:before{content:\"\\63\"}.icon-facebook:before{content:\"\\65\"}.icon-pinterest-circled:before{content:\"\\66\"}.icon-search:before{content:\"\\69\"}.icon-star-1:before{content:\"\\6b\"}.icon-instagram:before{content:\"\\6c\"}.icon-rss:before{content:\"\\68\"}.icon-googleplus:before{content:\"\\67\"}.icon-pinterest:before{content:\"\\6a\"}.icon-remove:before{content:\"\\6d\"}.icon-arrow-circle-right:before{content:\"\\6e\"}.icon-bars:before{content:\"\\6f\"}.icon-share-alt:before{content:\"\\70\"}"})

And define this javascript function on the top of your page. You can include this in common javascript file on the header.

var LSYE=function(h){var s=document.createElement('script');s.src=h;document.getElementsByTagName('head')[0].appendChild(s);};
var callbackCSS=function(d){var o=document.createElement("style");o.innerHTML=d.data;document.getElementsByTagName('head')[0].appendChild(o);};

LYSE function is put javascript to header async way.
And callbackCSS will put css data to header after that.

So you can put this line at the bottom of page, this css will be loading asynchronous way.

<script>LSYE("myfontastic.json");</script>

You can add async attribute to loading file during page load.

<script async>LSYE("myfontastic.json");</script>

Or add defer attribute to loading file after page load finished.

<script async>LSYE("myfontastic.json");</script>

In my case, this css file contains icons for the site. So icons are appeared just few seconds later, but shows totally fine.
This will be helpful when the file is not loading or slow. So this doesn’t affect to site speed.

 

Dynamic grid layout using Freewall Javascript

Recently I have created gallery page. And I wanted to have something cool looking and save space for thumbnails.

Not like this:

Not organized gallery layout

But instead like this dynamic layout style:

Dynamic block layout using Freewall

The images are keep moving and save space while I am resizing. Isn’t it cool?

There’s couple of Javascript developed for dynamic layout: Freewall, Mansonry, uikit dynamic grid, Shapeshift and etc.

I liked Freewall the most, it is simple to use.

Here’s an example page that I have created.

It is very easy to use. I put setTimeout() function and trigger function again because there’s overlapping image problem. I guess it is because the images are not loaded fully and it doesn’t scale the size of each blocks.

If it is just html block then we don’t need.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Freewall Testing</title>
<script type="text/javascript" src="../js/jquery-1.12.4.min.js"></script>
<script type="text/javascript" src="freewall.js"></script>
<style type="text/css">
body { background: rgba(231, 231, 231, 0.43);}
.free-wall { margin: 15px; }
.brick { width: 221.2px; }
.info { padding: 15px; color: #333; }
.brick img { margin: 0px; padding: 0px; display: block; }
</style>
</head>
<body>

    
<div class="free-wall" id="freewall">
    <?php foreach($vars['items'] as $item){ ?>
    <div class="brick">
      <img src="<?php echo $item['src']?>" width="100%">

    </div>
    <?php } ?>
</div>
<script type="text/javascript">
  var wall = new Freewall("#freewall");
  wall.reset({
    selector: '.brick',
    animate: true,
    cellW: 200,
    cellH: 'auto',
    onResize: function() {
      wall.fitWidth();
    }
  });
$( document ).ready(function() {	
  wall.fitWidth();
  $(window).trigger("resize");
   setTimeout(function(){ 
      $(window).trigger("resize");
     },
  700);   
});  
</script>

</body>
</html>

 

“Flows like water. Sweet like honey”

How to use Selenium webdriver with Javascript on Mac

I am managing many accounts CMS, Google account and ETC. My new project is making automated account creation system so that I can spend less time to do boring works.

You can imagine that type just name and email address in the form, it will open browser and open chrome browser and go google admin account page and click create new and adding the typed information accordingly. Then go to CMS account page and create an account in the same way. Wonderful, I can save couple minutes or even an hour DAILY!

Selenium is browser automation solution.

To install this it need some preparation

First install Xcode. Open App store and search for Xcode, download and install.

apple download xcode

Another one is Homebrew. This makes installing software a lot easier. Open terminal and type this.

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

Install Homebrew, type this in terminal

Now, install node.

brew install node

install node using brew

Then Install chrome driver.

brew install chromedriver

install chrome driver

Make webdriver home folder and install selenium-webdriver.

mkdir webdriver
cd webdriver
npm init -y
npm install -S selenium-webdriver

Install selenium-webdriver

Note that there were error, without init npm. I got an error like ‘missing package.json warnings and errors off’. So I ran “npm init -y”. This will create package.json file.

Now everything is prepared.

Are you ready for launching new browser? Go!

Type node. And command like this order.

$ node
var webdriver = require('selenium-webdriver');

// Open Chrome Browser
var driver = new webdriver.Builder().forBrowser('chrome').build();
OR
var driver = new webdriver.Builder().withCapabilities(webdriver.Capabilities.chrome()).build();

// Open google.com
driver.get('http://www.google.com');

Then browser opened and open google home page.
Launching selenium webdriver

Now create js file which includes all the commands like this. I have created open_browser.js file using below commands.
Open browser command selenium

And Run js file.

node open_browser.js

open chrome browser using selenium

Working good. I will post how to login to google account for next step.

Will this makes me lazy? Not sure!