For a quick demo click
here.
Introduction
Whenever writing CSS with all the vendor prefixes I thought there must be a better way to do this. After an hour of testing many of the solutions available online I chose SCSS/SASS. Although it does not have any direct solution but I was able to use the mixins to create template for every CSS3 property that had vendor prefixes and then use them.
SASS allows us to use variables for setting CSS values. This was an added bonus (there are many other cool features in SASS. Please see its home page for more info.). SASS is compiled before deploying. This limits its benefits to the server-side. It would have been very cool to be able to use this kind of approach on the client-side.
Inspired by this idea I started writing kLib-css.js. Although, I have decided to bundle it with the kLib libraries but, this micro-library has no dependency on the kLib main library. So you can use it even if you have not included the kLib main library.
kLib-CSS provides an approach for scripting CSS dynamically. So, it is possible to change the stylesheet on the fly thus making the coding of cool effects very easy. Since we are setting CSS via JavaScript we are able to use variables for writing common styles.
kLib-CSS also provides shorthand for vendor prefixing, making the life of the coder easier and improving the code readability.
Link to article about: kLib (main library)
Features
kLib-CSS provides a global object constructor named "css". It takes the css selector as the parameter. There is also a second optional boolean parameter named debugMode
. If debugMode
is passed and is true
then the debugger console will log the generated CSS. The properties of a "css
" obj are:
node
: A reference to the newly created style element in the document head. set(property, value)
or set({ prop1: val1, prop2: val2,.....})
: This function facilitates the ability to set a style property.unset(property,[another property,.....])
: This function facilitates the ability to remove a style property.remove()
: This function removes the style from document head.
Examples
Now lets see some of the examples. Say we want to set the following CSS:
.myDiv {
-webkit-box-shadow: 0px 0px 20px #00F;
-moz-box-shadow: 0px 0px 20px #00F;
-ms-box-shadow: 0px 0px 20px #00F;
-o-box-shadow: 0px 0px 20px #00F;
box-shadow: 0px 0px 20px #00F;
}
The vendor prefix shorthand will help us out here. To add a vendor prefix we represent it as --> @Prefix_name. For multiple prefixes we just have to cascade them together. Like --> @webkit@moz. For the last line with no vendor prefix we will just write --> @. All of these prefixes must be separated from the property name by a semicolon and space like --> "; " So the kLib-CSS's alternative code for the required CSS is:
css(".myDiv").set("@webkit@moz@ms@o@; box-shadow", "0px 0px 20px #00F");
Vendor prefixing can also be used for values. For example:
.myDiv {
display : -webkit-inline-box;
display : -moz-inline-box;
display : inline-box;
}
Can be written as:
css(".myDiv").set
("display", "@webkit@moz@; inline-box");
It is also possible to set different fallback values manually via an array. For example:
.myDiv {
background: #E4E8F1;
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,white), color-stop(62%,#E4E8F1));
background: -webkit-linear-gradient(top, white 0%,#E4E8F1 62%);
background: -moz-linear-gradient(top, white 0%, #E4E8F1 62%);
background: -o-linear-gradient(top, white 0%,#E4E8F1 62%);
background: -ms-linear-gradient(top, white 0%,#E4E8F1 62%);
background: linear-gradient(to bottom, white 0%,#E4E8F1 62%);
}
Can be written as:
css(".myDiv").set("background", [
"#E4E8F1",
"-webkit-gradient(linear, left top, left bottom, color-stop(0%,white), color-stop(62%,#E4E8F1))",
"@webkit@moz@o@ms@; linear-gradient(top, white 0%,#E4E8F1 62%)"
]);
The interesting thing to remember is that all of this CSS generation is dynamic on the client side and so can be changed dynamically too. Let's see a very basic example. Suppose we have:
<style type="text/css">
.myDiv {
width : 100px;
height : 100px;
color : red;
background : blue;
}
</style>
<div class="myDiv"> Hello </div>
<div class="myDiv"> Test Div 2 </div>
<button id="myBtn"> Change Background </button>
And we want to change the background color of all elements with class myDiv
to yellow. Then the current popular approach is to have another class with the new style settings and add this class in all the elements (or replace the current class with the new class depending on use). Like:
<style type="text/css">
.myDiv {
width : 100px;
height : 100px;
color : red;
background : blue;
}
.myDiv2 {
background : yellow;
}
</style>
<div class="myDiv"> Hello </div>
<div class="myDiv"> Test Div 2 </div>
<button id="myBtn"> Change Background </button>
<script type="text/javascript">
document.getElementById("myBtn").onclick = function() {
var list = document.querySelectorAll("mydiv");
for(var i = 0; i < list.length; i++)
list[i].className="myDiv myDiv2";
}
</script>
A quick look at "Can I Use It" shows that querySelector support is fairly decent in modern browsers, but the older browsers (like IE7) lack support for this function. The other approach could be to include the large jQuery library and then use its selector. But with kLib-CSS we won't need to be bothered with all of that. Since the CSS is generated dynamically so we don't need a second CSS class. We can just simply modify the existing CSS class and the browser will automatically search for the matching elements and change their appearance. Here is the kLib-CSS code:
<div class="myDiv"> Hello </div>
<div class="myDiv"> Test Div 2 </div>
<button id="myBtn"> Change Background </button>
<script type="text/javascript">
var myCss = css(".mydiv").set({
width : "100px",
height : "100px",
color : "red",
background : "blue"
});
document.getElementById("myBtn").onclick = function() {
myCss.set("background", "yellow");
}
</script>
We can also re-factor multiple CSS with almost same property values by using variables. For example:
<style type="text/css">
.myDiv1 {
width : 100px;
height : 100px;
color : red;
background : blue;
}
.myDiv2 {
width : 100px;
height : 100px;
color : red;
background : yellow;
}
.myDiv3 {
width : 100px;
height : 100px;
color : red;
background : green;
}
.myDiv4 {
width : 100px;
height : 100px;
color : red;
background : white;
}
Can be re-factored as:
var commonStyle = {
width : "100px",
height : "100px",
color : "red"
};
css("myDiv1").set(commonStyle).set("background", "blue");
css("myDiv2").set(commonStyle).set("background", "yellow");
css("myDiv3").set(commonStyle).set("background", "green");
css("myDiv4").set(commonStyle).set("background", "white");
If you are extensively using CSS3 for your webpages, then kLib-CSS can also be used as an alternative to stylesheets because it results in smaller code. Let's test this with the kLib-Overlay.css whose size is 1638.4 bytes (1.6 KB).
(This is just an example. Here the size of kLib-css.js itself will adversely affect the reduction. In actuality you will replace substantially larger stylesheets with kLib-CSS code. So the 1.81kb of kLib-CSS will not matter.)
.klib-overlay-main-div {
display: block;
background: rgba(0,0,0,0.7);
color: #FFF;
position: absolute;
overflow: auto;
text-align: center;
width: 100%;
}
.klib-overlay-container-div {
display: inline-block;
z-index: 5;
position: relative;
}
.klib-alert {
font-size: larger;
text-align: center;
word-wrap: break-word;
padding: 30px 70px;
background: #555;
border-radius: 7px;
border: 1px solid #FFF;
-webkit-box-shadow: 0px 0px 50px #FFF;
-moz-box-shadow: 0px 0px 50px #FFF;
-o-box-shadow: 0px 0px 50px #FFF;
-ms-box-shadow: 0px 0px 50px #FFF;
box-shadow: 0px 0px 50px #FFF;
}
.klib-alert > button {
width: 70px;
height: 30px;
}
.klib-confirm {
font-size: larger;
word-wrap: break-word;
padding: 30px 70px;
background: #555;
border-radius: 7px;
border: 1px solid #FFF;
-webkit-box-shadow: 0px 0px 50px #FFF;
-moz-box-shadow: 0px 0px 50px #FFF;
-o-box-shadow: 0px 0px 50px #FFF;
-ms-box-shadow: 0px 0px 50px #FFF;
box-shadow: 0px 0px 50px #FFF;
}
.klib-confirm-ok {
width: 70px;
height: 30px;
}
.klib-confirm-cancel {
width: 70px;
height: 30px;
margin-left: 10px;
}
.klib-prompt {
font-size: larger;
word-wrap: break-word;
padding: 30px 70px;
background: #555;
border-radius: 7px;
border: 1px solid #FFF;
-webkit-box-shadow: 0px 0px 50px #FFF;
-moz-box-shadow: 0px 0px 50px #FFF;
-o-box-shadow: 0px 0px 50px #FFF;
-ms-box-shadow: 0px 0px 50px #FFF;
box-shadow: 0px 0px 50px #FFF;
}
.klib-prompt-ok {
width: 70px;
height: 30px;
}
.klib-prompt-cancel {
width: 70px;
height: 30px;
margin-left: 10px;
}
The equivalent kLib-CSS code is 975 bytes.
(function () {
css(".klib-overlay-main-div").set({
display : "block",
background : "rgba(0,0,0,0.7)",
color : "#FFF",
position : "absolute",
overflow : "auto",
"text-align" : "center",
width : "100%"
});
css(".klib-overlay-container-div").set({
display : "inline-block",
"z-index" : "5",
position : "relative"
});
var oc = {
"font-size" : "larger",
"word-wrap" : "break-word",
padding : "30px 70px",
background : "#555",
"border-radius" : "7px",
border : "1px solid #FFF",
"@webkit@moz@o@ms@; box-shadow" : "0px 0px 50px #FFF"
},
ob = {
width : "70px",
height : "30px"
};
css(".klib-alert").set(oc).set("text-align", "center");
css(".klib-alert > button").set(ob);
css(".klib-confirm").set(oc);
css(".klib-confirm-ok").set(ob);
css(".klib-confirm-cancel").set(ob).set("margin-left", "10px");
css(".klib-prompt").set(oc);
css(".klib-prompt-ok").set(ob);
css(".klib-prompt-cancel").set(ob).set("margin-left", "10px");
})();
kLib-CSS has provided a reduction of 663.4 bytes. The kLib-CSS alternative code's size is 0.595% of the CSS code, with the added possibility of dynamic manipulation.
So what do you think of kLib-CSS?
Please provide your suggestions and feedback.