in Technology

Dynamic CSS and DataURI to the rescue

Paisa

Paisa Consumer Finance Redefined.

Source Files available at Github – DataURI and Dynamic CSS (Download)

How it all started?

We at Paisa are developing a financial Web Application, trying to make it easier for users to invest their money. We, in fact, have a rather nifty way of allowing users to browse through Stocks without the overhead complexity of trying to calculate the figures and stats.

The Situation

We wanted to have an identifying logo for each and every company. Well, that is about 3000+ companies. The logos themselves are small – 24 × 24 pixels each.

The Problem

The size of each logo is rather negligible. So, that’s not the problem. The problem is the number of HTTP calls we’ll have to do fetch these logos. Atop that, we’ve no clue what the user will pull and push the filter criteria to view her results. So, we have a problem of displaying 3000+ images and we’ve no clue when and where they’ll appear.

The Solution (Not)

Initially, I was thinking of doing a rather complex matrix of Image Sprites by combining them in pre-defined groups based on — BSE-100, BSE-200, Alphabetical, etc. However, this introduces useless image downloads (bigger size now due to the combined sprite) and not really that re-usable at multiple places. So, CSS-Image-Sprite was NOT the solution.

The Better Solution

One fine evening, an article popped up on HackerNewsData URIs make CSS sprites obsolete. Then, I knew this is something I can pursue to accomplish what we wanted.

In our situation, as each and every company is accompanied by their BSE Code, we inserted that in a class “bse_xxxxxx” (via Python in our case). We do have a default class, “stock_logo” that keeps a default logo ready just in case we don’t have the logo of the company or is being changed or it simply does not exist. This default class also defines how the logo will be displayed, what will be the padding style etc. The class “bse_xxxxxx” is used only to insert the actual logo as a background-image.

Next, Javascript picks up the IDs of the actual logos to be displayed (in our example, from the special attribute `imgID`) and then constructs a link to a handler which generates a CSS file with Data-URIs embedded in it so that we can download all the required images with a single HTTP call and insert them seamlessly into an HTML file.

Example:

Say the markup is like this –

<li class="img img_500" imgID="500">Foo</li>
<li class="img img_600" imgID="600">Bar</li>

The JS code extracts the “imgID” from the li and constructs a query like the one below and inserts it into the DOM inside a link tag –

stylesheets/logos.css?i=500|600

Then, the special handler generates a CSS file by reading the actual images and base64 encoding them. The CSS file is loaded into the DOM and the new images show up instantly.

Use Cases

The use cases look rather rare and might not be something you can use out of the box. However, we hope this will help someone who needs something similar and hope that this will inspire them in solving their own problem. We’ve use Python for our codes but this can be done in any Server Side Programming Language. We used Closure JS Framework with our Javascript but jQuery, a more common framework, was used in this example.

Thanks

Special thanks to @BGhose who stitched all the solutions together in a deployable and usable form. I had to write only a few Stylesheet sample codes for just few companies to show them how it can be done and @Prajwalit easily threw in some Javascript magic and Sidhant completed the Server Side code. Now, we’re just throwing in the logos in our bucket without caring for anything else except to name them against the BSE Codes for the companies. It will just continue to work like a charm.

Browser Support and the obvious Internet Explorer

The article by Nicholas refers to his CSSEmbed solution which uses MHTML mode to make IE6 and IE7 compatible stylesheets that use internal images similar to data URIs. So, you can use a conditional HTML comment to import IE specific styles.

This is our first cut to the solution, we’ll always be on the look-out to improve the solution (think Caching). If you’ve questions, or just want to say something, feel free to comment.

Source Files available at Github – DataURI and Dynamic CSS (Download)

18 Comments

  1. Sensex doesnt have 3000+ companies. BSE has those. Sensex always have only 30 companies.

  2. Sensex doesnt have 3000+ companies. BSE has those. Sensex always have only 30 companies.

  3. Interesting, thanks. Was mentioning to Abinash today about using this:
    <img src="data:image/png;base64,">

    Of course this means your HTML bloats up, and you need to GZIP the whole HTML where you might gzip the CSS file in your approach. But good stuff!

  4. Interesting, thanks. Was mentioning to Abinash today about using this:
    <img src="data:image/png;base64,">

    Of course this means your HTML bloats up, and you need to GZIP the whole HTML where you might gzip the CSS file in your approach. But good stuff!

  5. Deepak, True.

    I didn't mention the GZip part as that's kinda standard process of deployment and is taken care at the Server end.

    Yes, it would have however been a good point to mention that.

  6. Deepak, True.

    I didn't mention the GZip part as that's kinda standard process of deployment and is taken care at the Server end.

    Yes, it would have however been a good point to mention that.

  7. I'm not sure I get it. Why use JS to look for the IDs and construct the css link while this could be done server-side when building the page?

  8. I'm not sure I get it. Why use JS to look for the IDs and construct the css link while this could be done server-side when building the page?

  9. Deepak: We didn't want our HTML to bloat up and that's why the CSS is dynamically generated and then loaded lazily using JS. Another reason why we don't want to put the Data URIs in the HTML is that we want to serve our page as fast as possible and then load all the decorations gradually.

    Kalingo: You are right, but our use case was slightly different. A big chunk of our page is loaded using Javascript when certain filters are manipulated by the user. We also wanted to load our basic page as fast as possible and then load the (potentially heavy) CSS file with the Data URIs lazily. That's why we have to inject the CSS dynamically to the DOM so that it's loaded in the background and doesn't hamper the page rendering. If you email me your contact, I can give you the link to our webapp (still in private beta) so that you can experience it yourself.

  10. Deepak: We didn't want our HTML to bloat up and that's why the CSS is dynamically generated and then loaded lazily using JS. Another reason why we don't want to put the Data URIs in the HTML is that we want to serve our page as fast as possible and then load all the decorations gradually.

    Kalingo: You are right, but our use case was slightly different. A big chunk of our page is loaded using Javascript when certain filters are manipulated by the user. We also wanted to load our basic page as fast as possible and then load the (potentially heavy) CSS file with the Data URIs lazily. That's why we have to inject the CSS dynamically to the DOM so that it's loaded in the background and doesn't hamper the page rendering. If you email me your contact, I can give you the link to our webapp (still in private beta) so that you can experience it yourself.

  11. Wouldnt using GWT might simplify most of such requirements? There is some HTML+JS bloat attached to GWT but if its a sticky application which user is going to use heavily then I would much rather use GWT and live with first load time than use complex solutions.

  12. Wouldnt using GWT might simplify most of such requirements? There is some HTML+JS bloat attached to GWT but if its a sticky application which user is going to use heavily then I would much rather use GWT and live with first load time than use complex solutions.

  13. Ajit: The solution is not complex at all. It was implemented in < 10 lines of code.

  14. Ajit: The solution is not complex at all. It was implemented in < 10 lines of code.

Comments are closed.