You may or may not have watched a video I posted a while back where I created a single, encapsulated SVG file that not only contains SVG graphics but also GSAP's TweenMax (GreenSock Animation Platform) and the CSS and JavaScript required to animate it.

This was a proof of concept that I wanted to explore, in part because in the near future a method such as this could prove very useful for things like banner ads as the industry moves away from the Flash SWF as its primary ad format.

As it happens I have had a lot of interest and enquiries from agencies and individuals about how this method might work for them and their specific circumstances and, as I publish this post, I have just had my first ad signed off using this technique.

I'm writing this post to describe the process, highlight my findings and generally analyse and share the experience.


The Ad Brief

The brief was pretty simple - animate some strap lines and break up those messages with some simple on-brand transitions, ending with a logo and some contact info. The client used an Adobe font called Cronos Pro which was served from TypeKit and I was to use pure JavaScript (no jQuery).

Preliminary Bits

First of all I asked the developer from the hosting site some questions relating to any rules that apply to third party code and some more general things about their setup - the answers I got back were very useful and informed the final decision. His view was that the 'creative' part (i.e. the graphics) was the part that should adhere to the file size rule of around 70Kb. GSAP and the font (that sounds like a bad '80s sitcom I know) were considered to sit outside that rule, as long as they weren't excessively big. TweenMax is 33Kb (gzipped) and the specific weight of that particular font is 33Kb.

So I got on and created the animation here on CodePen (regardless of the final deployment method I always build stuff on CodePen first as it offers the most flexibility for output options) and when I was happy that it was roughly its final size and contained all the necessary animations and graphics, I offered the client a few different options on how the ad might be supplied.

Option 1

Supply it as separate JS, HTML (containing inline SVG) and CSS files; GSAP (specifically TweenMax because it contains TimelineMax, the CSS plugin and the attribute plugin) and the TypeKit font would be loaded from the HTML file as normal.

Option 2

This option was to try out the single encapsulated file method and supply the ad as one single .svg file; GSAP and a base64 encoded version of the Cronos font would all be included in that file. The .svg would then be embedded in the host page using an object tag so that we can inject clickTag and clickInfo parameters.

Option 3

This was a hybrid of the first two. Supply a single .svg file but load GSAP and the font from inside the SVG. Again we'd add the .svg to the page using an object tag.

Decision process

Option one was ruled out because having several files is a bit messy; for a start it requires the SVG tag to be pasted from the CodePen HTML into the main host page on which it sits and then there's the separate CSS and JS files issue and how they are loaded into the existing page with the least fuss and mess.

We considered the second option (complete encapsulation) so I did a few tests with a base64 encoded version of the font.

The first issue I encountered was that when I went to Font Squirrel to convert it to a base64 string I was prevented from doing so because Adobe had put a block on encoding that font. Fair enough although I was using it legitimately so this was a little frustrating (but I do understand why). I went elsewhere and successfully encoded it and pasted it into the file which resulted in a whopping 115Kb. This was a bit of a showstopper - however a quick test in IE revealed a deeper issue in that it just wasn't displaying the font at all.

Now I have to come clean here. I made a bit of a blunder when I created the animated text elements. In my wisdom I decided to use normal HTML h1 tags for the strap lines instead of the daft text tag that SVG uses. I was being lazy basically because HTML tags (for text at least) are better and far more usable in my opinion than SVG's text tag. They wrap for a start (if you set their width).

Daft SVG text? Let me elaborate.

If you've done much/any SVG work you may have had to add in some text using the text tag. You may also have discovered its quirky behaviour when it comes to new lines, wrapping, offsetting; pretty much everything about it is quirky actually. You can get around this quirkiness by using tspan which is like HTML's span only it's very different. It has attributes like dx and dy (delta X, delta Y) which are used to offset the X and Y position of a tspan in relation to the last tspan in a text block.

So I had a load of h1 tags and in order for them to display inside an SVG they must be placed inside a foreignObject - in case you're not familiar with foreignObject or you can't be bothered to click the link...

The foreignObject element allows for inclusion of a foreign XML namespace which has its graphical content drawn by a different user agent. The included foreign graphical content is subject to SVG transformations and compositing.

Couldn't have said it better myself.

But I'll try - a foreignObject is an SVG tag/wrapper that displays non-SVG elements. This means you can include normal HTML in your SVG file - very useful.

Computer says no

So there I was clutching my SVG in my sweaty palm with a base64 font stuffed inside and a load of h1 tags overlaid on top of the SVG graphics that should be styled with that font and it worked...!

(in Chrome but not in IE).

I'll fast forward past several horrific expletives, self kicking and hair pulling and decided that although I never intended to use this method because the file was too big, I couldn't anyway because computer (well, Microsoft) says no.

The Decision

We eventually opted for the third option (the hybrid option) as it satisfactorily met the criteria set out by the host plus the client was keen to try this new method as long as the performance, quality and file size were right.

The process was much the same as earlier except this time I would load the fonts using TypeKit and GSAP via the CDN (Content Delivery Network or 'a computer that nobody switches off').

I have a TypeKit account so I decided to use my account and then when it was ready to go live I'd just swap out the call using their account and we'll all live happily ever after. Except it still didn't work. And this time it didn't even work in Chrome. So I took to Twitter to plead for help. I had responses from several helpful folks including Sarah Drasner, Elliot Geno, some useful tests from Paul Trone and an in-depth technical discussion with Amelia Bellamy-Royds about WTF is going on.

Eventually Elliot Geno pinged Dirk Schulze who confirmed that TypeKit does not work when called from within an SVG as it returns its data to the head tag which SVG doesn't have although it didn't stop me from trying to put one in to test it! (in the main SVG and the foreignObject).

I didn't give up though - my next attempt was to load the TypeKit font from the HTML page in which the SVG will be embedded (using either iframe or object)

This didn't work either although Paul Trone did make a pen that showed how to load TypeKit fonts from within the foreignObject's body that can style elements inside and outside the SVG tag which is useful to know (although, again, this didn't work in IE).

Next up was trying the @font-face method with the fonts placed in a local/relative folder. Again this worked in Chrome but IE wouldn't display the fonts and started complaining with this not-annoying-at-all error that I've never seen before:

CSS3114: @font-face failed OpenType embedding permission check. Permission must be Installable. CronosPro_Bold.ttf

After a few hours of kicking myself I decided to swap feet and kicked myself for a few more hours with the other foot.

So I hunted around to find the cause and found a few threads talking about a little .exe program that can change the permissions on a font or something but to be honest I hadn't got a clue what they were talking about. I tried the .exe anyway but it was written in the last millennium so it wouldn't run on Windows 8.1 - a slow clap followed.

After a few hours of kicking myself I decided to swap feet and kicked myself for a few more hours with the other foot mainly because I had run out of hair to pull out. And then it happened...

I gave in. I bailed. I admitted defeat. I removed the foreignObject (that makes me sound like a surgeon) and replaced all of the HTML text with native SVG text (which only took about half an hour - this annoyed me even more because I'd spent the best part of a day trying to style the HTML text because I was too lazy to code it with SVG text - sometimes I'm a right idiot). If you're reading this, lovely client, I didn't charge you for this!

So half-heartedly I hit refresh in Chrome. It worked. I tried it in IE. And Firefox. It still worked.

At this point I think I cried a little partly because my legs hurt from all the kicking but mainly because my journey had come to a beautiful and much needed end.

Yes IE was still giving me that not-annoying-at-all CSS3114: @font-face failed OpenType embedding permission check. Permission must be Installable. CronosPro_Bold.ttf error but deep down I knew I had permission - plus it was working and that's what matters right?

To do a final tidy up so that all I had to supply to the client was a single .svg I moved the fonts onto a remote server instead of a local/relative folder and changed the @font-face to reflect the new URL. This works in my dev environment but I'm yet to test it on the live server. If there's a cross domain issue or whatever I can always ask the host to put the fonts on their server.

Interestingly as I was writing this article the folk at GreenSock published this article which was very timely, not least because their suggestion that the 'creative' file size should be considered separate from shared CDN resources like GSAP. This resonated with the guidelines that the host set out for this particular ad.

The Final Recipe:

  • One .svg file was supplied.
  • The CSS was included in the SVG in a CDATA tag inside a style tag.
  • The JS that animated the SVG was included in the SVG in a CDATA tag inside a script tag.
  • GSAP was loaded from inside the SVG using a script tag using xlink:href instead of src.
  • The TypeKit font call was replaced with an font-face call (this was placed with the CSS). Currently the font sits on a remote server under my control.
  • The ad is designed to be embedded in an HTML page using an object tag.
  • You can inject parameters into the SVG via the object tag in the HTML page in which it sits - these parameters are:
    • clickTag - the URL that the ad goes to when clicked.
    • clickInfo - the ad info (title tooltip).

The Result

The ad you see below is a version designed to run on CodePen only and does not reflect the final files I submitted to the client (it uses TypeKit for a start!). It's purely here to give you an idea of what I built.

Due to client confidentiality I have removed any references to the client and their brand and remade the ad in a more generic way using different strap lines and my own logo and URL. Note the timing of the typography is a bit wrong because the messaging in the branded ad was different.

You can download a ZIP of the final standalone unbranded SVG ad here.

The Takeaway

So what did I learn from the process of making an encapsulated SVG ad with separate (but embedded) calls to load GSAP and the font?

  1. Don't use foreignObject if you want it to run in IE. Just. Don't.
  2. Use all native SVG elements - this relates to point 1.
  3. For fonts consider using @font-face. TypeKit fonts won't load if the call is made from within an SVG.
  4. Base64 encoded fonts are much bigger than they you might think. If you really need a portable SVG file (or you need to run it offline) and file size isn't an issue then it's fine - otherwise see point 3.
  5. Embedding the SVG using object is a great way to make the ad more dynamic.

Final Thoughts

I think this is quite a succinct way to deliver fully scalable, retina-ready, low file size ads - I particularly like the clickTag and clickInfo parameters as it offers clients the flexibility to change their minds on the URL and ad info right up to the moment they publish the ad. Having this ability not only saves them time (and money) but it means that the same ad can be deployed in many different places with a different click-through URL (for tracking and other contextual data gathering).

You can also compress the SVG file along with the embedded JavaScript which is also a major advantage. My development SVG file is 22Kb and after I'd run the JavaScript through Google's Closure Compiler and run the SVG part through SVGOMG I had reduced the file size down to 16Kb - that's a saving of roughly 27%.

I've been around long enough to know that I've probably made some silly and/or incorrect assumptions here and that there probably are solutions to some of the issues I encountered - I just didn't discover them.

I also know that there are lots of people much more experienced than me out there (and some of you might hopefully be reading this) so if you've spotted some heinous mistake or oversight please let me know - I'm all about learning and improving.


Download

You can download a ZIP of the ad here.

As of 11-09-2015 the ad is now live on the Recruiter.co.uk.