Using HTML, CSS, and Javascript For Everything
To be honest, working in Objective-C and using the rich set of Cocoa APIs is difficult for me. I wasn’t a computer science major in school and never learned much about pointers or header files (thanks to 3 quarters of Java that I never used again) so it’s all a brand new landscape. I’ve learned new programming languages on my own before but they were higher-level constructs unlike C and Obj-C.
I downloaded the iPhone SDK the day it was unveiled and spent 5 hours reading about Cocoa and Obj-C on Apple’s Developer site. I absorbed it like a sponge, reading through all Apple-supplied example apps line by line trying to understand their magic. I put some views together, made some things happen, but had tremendous difficulty moving ideas in my head into code using a language I’ve never worked with, and I got frustrated.
It was frustrating mainly because I can do nearly anything I want to do inside a browser — any design, any user interaction scenario. I’ve been using CSS to create interfaces on the Web since 2002, HTML & Javascript since the late 90s. A web page is my canvas and I feel no limitation to what I can create. I rarely get bogged down in implementation details when creating something new on the Web, I mainly just dream it up and start making it work, thanks most recently to jQuery making Javascript fun again.
One of the first things I did after downloading the iPhone SDK was create a little application that loaded an HTML file from within the bundle into a UIWebView. This allowed me to use HTML, CSS, and Javascript to create something that loaded locally (aka, very quickly) and ran inside of a native iPhone application. After I became a little more comfortable with Cocoa, I wrote some hackish code that 1) was notified whenever a link was clicked, 2) stopped the new URL from loading, and 3) instead called a particular native method based on the string which returned its results by using stringByEvaluatingJavaScriptFromString to send it back to the HTML page. This allowed me to do some cool things like use JavaScript to call a native Cocoa method and then manipulate the results of that call. For desktop-based OS X apps, this is trivial as you can access the WebView directly via a WebScriptObject, but in the iPhone SDK there’s no such thing. I had to jump through some serious hoops to get JS talking to Cocoa, but in the end, it worked.
And that got me thinking.
Many people are unaware that HTML & CSS are used in popular desktop-based applications, in such ways that you’d probably never know they were being used unless you looked hard enough. Here’s a quick list of some apps that use HTML & CSS in interesting ways:
- Apple Mail — When you’re reading an email message, you’re reading it in a WebView. Many emails come through as HTML nowadays so it only makes sense to render the message directly as HTML. This is how Apple can do such innovative things with message templates — it’s all HTML & CSS.
- Help — In OS X, most applications display their Help pages (accessible via the Help menu in the menubar) as HTML.
- Safari/WebKit — I use the Web Inspector all day long when debugging Javascript, and it blew me away when I realized the entire thing is written in HTML, CSS, and Javascript. If you want to see some of the most precise and interesting CSS & Javascript you’ve likely ever seen, right-click within the Web Inspector and go to “Inspect Element” to view the source code of the Web Inspector itself.
- Firefox — One of the most interesting uses of CSS happens to be staring you in the face right now if you’re using Firefox. The entire interface of Firefox (toolbars, buttons, Find, etc.) are all styled using CSS applied to XUL, and XML-based interface definition language. When you use Find to search for text inside of a web page, the action that pops up the little Find box on the bottom of the window is actually just a Javascript call to change the
displayfrom none to block, just like you’ve used a hundred times before. This is actually what makes writing a Firefox plugin so appealing to web developers, because in the end you’re using CSS and Javascript to build your design and functionality. - Dashboard Widgets — You probably already knew that OS X Dashboard Widgets are just HTML, CSS, and Javascript, but you didn’t, go check them out again and see the level of interface detail you can achieve with stuff you already know how to use. Hint: if you view the package contents of a Widget’s bundle you can dive into the HTML, CSS, and Javascript code of the Widget to see how it works its magic. I’d highly recommend doing this for some of Apple’s beautiful widgets.
Use What You Know
The only reason that the list of desktop-based usage of HTML & CSS is so high is because Apple’s open source rendering engine WebKit is baked into OS X, allowing you to load an HTML file into your Cocoa application without breaking a sweat. Almost 5 years ago someone wrote a tutorial to build a web browser with one line of Cocoa code, so people have been using web-based display languages within desktop apps for a long time.
Over the years, WebKit has gotten a lot more powerful and its new Javascript engine is the fastest in the business. If you pack HTML, CSS, and Javascript into your application bundle and load it locally into a WebView, depending on the complexity of your code, it renders only a touch slower than if you built it using Interface Builder. Matt Gemmell even put out some code that lets you change your desktop-based application’s interface live by swapping CSS files.
This kind of stuff just blows me away. Design your interface using XML/HTML & CSS, hook up your behaviors to Cocoa using the WebScriptObject (call Cocoa from Javascript) and then only call Cocoa when you need to do some heavy lifting. Bake it into a desktop-based application by using a WebView, compile, and deploy.
I’ve been looking back on the ideas I had a few months ago that I struggled to reproduce using Obj-C and Cocoa and now feel confident that I can build them using what I already know. The idea isn’t a 3D adventure game or a photo manipulation app, it’s just something that’s useful, and I think using HTML & CSS to build it into a native app would be a perfect way to turn it into reality.
rafael mumme # —
can you add your source code to this post?
Mike Rundle # —
Source code for which concept/example?
rafael mumme # —
the UIWebView and JS talking to Cocoa. thanks.
rafael mumme # —
did you have any problem running jQuery with the iPhone? like, memory problems or errors. I just don’t feel that it is a good idea to embed jQuery there. Safari does have hardware accelerated animations with CSS and document.querySelector. I wish jQuery could release a special library just for the iPhone.
Mike Rundle # —
Hey Rafael, no problems running jQuery on the iPhone. It’s not a huge library (if you’re using the minified version, lightweight) but I’d recommend not using animations or anything like that when programming JS for the iPhone. It just can’t handle it.
Also, I’ve talked with John Resig behind jQuery and he said that jQuery v1.3 will support native querySelector syntax for browsers that support it, so it’ll figure out if it exists and use that version if the browser has it. Should be fast!
Kevin Bell # —
I think if you could post the source code to your original use case of use then everyone would be grateful for this.
Eli James # —
Wow this is amazingm, Mike. I never knew so many apps used CSS! Good observation.
Kyle # —
I am with you on using this methodology. Have you, by any chance, used XML/XSLT in your UIWebView? I can get a page to render just fine in Mobile Safari, but as soon as I hook up the same exact URL inside a UIWebView, all I see is the raw XML come back. Any ideas?
Mike Rundle # —
Hey Kyle, no I haven’t used XSLT translation on the iPhone, but I have worked with it in the past, which is why this is so odd. I’m just not sure. Maybe post to the webkit web development mailing list and see if you get an answer?
Kyle # —
Never mind. I am an idiot! Somehow, I was using some old third-party code to load the UIWebView. This code was setting the “MIMEtype” to “html”. I am now using a regular “loadRequest” and all is good. Mental note: don’t blindly assume all third-party tutorials are 100% correct. Thanks for the reply.
DK # —
Encouraging post — since we’ve also been investigating the pros and cons of doing most/even-more of our iPhone app UI using HTML/CSS/JS in WebKit, rather than with “native” UI elements.
However, as you pointed out, the “integration points” for WebKit as provided by UIWebView seem to be much more limited than those available on regular Cocoa… so could you *please* share/describe in more detail the particulars of the “serious hoops” that you employed to get the level of JS->ObjC integration that you needed to impl various features in this way?
Some example code would be fabulous… as it’s not obvious to me how everything one might want to do could be accomplished with the one simple “link handler” callback, and then using the stringByEvaluatingJavaScriptFromString method…
So please, do tell! Thanks!
Post A Comment