CSS 3D Clouds Retake

This post is going to cover my experience following through the tutorial on making CSS 3D clouds posted here: http://www.clicktorelease.com/tutorials/css3dclouds/. I didn’t make the original code, but I did run into several issues while I went through and I wanted to share my experience, work-arounds, and pieces of code that were missing from the original tutorial.

All the questions that came up and fixes changes here were done on the Chrome Beta (v20.0.1132.41 beta-m to be exact)

1. Creating the world and a camera

CSS 3D Clouds Step 1

In this step, you create two div’s in the body of your HTML 5 page, the outer <div> gets an id of viewport and the inner <div> gets an id of world. From there you setup some structural styling (viewport spans entire screen via absolute positioning, world is centered in the middle)

Initial Page Setup

Some initial styling needs to be done to make it look like the demo, here’s what I have:

* {
	box-sizing: border-box;
	margin: 0;
	padding: 0;
}

body {
	overflow: hidden;
}

#viewport {
	background-image: linear-gradient(bottom, rgb(69, 132, 180) 28%, rgb( 31, 71, 120 ) 64%);
	background-image: -o-linear-gradient(bottom, rgb(69, 132, 180) 28%, rgb( 31, 71, 120 ) 64%);
	background-image: -moz-linear-gradient(bottom, rgb(69, 132, 180) 28%, rgb( 31, 71, 120 ) 64%);
	background-image: -webkit-linear-gradient(bottom, rgb(69, 132, 180) 28%, rgb( 31, 71, 120 ) 64%);
	background-image: -ms-linear-gradient(bottom, rgb(69, 132, 180) 28%, rgb( 31, 71, 120 ) 64%);
}

#world {                    
	background-color: rgba(255, 0, 0, .2);
}

Vendor prefixes

I’m so used to Chrome being the “latest and greatest” that I honestly expected to be able to use non-prefixed CSS properties and have the code “just work”. That’s NOT the case. As of this writing you will need to use prefixed properties, so add the following prefixes into the appropriate rules:

#viewport {
	perspective: 400;
	-webkit-perspective: 400;
	-moz-perspective: 400;
	-o-perspective: 400;
}

#world {                    
	transform-style: preserve-3d;
	-webkit-transform-style: preserve-3d;
	-moz-transform-style: preserve-3d;
	-o-transform-style: preserve-3d;
}

Help, my javascript code doesn’t work!

You probably put your javascript in the <head> tag, which means that document.getElementById( 'world' ) will not work because the elements don’t exist yet. Put the script at the end right before the </body> tag and it should work if everything else is correct.

Besides, it’s just good practice to put your javascript last.

Help, my javascript code doesn’t work! (pt 2)

This just shows my ignorance of javascript, but if something still isn’t working, you might have this problem:

Javascript uses the \ character in your strings to tell the parser to treat the next line as if the string continued:

'translateZ( ' + d + 'px ) \
rotateX( ' + worldXAngle + 'deg) \
rotateY( ' + worldYAngle + 'deg)';

Is the same as:

'translateZ( ' + d + 'px ) rotateX( ' + worldXAngle + 'deg) rotateY( ' + worldYAngle + 'deg)';

Zooming javascript

The code samples in the original tutorial omit the code to zoom in and out with the mouse wheel. Here it is in all it’s javascripty wonderfulness:

window.addEventListener( 'mousewheel', onContainerMouseWheel );
window.addEventListener( 'DOMMouseScroll', onContainerMouseWheel );

function onContainerMouseWheel( event ) {
	event = event ? event : window.event;
	d = d - (event.detail ? event.detail * -5 : event.wheelDelta / 8);
	updateView();
}

2. Adding objects to our world

CSS 3D Clouds Step 2
E.g. .cloudBase.

Create cloud base code is incorrect

Instead of:

for( var j = 0; j <<; 5; j++ ) {

the correct line is:

for( var j = 0; j < 5; j++ ) {

Actual random numbers and prefixed transforms

The random numbers for createCloud():

var random_x = 256 - ( Math.random() * 512 );
var random_y = 256 - ( Math.random() * 512 );
var random_z = 256 - ( Math.random() * 512 );

The transform styles for createCloud()

div.style.transform = t;
div.style.webkitTransform = t;
div.style.MozTransform = t;
div.style.oTransform = t;

3. Adding layers to our objects

CSS 3D Clouds Step 3
There were a couple of things in this section that cause me to scratch my head and go whyyyyy?

Code for random generation and transforms.

Random variables:

var random_x = 256 - ( Math.random() * 512 );
var random_y = 256 - ( Math.random() * 512 );
var random_z = 100 - ( Math.random() * 200 );
var random_a = Math.random() * 360;
var random_s = .25 + Math.random();
random_x *= .2; random_y *= .2;

Vendor transforms:

cloud.style.transform = t;
cloud.style.webkitTransform = t;
cloud.style.MozTransform = t;
cloud.style.oTransform = t;

Why don’t I see the new squares?

You have to add in the style for .cloudLayer into your CSS:

.cloudLayer {
	position: absolute;
	left: 50%;
	top: 50%;
	width: 256px;
	height: 256px;
	margin-left: -128px;
	margin-top: -128px;
	background-color: rgba( 0, 255, 255, .1 );
	-webkit-transition: opacity .5s ease-out;
	-moz-transition: opacity .5s ease-out;
	-o-transition: opacity .5s ease-out;
}

I see the cloud layers, but why are they are all flat?

Yeah, this got me too, the parent div’s need to have preserve-3d, so add this into your CSS:

#world div {
	transform-style: preserve-3d;
	-webkit-transform-style: preserve-3d;
	-moz-transform-style: preserve-3d;    
	-o-transform-style: preserve-3d;    
}

4. Making the 3D effect work

CSS 3D Clouds Step 4

This section is essentially “make the layers point at the camera”. You still want them projected into the same locations, but you want them to always face the camera, giving you that sense of “volume” effect.

Vendor Transforms and Update()

First, here’s all the vendor transforms:

layer.style.transform = t;
layer.style.webkitTransform = t;
layer.style.MozTransform = t;
layer.style.oTransform = t;

Now, you also need to call this update manually once right before the end of your script. So right before the closing script tag, make sure you call this:

update();

Render Loop

Finally, even if you do this, you’ll notice that your layers still don’t point at the camera. You need to add in a function that loops and updates the layers in the #viewport at regular intervals. You could add a call to the update function inside your mouse move event, but we’ll need the loop to get the rotation to work in the next step, so it’s better if you just do this now.

(function() {
	var lastTime = 0;
	var vendors = ['ms', 'moz', 'webkit', 'o'];
	for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
		window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
		window.cancelRequestAnimationFrame = window[vendors[x]+
			'CancelRequestAnimationFrame'];
	}
	
	if (!window.requestAnimationFrame)
		window.requestAnimationFrame = function(callback, element) {
			var currTime = new Date().getTime();
			var timeToCall = Math.max(0, 16 - (currTime - lastTime));
			var id = window.setTimeout(function() { callback(currTime + timeToCall); }, 
				timeToCall);
			lastTime = currTime + timeToCall;
			return id;
		};
	
	if (!window.cancelAnimationFrame)
		window.cancelAnimationFrame = function(id) {
			clearTimeout(id);
		};
}())

Lets break this down. I discovered that this function is a polyfill for the browser animation spec here one Paul Irish’s awesome blog http://paulirish.com/2011/requestanimationframe-for-smart-animating/. Previously, when you would animate something, you would set a timer, and every few milliseconds go and update move something from point A to point B on the screen with a small increment. In order to get smoother animations, the browsers are starting to support this requestAnimationFrame function that allows several changes to be made, and update everything with a single reflow / redraw of the screen. This becomes especially handy when you are updating multiple elements on the screen and you want a clean responsive display. It also means that the browser can stop animating when you switch tabs, which means that you don’t eat up battery when someone isn’t looking at your page :)

All you really need to know is that this creates a function on the javascript window object that tells the browser to “please render an animation frame, and call back to this function when you are done and ready to render the next frame”.

5. Final words

CSS 3D Clouds Step 5

Subtle Rotating

Not mentioned, but if you want the clouds to slowly rotate like the demo, you need to add in the rotate z component into the transform update of your layers like so:

'rotateZ( ' + layer.data.a + 'deg ) /

And, you need to add in a speed property into your cloud layers when you create them:

speed: .2 * Math.random() - .1

Adding Cloud Images

Instead of this:

var cloud = document.createElement( 'div' );

Use this (or find your own cloud .png, it should be transparent to work properly)

var cloud = document.createElement( 'img' );
cloud.style.opacity = 0;
var src = 'http://www.clicktorelease.com/tutorials/css3dclouds/cloud.png';
( function( img ) { 
	img.addEventListener( 'load', function() {
		img.style.opacity = .8;
	} )
 } )( cloud );
cloud.setAttribute( 'src', src );

And finally to remove all the debug styles remove the following lines out of your CSS:

From #world remove:

background-color: rgba(255, 0, 0, .2);

From .cloudBase remove:

background-color: rgba( 255, 0, 255, .5 );

From .cloudLayer remove:

background-color: rgba( 0, 255, 255, .1 );

That should cover it! Now go make some happy clouds.

Credits

Everything here was completely taken from the Click To Release CSS 3D Clouds tutorial and expanded to include the missing parts.

How to use PhoneGap to port quickly your web app to a native iOS and Android device

This blog post will show how to take a web site written only in HTML5, CSS3 and JavaScript and quickly develop an iOS and Android mobile application. In order to do this, I will use Adobe PhoneGap, a mobile web frame to build cross-platform mobile applications. As mentioned in my previous blog post, PhoneGap is an HTML5 app platform that allows you to author native applications with web technologies. Even though my blog post will only show how to develop an iOS and Android application, PhoneGap also supports developing BlackBerry, webOS, Windows Phone 7, Palm devices, etc. In a nutshell, you’ll be using a PhoneGap wrapper that contains your web-based HTML, CSS and JavaScript code. Also, you will gain access to many of the device’s native features such as the compass, camera, the contacts list, accelerometer, etc.

PhoneGap introduced last year PhoneGap Build which offers a cloud-based service that takes your app written in HTML5, CSSe and Javascript and sends you back app-store ready apps for iOS, Android, Palm, Symbian and the other mobile platforms. Check out pricing and other details on their web site.

Below is a general process involved in getting setup using PhoneGap and developing an application:

1. PhoneGap has a great Getting Started tutorial for all the mobile platforms. Download the PhoneGap tools and the specific set of tools for the platforms you’re working with. For example, download Xcode and iOS SDK if you plan on porting your web site to an iOS application. Download the Android SDK and Eclipse if you plan on making an Android application.

2. Install all the platform tools and PhoneGap to your existing environment.

3. Start developing your web application and test with a web browser of your choice. I normally use Visual Studio to write my web application and test it using Safari, Chrome or any webkit supported browser. Since these are the types of browsers on smartphones. I would take advantage of Visual Studio’s IDE in debugging my javascript code or Web Inspector in Safari or the dev tools found in FireFox or Chrome.

4. Once you’re ready to port it to a mobile application, you will put all your web files within the www folder. For Xcode, all you need to do is create a new project using the PhoneGap template. Once the project is created, immediately compile the project. Once the project is done building, a www folder will be created in your project folder. Add the www folder into the project navigator. This is where you will house all your web files (HTML5, CSS3 and Javascript files). Run your project and you should see your web page displayed in the iPhone or iPad simulator.

5. For Android, install Android SDK, Eclipse and then the Android plug-in for Eclipse. Create an Android project in Eclipse and follow these steps to modify the project to support PhoneGap. Then run the project and select an Android Virtual Device (AVD) to use as the emulator to display your application.

6. Steps 4 and 5 can be done for you using PhoneGap Build. Just upload your web application files using their Cloud service and they will send you back app-store ready packaged files for the mobile platforms they support.

7. A noteworthy caveat is you will have to tweak some of your web language code depending on which mobile platform you choose. Not all mobile devices are similar in hardware but PhoneGap does an excellent job in pointing out issues through their API Docs section on their web site.

For step 5, here are some links to great tutorials on how to Get Started in developing for Android:
1. Getting Started With Android Development Using Eclipse
2. Getting Started with Android on a Mac
3. Running Android SDK Examples Using Eclipse

So below is a web page example written only in HTML5, CSS3 and Javascript. The HTML consists of an input element and a button. Using JavaScript, it dynamically shows in an unordered list the input values you submit. If you click any of the list items in the unordered list, it will make a call using the Twitter Search API and return the latest tweet with that keyword as an input parameter.

HTML elements:

- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    <body>
	<div id="main">
        <h1>Search Twitter</h1>
        <form id="foodForm">
            <input type="text" id="foodName" placeholder="keyword" />
            <button id="submitFood">Tell Us!</button><br>
        </form>
        <ul id="foodList">
        </ul>
        </div>
   </body>
}

JavaScript code event handler when DOM is loaded:

- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    document.addEventListener("DOMContentLoaded", function () {
            //navigator.notification.alert("I think today will be a great day.", function() {}, "Great Day");
            // uncomment below code to clear items in LocalStorage
            //window.localStorage.clear();
            // <ul> instance variable
            var foodList = document.getElementById('foodList');
            // textbox instance variable
            var foodField = document.getElementById('foodName');

            // length of food items in localStorage
            var l = window.localStorage.length;
            var i = 0;
            var storedFoodName;


            // add food item to <li> child
            function addNewFoodItem(foodName) {
                var newFoodItem = document.createElement('li');
                newFoodItem.innerHTML = foodName;
                foodList.appendChild(newFoodItem);
            }

            // loops through localStorage for food items and calls addNewFoodItem function
            for (i; i < l; i++) {
                storedFoodName = window.localStorage.key(i);
                if (storedFoodName.match(/^food[.]/))
                    addNewFoodItem(window.localStorage.getItem(storedFoodName));
            }
}

Javascript code that gets handled when the button is clicked:

document.getElementById('foodForm').addEventListener('submit', function (evt) {
                evt.preventDefault();
                var newFood = foodField.value;

                // creates a foodKey value with food.[length]
                var foodKey = "food." + (window.localStorage.length + 1);
                // calls addNewFoodItem function
                addNewFoodItem(newFood);
                // saves foodKey and input food to localStorage
                window.localStorage.setItem(foodKey, newFood);

                // clears foodFied variable
                foodField.value = "";
                return false;

            }, false);
        });

Javascript code that calls the Twitter Search API remote service using the XMLHttpRequest object and parses the JSON data returned. It displays the latest tweet in a notification alert after you click on the ListItem in the unordered list.

// callback function to get the latest tweet
        function getLatestResult(JSONstring) {
            var twitterPayload = JSON.parse(JSONstring);
            var latestResult = twitterPayload.results[0];

            return latestResult;
        }

        // performs a get request for url
        // passes the response text to callback
        function getXHR(url, callback) {
            var req = new XMLHttpRequest();
            req.onreadystatechange = function () {
                if (this.readyState == 4) {
                    if (this.status == 200 || this.status == 0) {
                        callback(this.responseText);
                    } else {
                        console.log('something went wrong');
                    }
                }
            }
            req.open('GET', url, true);
            req.send();
        }

        // event handler for the clicks on <li> elements using event delegation to catch all of these events.
        // We listen on the document element, and then, if the target of the event matches one of our list items, 
        // fires the event handler
        document.addEventListener("click", function (evt) {
            if (evt.target.tagName == 'LI') {
                // gets the selected <li> element
                var foodSubject = evt.target.innerHTML;
                var foodSearch = encodeURIComponent(foodSubject);
                // generates twitterURL for Twitter Search API
                var twitterUrl = 'http://search.twitter.com/search.json?q=' + foodSearch;

                // calls getXHR function to get latest tweet of selected <li> element 
                // then calls callback function to pop-up an alert msg with latest tweet
                getXHR(twitterUrl, function (response) {
                    var latestTweet = getLatestResult(response);
                    var msg = 'Latest Tweet about ' + foodSubject + ' from ' + latestTweet.from_user + ': ' + latestTweet.text;
                    //navigator.notification.alert("PhoneGap is working")
                    alert(msg);
                })
            }

        }, false);

Project Navigator in Xcode

Project Navigator in Xcode for PhoneGap project

iPhone Simulator of Search Twitter

iPhone emulator of PhoneGap application

Project Explorer in Eclipse

Project Explorer of Android project in Eclipse. Notice the /assets/www folder and /libs folder with PhoneGap related web files

Android Virtual Device

Android Virtual Device running the web page

PhoneGap is good at helping developers leverage their experience at building web applications using web standards, HTML, CSS and JavaScript. If you know web standards, you’ll experience few problems while working with PhoneGap. All you need to learn is how to use the PhoneGap API. Once you become familiar with the PhoneGap API, you can quickly take advantage of accessing the device’s camera, pull up the contacts or work with the accelerometer or compass.

As the web site example above shows, if you need to connect your application with a remote web service, you can easily bring in tools like jQuery to create powerful Ajax handlers. Or as I demonstrate in how to use XmlHttpRequest objects.

As I pointed out in step 7 above, just because you code a web application using PhoneGap and it works on an iPhone device, it doesn’t automatically mean that it will work on other devices. You will have to test and tweak for the other devices that are supported.

If you want to port to multiple devices, you will need separate environments for each wrapper. For example, you won’t be able to maintain your Android PhoneGap wrapper with Xcode. I used my Mac and have installed Xcode and Eclipse but I make sure I keep them in separate environments.

PhoneGap, Appcelerator and mobile web frameworks

What are mobile web frameworks

What are web based application frameworks? First, there are many out there including PhoneGap, Appcelerator, etc. For developers struggling to learn Objective-C, Java, etc these frameworks allow you to still build mobile applications. Essentially, these frameworks exist to help developers that come from a web development background with a set of tools to use with their current skillset (HTML, CSS and Javascript) to build native or native-like mobile applications. PhoneGap and Appcelerator Titanium are the most popular amongst all the frameworks out there on the interweb. For this blog post, I want to compare and contrast the two along with other mobile frameworks. Hopefully this will help you if you’re deciding on which framework to architect your next project.

PhoneGap is developed by Nitobi Software which was recently acquired by Adobe. On their website, it says “Build apps in HTML and Javascript and still take advantage of core features in iPhone/iPod touch, iPad, Google Android, Palm, Symbian and Blackberry SDKs.” Currently, PhoneGap v1.3 supports 7 different platforms including iOS, Android, Palm, WebOS, WP7, Symbian and Bada. The framework is open source which means developers and companies can use PhoneGap for mobile applications that are free, commercial, open source, or any combination of these.

What is required to use PhoneGap

PhoneGap projects require the underlying SDKs (e.g. iOS 5 SDK) to be installed and building the project happens from an IDE, such as Xcode 4. Once you have Xcode and iOS 5 SDK installed, download PhoneGap and install it. Open up Xcode and under the New Project dialog, there should be a PhoneGap-based Application project template as shown in Figure 1.

New Project Dialog

Figure 1

After installing the PhoneGap project template, make sure to build and launch the iPhone simulator. You should see an error in your simulator informing your “index.html” was not found as shown in Figure 2.

iPhone Simulator Error

Figure 2

In order to fix this, go ahead and copy the ‘www’ directory to the Project Navigator in Xcode. The ‘www’ folder exists in the PhoneGap project folder location. You can quickly go to that folder by right-clicking on the project root in Project Navigator and selecting “Show In Finder”. After you drag the ‘www’ folder, you should see a prompt as shown in Figure 3. Select “Create folder references for any added folders” and click Finish.

Folder Reference

Figure 3

Your Project Navigator should look similar to Figure 4.

Project Navigator

Figure 4

Now rebuilt and run the iPhone simulator again and you should see similar to Figure 5

iPhone Simulator

Figure 5

Basically, the developer puts his files (HTML, CSS or Javascript) into a ‘www’ folder in the project directory. When building, PhoneGap then renders these files inside a native WebView provided by the OS-specific language (either Objective-C or Java), it exposes access to certain native device features, like Accelerometer, Camera, Notifications, etc.

In a nutshell, a PhoneGap application is essentially still a web application, wrapped inside a WebView. It still remains a web application that is displayed through rendering of HTML, CSS and Javascript using a browser instance on a mobile device.

Appcelerator Titanium

Appcelerator Titanium is another mobile framework to help developers build mobile applications but only on iOS and Android at this time. Similar to PhoneGap, Titanium provides a binding layer that maps Javascript function calls to natively available APIs.

However, Appcelerator claims to be different than PhoneGap in translating Javascript code to native application code. The Javascript code is being interpreted during runtime and through a bridge layer, function calls to Titanium.some_function invoke native application code under the hood.

Another way Appcelerator is different is up until the latest version of Appcelerator, v1.5, you would write your application code in HTML, CSS and Javascript. Now, the application code is written in pure Javascript, using mainly functions that the Titanium API exposes. Apart from using it to access special device features (Camera, Accelerometer, etc), it also enables the developer to render native UI elements (buttons, tables, etc).

These differences give Appcelerator an edge of performance. Just want to emphasize, all the application code will be in Javascript, even the styling of elements happens through function calls. One thing to also keep in mind is to ask yourself will the Javascript API provide all the functionality needed in your application.

Unlike PhoneGap, building and packaging your application does not happen inside an IDE (Xcode, Eclipse, etc), but through their software, Titanium Developer. This is the tool to set up new projects, configure, test and package them. Any IDE of your choice can be used to write the application code.

When choosing a mobile web framework, keep in mind it depends on the requirements of the application when choosing which framework to go with. If the goal is to target many platforms as possible, then PhoneGap may be the right choice. If true native-ness and performance is important, then Titanium may be the choice.

There are many other mobile web frameworks out there that are open source and free and some that charge a developers license fee. I would like to write a follow up blog post on MonoTouch, NimbleKit, AppMobie and others. Stay tuned.

Font Hybridization in HTML 5

Over this Christmas break, I was over at a friends house and got to sit down and tinker with my friends Mac. I’d forgotten how good fonts look, and I suddenly realized why so many sites are now using custom web fonts. Since I primarily use Windows at work and at home, I get annoyed by fonts that are difficult to read or that don’t render well on the screen. Somehow, I’ve never been 100% happy with font rendering on windows. It’s been getting better, but it’s still not as good as a Mac is. Maybe its the screen, maybe its the OS, maybe its the app, maybe its a combination of all of the above. Because I’ve been on this HTML kick, and I’m on windows, I’ve tended toward Cufon as my font replacement tool of choice when building sites since it’s the only one that produces a “more-reasonable” output on my machine.

But Cufon by it’s nature has several drawbacks. First, you can’t copy and paste text rendered with Cufon. With most of the newer browsers you can select it, but there’s not much more you can do beyond that. So, I usually limit Cufon usage to titles, headers, and the more “design-ery” aspects of a page. Second, because Cufon is image based, if someone zooms in on your text beyond 100% Cufon rendered text gets all fuzzy the same way it would if you zoomed in on an image. And finally, because Cufon renders with javascript on the client, there’s no way to cache the text. Javascript is fast, but when you’re rendering a large amount of text on a phone, there’s usually not a good way around a flash of unstyled content. And it happens each time you go to a new page because it can’t be cached.

Web fonts on the other hand, allow you to use fonts in a very similar manner as if you had them installed on your device with native rendering by the OS. You can select, copy, paste, and use it as you would any other piece of text. Web fonts are cacheable, so although you could get a flash of unstyled content when you first visit a page, subsequent visits should render immediately. The disadvantage however, is the OS. On windows, the rendering of fonts just… Sucks. So people don’t use it.

But what if there was a way to do a hybrid between Cufon and Web Fonts?

Besides the rendering issue, Web Fonts are the best option. They’re the most flexible and the most future proof. But they still suffer on Windows, some phones, and on older browsers that don’t support the new @font-face CSS syntax. So what if we did a hybrid? Use @font-face, then fall back on Cufon for older browsers, and for windows. The advantage is that on a new browser the@font-face‘s will be cached, used for the initial rendering of the page, and then cleaned up with Cufon later.

Using Modernizr and a little custom javascript to do user agent testing I put together a page to test out the hybrid font idea:

http://www.paulrohde.com/demo/cufon-hybrid/demo.html

It’s a rough draft. I have some screen shots below from both Mac and PC’s (click for full size versions).

Mac

PC

For simplicity, the javascript code to test and load Cufon and my custom cufon polyfill looks like this:

function rendersNiceFontface() {
	result = navigator.appVersion.indexOf("Win") != -1 
		|| navigator.appVersion.indexOf("Android") != -1;
	return result;
}

var supportsNiceFontface = !rendersNiceFontface();

Modernizr.load([
	{
		test : Modernizr.fontface && Modernizr.canvas && supportsNiceFontface,
		
		nope : [ 'cufon-yui.js', 'BebasNeueRegular_400.font.js', 'cufon-polyfill.js' ]
	}
])

Using the Modernizr yepnope.js, I’m able to completely skip loading Cufon at all if the browser supports good @font-face rules. There’s more that I’d have to do to clean it up before I’d use it in a real setting, but it demonstrate the concept, and is something I could definitely use later as a @font-face polyfill. It does have some drawbacks though, you have to maintain both your CSS rules and your Cufon replacement calls, and Cufon doesn’t work well with a large amount of body text, so if you don’t support @font-face, I’d fall back to a good secondary font and forgo Cufon in those cases.

I hope this got some gears turning, I’m looking forward to some comments.

Back to HTML – Tricky margins

HTML layout is weird. Half the time it makes sense, and the other half it makes half as much sense as it should. To that end, here’s a quick refresher on margins and padding and layout that I’m writing as much for myself as for you.
Lets start with a box. In this imaginary real box wold, you are either putting blocks next to each other, or inside other boxes, to get elements to line up and appear in some fashion or another. These virtual boxes have two properties, margin and padding. In our box world analogy, the padding would represent the thickness of the walls of the box. If you add something thats bigger than the inside of the box, the actual outside edge of the box will have too expand to contain whatever is inside. When you set a margin however, its simply stating a rule that you would like this box to be at least x number of units away from any other sibling box.

For instance, I have Box A and I want anything around Box A to be at least 2 feet away on the top or bottom of the box. Now, I have Box B that also has margin, but for Box B I only need everything to be 1 foot away along the top or bottom of the box. If I placed these two boxes next to each other (as siblings), the boxes would be 2 feet apart. Box A overrules Box B since A requests any other box to be further away from B, and thus B is also satisfied since the margin for B is less than A. If I also specified padding for box B of 6 inches, the contents of B would be at least 2 feet 6 inches from A since margin is measured from the outside edge of the box.

Here is a real example. In this case, I have 2 paragraphs. The orange space represents margins, and the green represents padding as shown by the debugging tools in chrome.

The code looks something like this:

<article>
     <p>This is some paragraph text 1</p>
     <p>more paragraph text</p>
</article>

Example 1 Margining:


Notice how the margins collapse when they touch each other. Remember that margin represents ‘minimum spacing’.

Example 2 Padding:


Notice how not only are the paragraphs further apart with similar spacing, but they padding doesn’t overlap at all. This distinction is important when you lay out content, and especially when you start floating things. Eventually the imaginary real box model starts to break down as we approach real world HTML. Another really important tidbit to understand is that margining can extend OUTSIDE of the container. For instance, in the previous code snippet, we only have one article and two

tags. If we put two articles side by side, we can see how the paragraph margining will extend out of the article block:

HTML:

<article>
     <p>This is some paragraph text 1</p>
     <p>more paragraph text</p>
</article>
<article>
     <p>This is some paragraph text 1</p>
     <p>more paragraph text</p>
</article>

Note how the article is only the size of the paragraphs inner dimensions:

However, when we look at the paragraph margining, we see:

The paragraph spacing extends beyond the bounds of the article and pushes the paragraphs and the article down. I know. The box model doesn’t work any more. Remember the differences and play around with it yourself.

Some Practical Advice

  • When you first start laying elements out on a page, only specify bottom margining and keep the space consistent. It will help debug initial issues since there will be less overlapping margins.
  • Use a sylesheet language like less or sass so you can keep the numbers more consistent and easier to change.
  • Use good debugging tools. Chrome Developer tools, or Firebug are both good. They’ll keep you from going insane immediately.
  • If all else fails, simplify the problem. Make a small, quick html page to try to replicate your scenario.
  • Tinker. You only learn something by doing it. Do it.

Stream HTML5 Video from Azure Blob Storage

I’ve been looking into what needs to be done in order to stream videos hosted in Microsoft Azure’s Blob storage with the HTML5 <video> control. Once I got over a few little hiccups, the process was very straight forward.

The Process

I followed the Video On The Web section of the online book Dive Into HTML5 by Mark Pilgrim for the overall process. It provides a couple nice pictures stating which browser supports which codec. I was disappointed with the fact that there isn’t one codec supported by all the mainstream browsers, so to support all you have to have at least 2.

I decided that I would take my video and encode it in the H.264 and OGG formats. NOTE: The document above is a bit old but the steps provide a good idea of what to set to accomplish the encoding. Once the two versions were ready I created a simple .html page and hosted it in my local IIS just to test out that I had done the encoding correctly. Below is what I had.

<!DOCTYPE html>
<html>
<body>
<h1>Test</h1>
<video width="576" height="320" controls>
	<source src="tbbt_s1e1.mp4"  type='video/mp4; codecs="avc1.42e01e, mp4a.40.2"'>
	<source src="tbbt_s1e1.ogv"  type='video/ogg; codecs="theora, vorbis"'>
</video>
</body>
</html>

The HTML5 <video> control is really straight forward to use. The controls attribute tells the browser to display its prebuilt controls and there are 2 ways to specify the source video file(s). The first way only uses one file so if the browser doesn’t support it, then you can’t watch. The second way is what I followed, and it allowed me to provide multiple video files allowing the browser to choose the codec it supports.

When I viewed the page the video player controls showed up, but the videos didn’t work. The important thing I missed was to make sure IIS had the correct MIME type defined for the videos (MIME Types Rear Their Ugly Head section of the document above). After adding the following MIME types to the root IIS node the videos played.

Extension MIME type
.ogv video/ogv
.mp4 video/mp4

 
With the videos functioning, I then moved on to hosting the video files in my Blob Azure Development Storage and pointing to those files. Previously I had created a little application to upload files to Blob storage, so I used it to upload the files instead of any of the Azure file explorer applications.

I then pointed the .html file above to the Azure urls and got the player again with the video not working.

<!DOCTYPE html>
<html>
<body>
<h1>Test</h1>
<video width="576" height="320" controls>
	<source src="http://127.0.0.1:10000/devstoreaccount1/videocontainer/c625cff5-6f03-4e89-a8b3-43f29b97f14b.mp4"  type='video/mp4; codecs="avc1.42e01e, mp4a.40.2"'>
	<source src="http://127.0.0.1:10000/devstoreaccount1/videocontainer/4e3f4531-e3d2-407f-8a78-bea8d540d537.ogv"  type='video/ogg; codecs="theora, vorbis"'>
</video>
</body>
</html>

Turns out I ran into the exact same MIME type issue. My application didn’t set the Content Type property of each Blob to the correct type so Azure wouldn’t allow it to be streamed out, but it could be downloaded. To quickly change this I used Azure Storage Explorer to point to my Development Storage and change the Content Type of each of the files to their respective MIME type specified in the table above.

I then browsed to the .html file again and the videos played!

Codec Issues
When encoding the video to the H.264 and OGG formats I ran into a few issues. First I used HandBrake and Firefogg (requires Firefox) respectively to encode the files, but while HandBrake worked, the file Firefogg provided didn’t have audio when played in Firefox. I then switched to using ffmpeg2theora hoping that would fix the issue, but it didn’t. I then tried encoding them for the WebM codec, but that still didn’t work. In a final attempt I took the H.264(.mp4) file that HandBrake output(since it was working great) and used Miro Video Converter to convert it to a OGG(.ogv) file. This new version worked in Firefox, so what I thought was an issue with Firefox or my hosting just turned out to be an encoding problem.

I also ran into an issue viewing the H.264 version in IE9, but it turned out to be a Compatibility View issue that I documented here

I still have a ton to learn about Azure Storage, HTML5 Video and Codecs, but I think this was a good start.

Tip: Using zoom to target images to high density displays

I found this several days ago when I was looking for a way to scale images on an iPhone inside of a fluid layout such that they would display at a 1:1 pixel ratio. If you didn’t already know, the iPhone 4 and 4S displays everything as if the screen was the same size as a normal iPhone when it measures and does the layout. The result is that all the text looks extremely crisp, and any sites already designed for the original iPhone don’t break or look weird. With images this means that a 300 x 300 pixel image displays the correct size in the layout, but is essentially scaled up to fit over 600×600 “physical pixels”. As I was poking around I found an old CSS zoom property here: http://reference.sitepoint.com/css/zoom that for some reason works on mobile safari. Add a media query for 2x density screens, and viola! Your images now display at physical pixel dimensions on the iPhone 4 and 4S.

Here’s what the CSS looks like:

@media screen and (-webkit-min-device-pixel-ratio: 2) {
     img {
          zoom: 50%;
     }
}

Awesome hacks.

Happy img scaling.

HTML5 Video and IE9 Compatibility View

When messing around with HTML5 and its <video> I had it working great in IE9 on my machine using the H.264 codec. I then had some of my coworkers attempt to view my .html file which I had hosted in IIS on my machine. Everyone could view the page but the video player only showed up for one guy. I was baffled and started on a wild goose chase trying to figure out what was different between my machine, the one that worked and all the other machines.

Finally I started comparing the HTML being displayed in each IE9 browser using the Developer Tools (these can be accessed easily by pressing F12).

In the 2 browsers that showed the video, the HTML looked totally correct. In the others the <video> tag was closed prematurely and the <!DOCTYPE html> tag at the top was a comment instead of valid HTML. Then I noticed what the issue was. My page was being shown in IE9 Compatibility View which doesn’t support HTML5, which totally explained the weird behavior.

It turns out that the default settings in IE9 are to view all intranet sites in Compatibility View. This seems totally backwards to me as a developer as I am usually dealing with the latest and greatest (which Compatibility View is not). To change this press alt, then choose Tools, select Compatibility View settings, and then uncheck Display intranet sites in Compatibility View.

With this change on everyone’s machines they can now all view the HTML5 video hosted in my IIS.

On Modern Layouts and Semi Fluid Grids

Over the last several weeks, I’ve really been digging into HTML5, CSS3, and really figuring out what modern browsers can do. Frankly browsers have grown by leaps and bounds over the last several years, and as such we need to re-evaluate how we build websites. Especially in regards to how we treat older browsers. I recently read this post by Paul Irish and he points out that ideally, each browser gets an experience that is customized to that browser’s capabilities. What this means however, is that we should expect older browsers to get an experience that isn’t exactly the same as the experience we get on a modern one. (Example, no rounded corners. No text shadows. Etc…)

Let me try to explain:

A really good analogy to this is how HD TVs have changed the TV industry. Imagine for a moment that a website site is the film, and the TV is your browser. If you had a black and white TV, you wouldn’t expect to see the film in color. If you have a standard definition TV you don’t expect to see the full wide screen movies, and if you have a widescreen 720p TV, you don’t expect to experience the full effect of 1080p Blu-ray. Filmmakers don’t shoot in standard definition and then try to ‘upgrade’ the film to HD quality. Its pointless and a LOT of extra work. No, they shoot with the best film and resolution they can afford and then cut it down to the lower denominators when or if they support older formats.

In the same way, if you use an older browser you wouldn’t expect to get the full experience a modern browser supplies, and moreover, you likely wouldn’t even know what your missing! You don’t expect it since any other site you visit also doesn’t have those features or details. Because of this, you should be designing for the ‘1080p’ of the web, and accept that users with older browsers will still get the ‘standard definition’ experience.

The Web Is Not Print

There’s also an important distinction between print and the web. The web is dynamic and fluid, highly interactive. The web is also delivered on a range of sizes and devices, from something the size of a business card up to large 30″ monitors. There comes a point where form and function have to merge in a non-trivial way to provide an experience that fits itself to the users needs, when they need it, the way they need it.

Print isn’t.

Print is extremely static, once it’s designed, it stays that way. If you design a poster, you design it to be printed at a certain size or at certain proportions. If you design a book or a magazine, you have total control over the size and layout of your spread. If you continue to think about the web this way, you’ll miss much of the dynamic nature of the web that makes it attractive as a medium.

Its only recently we’ve really gained the tools and techniques we need to REALLY break out and away from the classic printers layout due largely to the rise in mobile devices, HTML5 and CSS3. What I’m calling this “Print Format” tends to reveal itself at the extreme edge cases.

Specifically:

  • On large monitors where content will appear tiny and hard to read with lots of extra white space.
  • On small monitors or mobile devices when the content doesn’t scale down and your forced to scroll back and forth to read.

Over the years one of the only real solutions to address this, if someone addressed it at all, was just to never set a width for your content and just let it fill your entire screen. Although this almost works for some things, it’s difficult to read as paragraphs will stretch across the screen. You will constantly lose your place as your eyes track back and forth to the beginning of the next line. Also, if your designing a static site and you and your designers both have large screens, it’s easy to ‘fill up the space’ with ancillary or useless content and ads to make the site feel balanced. All in all, most so called solutions were hacks on a broken system.

Semi Fluid Layout

I’m finally starting to see some CSS frameworks and sites that are really starting to apply these principles. An excellent site that demonstrates this principle is the following:

www.goldengridsystem.com

No matter what browser you visit it on, or what size your browser is at, the content will be sized appropriately, the typography will be readable, and everything will feel right. Sans insane urges to resize your browser window.

One of the key benefits to designing a fluid theme is the instantly correct look you get when you open the site. Its not something people will or should consciously expect, it should simply BE the correct size the instant it appears, regardless of size, screen, or orientation. Its like walking into a store. A well designed building is easy to navigate, spacious, and consistent across all other stores you visit regardless of size. You don’t ever think about it, you’re not there to analyze the layout of the store. You’re there to buy groceries. Anything that gets in the way or makes it hard to find what you’re looking for will stick out, and if it’s bad enough, you’ll go somewhere else. Its the same way with a site or blog. Users are there for a reason: For information, or to read, or to consume whatever content you are serving up. They didn’t come to analyze your site and how it’s designed, but if they have any difficulty at all in getting to what they want in whatever form they want it in, they’ll be somewhere else in about 8 seconds.

It’s also important to be intentional about the decisions your making and how they will affect the final layout of a site. The more you reduce the complexity of the interactions, and the better defined the interactions are, the better the final end result will be. Use what you design. Do what your users do. You’ll know best what you do and don’t like and what feels right. Go with it, but don’t be afraid to stop, backtrack, or even completely scrap good ideas if they don’t fit with what you expect from the design.

Fluid Layout First

Something that’s going to become really important is to start out your design efforts knowing your designing for a fluid site like this. Laying out the groundwork and page structure is going to be extremely important to your long term sanity as a developer. There’s this concept in computer science called emergent behavior, essentially, the less you specify about a system, and by imposing fairly simple rules you can get easily get complex behavior. By starting with the containers, and then working your way to the content I have much less to worry about since most of the content takes care of itself without much more intervention from the developer.

If your someone who already has a well established, static width layout, its going to be difficult to establish a well behaved fluid grid system without tweaking MANY aspects of the site. Its probably why a lot of companies simply serve up an entirely different set of HTML and CSS for the site for mobile devices: Its easier to do than to rebuild their main site to scale all the way down to small screens.

An Introduction To Web Fonts

Back in the old days of the Internet, circa 10 years ago, people were just beginning to discover all the new cool things you could do with the web. Print was still around in full force in all its forms of magazines and newspapers. We even had individuals that made a living putting together and curating text based content. Over the years as more and more content has migrated to the web, one of the major limitations designers have faced is that they only had about 3-5 fonts that they could reliably use to format their text and be sure that the particular font they had chosen would exist on the users machine. Sometimes there would be variations, but those variations could never be guaranteed to render the same way in a users browser. Print was just extremely flexible and could provide a typographical brand and experience that the web simply couldn’t match.

As the web has continued to evolve through the browser wars and the waves of ‘web 2.0′ there was still very little change in the way text was shown in the browser. Over the last few years some of these issues have begun to be addressed, and there’s a growing amount of support in more modern browsers to express this new idea of web fonts. The core issue is that everyone is running on a different browser, different operating system, platform, or device, and each unique configuration has its own typographical settings, fonts, defaults and so on. Websites initially began experimenting with solutions to solve this issue by actually embedding a link to the font that the browser can recognize, download, cache, and use to render fonts it doesn’t already possess. But this also posed a problem: Type foundries don’t simply want their fonts to be embedded and freely downloadable and usable by whoever happens to come along and visit a site that uses one of their fonts. A font foundries whole business model is based around the licensing of the fonts they create, so having something ‘freely downloadable’ would never appeal to them.

As I have been doing some exploration on the latest and greatest of web technologies related to HTML5 for RECESS here at InterKnowlogy, I wanted to share two different approaches that I’ve found of companies that are exploring this somewhat new idea of web fonts. Chances are you may have even seen sites already that use this, but didn’t realize it or how they did it.

TypeKit – http://www.typekit.com

Google Web Fonts – http://www.google.com/webfonts

Each of these take two separate approaches that may or may not be viable to you as a designer / developer / company depending on your needs. TypeKit is arguably the more powerful and flexible options of these two, but is a paid service (although very reasonably priced). It has a large portfolio of professional grade fonts from many different foundries, including some many of the main fonts that are included in Adobe products (which I’m sure is a plus for many designers). They uses an internal obfuscation and customization process to protect the individual font from being used outside of the website that the license was purchased for. This has allowed them to negotiate deals with some of these foundries to license the fonts for web use through their company (and they’ve obviously been decently successful).

Google on the other hand, has opted for the freely available open source fonts. All the fonts used in its web fonts site are free to use for anything and are supported on a purely donational basis. This provides two advantages: All the fonts are freely available, and a single browser can cache a font and use it across any sites that also use that same font without redownloading it, this means there will be less overhead and a more consistent experience across sites that use Google Web Fonts. However, arguably the biggest downside is that the selection of fonts is much more limited. Google has done a excellent job of curating the available fonts it has to ensure that they meet some internal quality standards, but likely many of the industry standard fonts will never be available in Google’s catalog because of licensing issues.

There is some very cool things you could do with this, I’ve purposely left out many technical details in order to give a more general overview of web fonts. Hopefully this has been enlightening and has sparked some creative ideas for cool new things you could do with this technology.

Happy Typing!