Skip to content

Using CSS for custom JavaScript components

2012 January 3
by Sven Busse

Juten Tach,

I’m working quite a lot with HTML / CSS / JavaScript these days (wonder why …). Sometimes, you want to build a component completely through JavaScript. For example, you might want to build a component, that uses the canvas, where you draw things. That component has a JavaScript function object (some sort of class) and the canvas element.

Now, I thought, I would like to style this component with CSS. Problem is, since I am using a JavaScript / Canvas component, CSS cannot affect my drawing on the canvas, since this is done through JavaScript. Still, I would like to define things in CSS.

After digging a little bit, here is my solution (in a little example):

First, in my HTML page I have a simple canvas element with an id “myCanvas”. Since I am using jquery I use this little on ready function:

<script>
 $(document).ready(function(){
  var myComponent = new CanvasComponent($("myCanvas"));
 });
</script>

OK, so this instantiates my JavaScript component object an passes it a reference to the respective canvas DOM element.

Next, I define the CSS, that I would like to have for my component. Note, I do not necessarily define css for the canvas element itself, but rather css for what I will do on the canvas. Sounds weird? Bear with me.

canvas-component {
 background-color: #cacaca;
 line-height: 2px;
}

Ok, let’s see. First of all, you notice, that the selector says “canvas-component”, which is not a known HTML tag. But that’s OK, because HTML5 allows for custom tags officially. Second, the style attributes are not meant to affect the canvas directly, as I already said. I declare styles, that I want to use later in my drawings on the canvas. There is a little downside: unfortunately you cannot define your own custom style attributes here, because the browsers will ignore them, so you have to use the best next existing attribute, that comes close semantically. For this little example, I just choose a background-color and a line-height.

Now all we have to do, is bring my JavaScript component and the style declaration together. I do this in the constructor of my JavaScript component object:

function CanvasComponent(canvas) {
 this.canvasElement = canvas;
 this.styleClass = null;

 // Some IE use 'rules', other browsers mainly use 'cssRules', which is official
 var allCSSRules =
      document.styleSheets[0].cssRules
   || document.styleSheets[0].rules;
 for(var i = 0; i < allCSSRules.length; i++) {
  if(allCSSRules[i].selectorText == "canvas-component")
   this.styleClass = allCSSRules[i].style;
 }
 alert("line-height: " + this.styleClass.getPropertyValue("line-height"));
}

So, as we can see, in document.styleSheets we have an Array of all the different embedded or loaded stylesheets. In my example, I have only one stylesheet declaration as an external file, that’s why I can use document.styleSheets[0]. Within the stylesheet, there a many rules, of which one is the rule, i have printed above. We have to find it manually, since the DOM API does not provide any functionality for that. So i go through all the rules and search for the selector “canvas-component”. If I find it, I save it. And now I can access the declarations via <code>getPropertyValue()</code>, for example. There are other functions as well, but this one is probably the most useful one.

Now that I can access the declaration, I can use them in my canvas drawings. For example, when drawing a line, I can now set the thickness of the line according to the line-height from my CSS, or if I draw some big background rectangle, I can use the background-color from CSS.

Well, that’s it, perhaps that comes in handy for you some time.

2 Responses leave one →
  1. January 3, 2012

    I can see why you would do this (i.e. im not dissing your workaround), but it looks absolutely HORRID!

    • Sven Busse permalink*
      January 3, 2012

      hehe, well perhaps it needs some cleaning, like hiding the complexity behind a nice API.

Leave a Reply

Note: You can use basic XHTML in your comments. Your email address will never be published.

Subscribe to this comment feed via RSS

*