9 septembre 2009


Build Web Apps for iPhone using Dashcode


So far, much mobile developer attention has been fixated on the iPhone SDK released by Apple to build native iPhone applications. This is understandable, since with the SDK you can write native iPhone apps that take full advantage of the capabilities provided by the device, such as accessing the accelerometer, the camera, as well as obtain geographical locations using Core Location.
However, building Web applications for the iPhone has advantages too. For example, there is no need to wait for approval from Apple, as in the case of hosting the applications in AppStore. Also, the tools provided by Apple makes it very easy to build Web applications that look just like native iPhone applications. And when it comes to developers' skill-sets, developing Web applications is far easier than building native applications - all you need is some Javascript skills and you are ready to go!
In this article, I will take you through the Dashcode tool provided by Apple (part of the iPhone SDK; hence you need to download it first) to build compelling Web applications for the iPhone.

Trying Out the Various Templates

When you first launch Dashcode (the easiest way to launch it is through Spotlight), you will see that Dashcode has already created some templates for you to build your Web applications quickly (see Figure 1).

Figure 1: The various templates provided by Dashcode
The best way to learn is to select each template (other than the Custom template) and examine the content of each application. When you have selected a template, examine their contents and press Command-r to test the application on the iPhone Simulator. Go ahead and have fun with each template. When you have enough fun and get yourself acquainted with the environment, come back and we shall create an iPhone Web application from scratch and you will see how each part is built.

Building the UI

Alright, now that you are back, create a new Custom project In Dashcode. Notice that by default, Dashcode created a content and a footer parts for you (see Figure 2). Parts are the various views that you seen on your Web applications, such as buttons, text, etc. For this section, you will create a simple currency convertor Web application for the iPhone.

Figure 2: The parts in the Custom template
Select each of these parts and press the delete key. We shall delete these two parts and add our own parts manually.
Using the Library (Window'Show Library), drag-and-drop a Stack Layout part to the design surface (see Figure 3).

Figure 3: Using the Library to drag and drop parts onto your application
Expand the stackLayout part and you should see that it contains two subviews - view1 and view2. Select view1 and change its size to 320px by 356px (see Figure 4) via the Inspector window (Window'Show Inspector). Do the same for view2.

Figure 4: Changing the size for view1 and view2 via the Inspector window
Double-click on view1 and rename it as mainScreen. Do the same for view2 and rename it as settings (see Figure 5).

Figure 5: Renaming the two subviews
In the Library, drag-and-drop the Rounded Rectangle Shape part onto the mainScreen view (see Figure 6).

Figure 6: Adding the Rounded Rectangle Shape part to the subview
It its Inspector window, select the Fill & Stroke tab and in the Style tab select Gradient fill (see Figure 7) and select two colors.

Figure 7: Using the gradient fill to fill the part
Select the Effects tab and check the Glass and Recess checkboxes (see Figure 8).

Figure 8: Adding glass effect to the part
Select the Metrics tab and select the Absolute layout (see Figure 9).

Figure 9: Using absolute layout for parts positioning
Add the following parts to the Rounded Rectangle Shape part (see Figure 10) and name them as shown:
  • Text
  • TextField
  • Pop-up Menu
  • Push Button

Figure 10: Adding additional parts to the subview
Select the settings subview and repeat the same steps you have performed above. Figure 11 shows the parts added to the settings subview.

Figure 11: Populating the settings subview
You are now ready to view the application on the iPhone Simulator. Press Command-r to view the application on the iPhone Simulator (see Figure 12). Notice that the application is hosted by mobile Safari on the iPhone.

Figure 12: Viewing the application on the iPhone Simulator
Notice that you can only see the mainScreen subview. To see the settings subview, you need to write some code to navigate to it from the mainScreen subview.

Coding the Application

So you are now ready to write some code. With the mainScreen subview selected, right-click on the Settings button and select Events'onclick (see Figure 13).

Figure 13: Creating an event handler for the onclick event
You will be asked to name the event handler for this event. Name it as shown in Figure 14.

Figure 14: Naming the handler for the event
Notice that the code editor now appears at the bottom of the designer (see Figure 15).

Figure 15: The code editor where you can add your code
Enter the following code:
function btnSettings_ClickHandler(event)
{
    var views = document.getElementById('stackLayout');
    var settings = document.getElementById('settings');
    if (views && views.object && settings) {
        views.object.setCurrentView(settings);
    }
}
Select the settings subview and right-click on the Save Settings button and select Events'onclick. Name the handler as btnSave_ClickHandler. Enter the following code:
function btnSave_ClickHandler(event)
{
    var views = document.getElementById('stackLayout');
    var front = document.getElementById('mainScreen');
    if (views && views.object && front) {
        views.object.setCurrentView(front, true);
    }
}
Test the application again by pressing Command-r. This time, you will be able to navigate to the settings view by tapping on the Settings button in the mainScreen subview (see Figure 16).
Figure 16. Tapping on the Settings button navigates to the settings subview

Database Access

So far, your application displays two screens where you can perform some currency conversion as well as set the exchange rates for the different currencies. For simplicity, I am going to assume that you are converting the currencies into Singapore Dollars (SGD). All the exchange rates would be based on the SGD as the base currency.
To allow the users to store their own exchange rates, you will make use of the local database feature as defined in HTML 5 (which is supported by Mobile Safari). Doing so allows users of your application to store the exchange rate locally on their iPhones.
In the main.js file, add the following lines of code for performing database operations:
var database = null;                           // The client-side database
var DB_tableName = "CurrencyKeyValueTable";    // database name
 
// Function: initDB() - Init and create the local database, if possible
function initDB()
{
    try {
        if (window.openDatabase) {
            database = openDatabase("ExchangeRatesDB", "1.0", 
                                    "Exchange Rates Database", 1000);
            if (database) {
                database.transaction(function(tx) {
                    tx.executeSql("SELECT COUNT(*) FROM " + DB_tableName, [],
                    function(tx, result) {
                        loadRates();
                    },
                    function(tx, error) {
                        // Database doesn't exist. Let's create one.
                        tx.executeSql("CREATE TABLE " + DB_tableName +
                        " (id INTEGER PRIMARY KEY," +
                        "  key TEXT," +
                        "  value TEXT)", [], function(tx, result) {
                            initRates();
                            loadRates ();
                        });
                    });
                });
            }
        }
    } catch(e) {
        database = null;
    }
}
 
// Function: initRates() - Initialize the default exchange rates
function initRates()
{
    if (database) {
        database.transaction(function (tx) {
            tx.executeSql("INSERT INTO " + DB_tableName + 
                " (id, key, value) VALUES (?, ?, ?)", [0, 'USD', 1.44]);
            tx.executeSql("INSERT INTO " + DB_tableName + 
                " (id, key, value) VALUES (?, ?, ?)", [1, 'EUR', 2.05]);
            tx.executeSql("INSERT INTO " + DB_tableName + 
                " (id, key, value) VALUES (?, ?, ?)", [2, 'AUS', 1.19]);
        });
    }
}
 
// Function: loadRates() - Load the currency exchange rates from DB
function loadRates()
{
    var element;   
    var popUpElement = document.getElementById('popupConvertTo');
 
    if (database) {
        database.transaction(function(tx) {
            tx.executeSql("SELECT key, value FROM " + DB_tableName, [],
            function(tx, result) {
                for (var i = 0; i < result.rows.length; ++i) {
                    var row = result.rows.item(i);
                    var key = row['key'];
                    var value = row['value'];
 
                    //---populate the pop-up menu part---
                    popUpElement.options[i].text = key;
                    popUpElement.options[i].value = value;
 
                    if (key == 'USD') {
                        element = document.getElementById('txtUSD');
                    }
                    else {
                        if (key == 'EUR') {
                            element = document.getElementById('txtEUR');
                        }
                        else if (key == 'AUS') {
                            element = document.getElementById('txtAUS');
                        }
                    }
                    element.value = value;
                }
            },
            function(tx, error) {
                showError('Failed to retrieve stored information from database - ' + 
                    error.message);
            });
        });
    }
    else {
        loadDefaultRates();
    }
}
 
// Function: saveRates() - Save the currency exchange rates into DB
function saveRates()
{
    if (database) {
        var elementUSD = document.getElementById('txtUSD');
        var elementEUR = document.getElementById('txtEUR');
        var elementAUS = document.getElementById('txtAUS');
 
        database.transaction(function (tx) {
            tx.executeSql("UPDATE " + DB_tableName + " SET key = 'USD', 
                value = ? WHERE id = 0", [elementUSD.value]);
            tx.executeSql("UPDATE " + DB_tableName + " SET key = 'EUR', 
                value = ? WHERE id = 1", [elementEUR.value]);
            tx.executeSql("UPDATE " + DB_tableName + " SET key = 'AUS', 
                value = ? WHERE id = 2", [elementAUS.value]);
        });
    }
    loadRates();
}
 
// Function: deleteTable() - Delete currency exchange table from DB
function deleteTable()
{
    try {
        if (window.openDatabase) {
            database = openDatabase("ExchangeRatesDB", "1.0", 
                                    "Exchange Rates Database");
            if (database) {
                database.transaction(function(tx) {
                    tx.executeSql("DROP TABLE " + DB_tableName, []);
                });
            }
        }
    } catch(e) { 
    }
}
 
// Function: loadDefaultRates() - Load the default exchange rates
function loadDefaultRates()
{
    var popUpElement = document.getElementById('popupConvertTo');
    var element = document.getElementById('txtUSD');
    element.value = "1.44";
    popUpElement.options[0].text = "USD";
    popUpElement.options[0].value = element.value;
 
    element = document.getElementById('txtEUR');
    element.value = "2.05";
    popUpElement.options[1].text = "EUR";
    popUpElement.options[1].value = element.value;
 
    element = document.getElementById('txtAUS');
    element.value = "1.19";
    popUpElement.options[2].text = "AUS";
    popUpElement.options[2].value = element.value;
}
The database code above is pretty straightforward - store the exchange rates inside the database and populate the pop-up menu part when the rates are retrieved.
Modify the load() function as follows:
//
// Function: load()
// Called by HTML body element's onload event when the Web application is ready to 
// start
//
function load()
{
    dashcode.setupParts();
 
    initDB();    
    if (!database) {
        loadDefaultRates();
    }
}
Press Command-r to test the application. When the application is loaded, the pop-up menu will now display the three different currencies (see Figure 17).
Figure 17. The pop-up menu part displaying the different currencies
When you tap on the Settings button, the exchange rates would also be displayed in the settings subview (see Figure 18).
Figure 18. The exchange rates displayed in the settings subview

Performing the Conversion

You are now ready to perform the actual conversion of the currencies. In Dashcode, select the mainScreen subview and right-click on the Convert! Button and select Events'onclick (see Figure 19).
Figure 19. Handling the onclick event for the Convert! button
Name the event handler as btnConvert_ClickHandler and code it as follows:
function btnConvert_ClickHandler(event)
{
    var amount = document.getElementById("txtAmount").value; 
    var rates = document.getElementById("popupConvertTo").value;
    var result = amount * rates;
    alert(result);
}
Press Command-r to test the application. Enter an amount and select the currency to convert. Tapping on the Convert! button will now display the amount converted (see Figure 20).
Figure 20. Try converting some currencies!

Converting your Web Application into an iPhone Native Application

Now that your application is completed, you may deploy your application onto a Web server so that users can access your application through the Safari browser on their iPhones. However, since this is a Web application, the user must have access to the Internet, or else there is no way to access your application. And since our application does not make use of any server-based data, it is a good candidate to convert into a native iPhone application. The easiest way would be to host the Web application within the Safari browser, which is represented by the WebView view in the iPhone SDK.
In this section, I will show you how you can convert an iPhone Web application into a native iPhone application.
First, deploy your Web application by clicking the Share item in Dashcode (see Figure 21). Click the Deploy button so that all the files of the application will be saved to a Web publishing directory. Take note of the Web publishing directory shown in Dashcode. It is saved in /Users//Sites/CurrencyConvertor/. You will make use of the files contained within this folder shortly.
Figure 21. Deploying a Web application in Dashcode
Launch Xcode and create a new View-based Application project. Name the project as CurrencyConvertor.
In Finder, navigate to the /Users//Sites/CurrencyConvertor/ folder and select the files shown in Figure 22.
Figure 22. All the project files created by Dashcode
Drag-and-drop all the selected files onto the Resources folder in Xcode. Xcode will prompt you with a dialog (see Figure 23). Check the Copy items into destination group's folder (if needed) checkbox and click Add.
Figure 23. Adding all the Dashcode files into the Resource folder in Xcode
Perform a global Find-and-Replace (by pressing Shift-Command-F). Search and replace the following strings with an empty string (see Figure 24):
" "Parts/"
" "Images/"
Figure 24. Replacing all instances of "Parts/" and "Images/" with an empty string
This will update the various HTML and JavaScript files that reference other files using the Parts/ and Images/ folder. Files stored in the Resources folder of your Xcode application have no directory structure when they are deployed; hence all the files are in a flat directory.
Select the files shown in Figure 25 and drag-and-drop them onto the Copy Bundle Resources (16) folder. This will ensure that all the HTML, JavaScript, CSS, and images files will be deployed together with your application.
Figure 25. Copying all the Web files into the targets folder so that they are deployed together with your application
In the CurrencyConvertorViewController.h file, add the following statements to define an outlet:
#import 
 
@interface CurrencyConvertorViewController : UIViewController {
 IBOutlet UIWebView *webView;
}
 
@property (nonatomic, retain) UIWebView *webView;
 
@end
Double-click on the CurrencyConvertorViewController.xib file to open it in Interface Builder.
Add a WebView view to the View window and control-click and drag the File's Owner item to the WebView view (see Figure 26). Select webView.
Figure 26. Connecting an outlet to a view
In the CurrencyConvertorViewController.m file, add the following statements:
#import "CurrencyConvertorViewController.h"
 
@implementation CurrencyConvertorViewController
 
@synthesize webView;
 
- (void)viewDidLoad {
 NSString *path = [[NSBundle mainBundle] pathForResource:@"index" 
                        ofType:@"html"];
 [webView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath: path 
                            isDirectory:NO] ]];
    [super viewDidLoad];
}
That's it! Press Command-r to test the application on the iPhone Simulator. The Web application is now hosted within the WebView view (see Figure 27). What you have just done is convert a Web application into a native application!
Figure 27. Running the Web application as a native iPhone application

Summary

In this article, you have seen how easy it is to build Web applications for the iPhone using the Dashcode tool included in the iPhone SDK. Not only that, you have also learned how to convert a Web applications into a native application. If you are currently building Web applications for the iPhone, drop a note below to share with us what type of applications you are building.



http://mobiforge.com/developing/story/build-web-apps-iphone-using-dashcode

Golden rules for software testing


Read these simple golden rules for software testing. They are based on my testing experiences.

Its all about finding the bug as early as possible:
  • Start the software testing process by analysing requirements long before development.
Make sure you have these 3 software testing levels
  • Integration testing (performed by IT)
  • System testing (performed by professional testers)
  • Acceptance testing (performed by business users)
Don’t expect too much of automated testing:
  • First let me state this : automated testing can be extremely useful and can be a real time saver. But it can also turn out to be a very expensive and invalid solution.
Deal with resistance:
  • If you like to be instant popular, don’t become a software tester ! You 'll find out that you are going to meet a great deal of resistance... It is very likely that you will end up being the sole defender of quality at a certain point. Other participants in the project will be tempted to go for the deadline, whatever the quality of the application is.
  • You should deal with this by reporting facts and figures in stead of opinions. It might take a while before your work colleagues appreciate the great job you're doing !
Do regression testing every new release
  • Okay, you've tested your new development successfully. Great. But do the features of the application that you didn't change still work ? You really should test this before going live.
Let real users test with real data
  • This one is obvious but who does it ?
  • You cannot beat real data.
Give defects a test severity status :
  • Critical (must have, no work around)
  • High (must have, work around possible)
  • Medium (not business critical, but wanted)
  • Low (nice to have)
Let product owners deceide if a defect is to be fixed based on business priority:
  • A bit obvious, but I've seen testers make this decision and assign business statuses
  • Actively use these statuses for reporting and follow up !
This might be the most difficult goal to achieve:
  • You should talk about exit and entry criteria with IT. When is software good enough to deliver to a test team ? Think about server errors, certain level of IT testing achieved, when and how to build...
  • Same goes for business. What quality do they expect ? Who is going to make decisions on when to go live ? Make sure it is not you. Your role should be advisory.
Focus on the software testing process, not on the tools:
  • There 's a lot of talking about test management software. Sure, they can be very helpful indeed. These tools probably will take a lot of work out of your hands... But don't forget : it 's you who has to define the testing process. No tool is going to do that for you ! Think thoroughly about how you 're going to organise your testing. You can be very successful by using basic tools like MS Excel.



From http://www.testertroubles.com/2009/05/golden-rules-for-software-testing.html

Skype for iPhone Now Available in Canada!

Remember the whole SNAFU regarding the Skype iPhone app and how it wasn't available in Canada? The only way to download Skype was to go through a US iTunes account. But that has now changed because SKYPE IS NOW AVAILABLE IN THE CANADIAN APP STORE!


That's right folks! Skype for the iPhone is now available in Canadian iTunes! Here's what Tom Yeung from Skype had to tell CBC.ca:

Skype's Canadian iPhone delay was the result of a licensing issue over how it plays sound. The application has already been available for other mobile phones, including those running Microsoft Windows, for some time.

A territorial restriction on an audio codec — a program for compressing data used specifically by the iPhone — was the sticking point that prevented Skype from rolling out to Canadians in March, at the same time as the rest of the world, Yeung said.

"Unfortunately Canada was not part of the allowed geography at the time, but that's been taken care of," he said.

So you know what this means now for Canadians?

For iPhones right out of the box you can…

-Sign up for SkypeOut credit to make Canadian/USA long distance calls for 2 cents/minute.

-Sign up for a Skype subscription plan and make unlimited calls to Canada/USA for $3/month.

-Download Skype from Canadian iTunes instead of going through US iTunes

If you have a jailbroken iPhone…

- install VoIPOver3G or 3G Unrestrictor to make Skype calls over 3G and bypass the WiFi restriction.

8 septembre 2009


Taito Tugs At Our Retro Gaming Heart Strings With Arkanoid For The iPhone And iPod Touch

arkanoid

Taito definitely knows how to make an old school gamer feel all warm and fuzzy inside. They recently released the classic Bust-A-Move for the iPhone and iPod touch, and now we have another great retro game to sink some hours into, Arkanoid.

For those of you who are old enough to remember, Arkanoid is Taito’s 1986 take on the classic Breakout brick breaking game. The iPhone and iPod touch version of Arkanoid looks and sounds just like the original, but it also sports some brand new features to keep you coming back for more.

Arkanoid features touch-based controls that allow you to control your VAUS spaceship, which acts as your paddle, by simply sliding your finger from side to side. The idea of the game is to bounce a ball against a variety of colored bricks to clear each stage. Some bricks drop random power-ups which can be activated by catching them on your paddle. The game features over 100 stages, boss battles, classic yet updated graphics and sound, three difficulty levels, and even a two-player versus mode that allows you to compete against a friend on a single device.

Being that Arkanoid is a classic arcade game, Taito has decided to give it the relatively high, yet somehow normal price of $4.99. I guess it’s a small price to pay for retro gaming goodness.

The official Arkanoid gameplay trailer is embedded below.



Related Posts


So, You Want to be a Software Programming Rock Star?


A great Google Tech Talk by Joshua Kerievsky, where he discusses some of the challenges faced by programmers, common gotchas and how Industrial Logic ’s eLearning albums can help you to improve your Programming Skills.
Some of the following topics:
  • What are ‘code smells’ i.e. bad design
  • How do you improve the design of existing code (java, C++, C#)
  • How do you write good unit tests?
  • Test Driven Development
  • How do you deal effectively with legacy code?
  • Design Patterns
ABSTRACT
Presented by Joshua Kerievsky.
Software programming rock stars test-drive their code, refactor mercilessly and deftly apply design patterns.
If youd like to get from musician to rock star status, a good place to start is Industrial Logics eLearning albums. Crafted over the past 4 years, these interactive, multimedia tracks feature challenging labs that rank your level and suggest improvements, engaging videos by experts, stimulating quizzes and an ability to ask questions and receive answers by knowledgeable practitioners.
Join Joshua Kerievsky, founder of Industrial Logic, as he guides you through his company’s state-of-the-art eLearning albums on timeless software design skills.

Agile Project Management – Self-Organisation: The Secret Sauce for Improving your Scrum Team


A ‘must watch’ Google Tech Talk by Jeff Sutherland, one of the founders of Scrum, about the ’secret’ ways to achieve ‘hyper-productivity’ in an Agile Project Mangement environment.
In this seminar, Jeff talks about the following topics:
  • Introduction to the ‘Scrum But…’ (!)
  • How to monetise improved team performance
  • Shock therapy as a strategy for booting up teams.
  • The Cosmic Stopping Problem, otherwise known as the choice uncertainty principle.
  • Punctuated equilibrium – how software systems evolve
Google Tech Talks
September 4, 2008
ABSTRACT
High performance depends on the self-organizing capability of teams. Understanding how this works and how to avoid destroying self-organization is a challenge. Until you understand complex adaptive systems and how Toyota works it is difficult to improve team velocity.
Jeff will discuss three core topics:
  1. Shock therapy as a strategy for booting up teams.
  2. The Cosmic Stopping Problem, otherwise known as the choice uncertainty principle.
  3. Punctuated equilibrium – how software systems evolve
Take advantage of these concepts and you may find a way to achieve the ultimate potential of a team. This session will be a “Deep Agile” presentation keying off topics presented to engineers at MIT.
Speaker: Jeff Sutherland
Dr. Jeff Sutherland is one of the co-creators of the Scrum software development process. He and Ken Schwaber invented Scrum in 1993. Since then he has worked with many software companies and IT organizations to extend and enhance this process.

The Difference Between Waterfall, Iterative Waterfall, Scrum and Lean Software Development (In Pictures!)


Here’s a VERY simple overview of the main differences between Waterfall Development, Iterative Waterfall Development, Scrum/Agile Development and Lean.

Waterfall Development

‘Waterfall Development’ is another name for the more traditional approach to software development.
It’s called ‘waterfall’ as this type of development is often planned using a Gantt chart – you complete one phase (e.g. planning) before moving on to the next phase (e.g. development).
In Waterfall approaches, you will rarely aim to re-visit a ‘phase’ once it’s completed. As such, you better get whatever you’re doing right the first time!
This approach is highly risky, often more costly and generally less efficient than more Agile approaches.
The main issues with this approach include:
  • You don’t realise any value until the end of the project (when you deploy) (See: Self-Funding Projects, a Benefit of Agile Software Development)
  • You leave the testing until the end, which means you’re leaving issue discovery until late in the day
  • You don’t seek approval from the stakeholders until late in the day – their requirements might have changed
  • You’re heavily reliant upon a plan, which you can/will often follow to the detriment of the end result
  • You’re heavily reliant upon a project manager driving the way – the power of one

Iterative Waterfall Development

This approach carries less risk than a traditional Waterfall approach but is still far more risky and less efficient than a more Agile approaches.
The focus is on delivering a sprint of work as opposed to a series of valuable/shippable features.
The most commonly occurring issue in this type of scenario (in my experience) is bottle necking.
For example, you deliver loads of code a little bit behind schedule (?) and you leave it until the last minute to test everything. One issue takes longer than expected to resolve, you miss your sprint deadline and you deliver nothing.
Another common symptom of this type of approach is over-commitment.  It’s really difficult to estimate the totaleffort associated with a particular User Story/Feature when approaching delivery in this phased way. 
You’re more or less forced to estimate each phase separately (e.g. estimate development separately to testing in this instance) – this doesn’t work as the phases are not separate, they’re totally intertwined.
For example, if you find an issue with the test, you must return to development. The whole team must remain focused on delivering the end goal, not the separate phases.
It’s also worth noting that velocity and burn downs are far less (if at all) useful in this type of environment – you don’t benefit from early-warning-signs as you don’t find out whether you’re on track until the end of the sprint.

Scrum Development

This approach carries far less risk than Waterfall approaches.
We focus on delivering fully-tested, independent, valuable, small features. As such, we diversify our risk – if one feature goes wrong, it should not impact another feature.
With that said, we still plan our work in iterations and we will still release at the end of each iteration.

Lean Development

Lean is very similar to Scrum in the sense that we focus on features as opposed to groups of features – however Lean takes this one step further again.
In Lean Development, you select, plan develop, test and deploy one feature (in its simplest form) before you select, plan, develop, test and deploy the next feature. By doing this, you further isolate risk to a feature-level.
In these environments, you aim to eliminate ‘waste’ wherever possible – you therefore do nothing until you know it’s necessary or relevant.
the-difference-between-waterfall-iterative-waterfall-scrum-and-lean

11 Classic CSS Techniques Made Simple With CSS3

We’ve all had to achieve some effect that required an extra handful of divs or PNGs. We should be limited to these old techniques when there’s a new age coming. This new age includes the use of CSS3. In today’s tutorial, I’ll show you eleven different time-consuming effects that can be achieved quite easily with CSS3.


CSS3? What’s that?!

I’m sure you’ve heard of CSS in general. CSS3 isn’t that much different, in terms of syntax; however, the power of CSS3 is much greater. As you’ll see in these eleven techniques, you can have multiple backgrounds, dynamically resize those backgrounds, border radiuses, text shadows, and more!
Here’s what the official (or at least, what I consider official) website of CSS3, css3.info, has to say about CSS3:
CSS3 is the new kid in the stylesheet family. It offers exciting new possibilities to create an impact with your designs, allows you to use more diverse style sheets for a variety of occasions and lots more.

What We’ll Be Covering

Here are the 11 techniques that I’ll be showing you how to recreate with CSS3. I’ll show you how to create them using CSS2 (or JavaScript), and then with CSS3 properties. Remember – these effects will only work in modern browsers that implement these CSS3 features. Your best option is to view these with Safari 4.
  1. Rounded Corners
  2. Box Shadow
  3. Text Shadow
  4. Fancy Font
  5. Opacity
  6. RGBA
  7. Background Size
  8. Multiple Backgrounds
  9. Columns
  10. Border Image
  11. Animations

1. Rounded Corners

Rounded Corners
Probably my favorite on of this list, rounded corners provide a developer with so many options. You can create a rounded corner button in seconds. My favorite thing to do is set a gradient background to repeat along the x-axis and then apply rounded corners to make a very nice looking Web 2.0 button.
You can simulate rounded corners by using four extra divs or by using JavaScript. Though, a user doesn’t see these smooth corners if they have JavaScript disabled, I think that’s fine as long as the website still functions as it should. You can read up on this method if you would prefer to use pure CSS in making rounded corners.

Classic Way

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript" src="js/jquery.corners.js"></script>
<script type="text/javascript">
$(function(){
$('.box').corners('10px');
});
</script>
<div class="box">
<!--CONTENT-->
</div>
The classical method uses jQuery along with a JavaScript plugin called Corners.

CSS3 Way

<style type="text/css">
.box {
border-radius: 10px;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
}
</style>
<div class="box">
<!--CONTENT-->
</div>
As you can see, all that you need to do is specify three CSS3 properties. Eventually, it will only be one; you have to use three now because different browsers use different property names.
View the demo.

2. Box Shadow

Box Shadow
Box shadows provide you with a very powerful tool. 99% of the time when I’m desigining, I find myself using drop shadows for something. Once again, I’ll be using a jQuery plugin to take care of the classic way because honestly, trying to figure it out with just CSS is confusing. Why should I waste my time fiddling with negative margins when there’s already something written that does the job for me? As long as my design looks fine when people have JavaScript disabled, I’m perfectly content using a jQuery plugin.

Classic Way

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript" src="js/jquery.dropShadow.js"></script>
<script type="text/javascript">
$(function(){
$('.box').dropShadow({
left: 5,
top: 5,
opacity: 1.0,
color: 'black'
});
});
</script>
<div class="box">
<!--CONTENT-->
</div>
I’m using the dropShadow plugin. Simple and what I wanted; though I would prefer to use just CSS ;) .

CSS3 Way

<style type="text/css">
.box {
box-shadow: 5px 5px 2px black;
-moz-box-shadow: 5px 5px 2px black;
-webkit-box-shadow: 5px 5px 2px black;
}
</style>
<div class="box">
<!--CONTENT-->
</div>
The values for the box shadow properties are: x-offset y-offset blur color. Much easier than importing two JavaScript files, and A LOT easier than messing around with background images and negative margins.
View the demo.

3. Text Shadow

Text Shadow
If you’ve ever read a tutorial about how to make the letterpress effect in Photoshop, you’ll know that the drop shadow effect is used. It’s really simple to create letterpressed text, just follow this tutorial at Line25 by Chris Spooner.

Classic Way

<style type="text/css">
.font {
font-size: 20px;
color: #2178d9;
}
.fonts {
position: relative;
}
.fonts .font {
position: absolute;
z-index: 200;
}
.fonts .second {
top: 1px;
color: #000;
z-index: 100;
}
</style>
<div class="fonts">
<span class="font">The quick brown fox jumps over the lazy dog.</span>
<span class="font second">The quick brown fox jumps over the lazy dog.</span>
</div>
Instead of using a jQuery plugin this time, I just used some simple CSS tricks to absolutely position the text behind the other copy of text. The only bad thing about not using CSS3 for this situation is that you will get two copies of the text if CSS is disabled.

CSS3 Way

<style type="text/css">
.font {
font-size: 20px;
color: #2178d9;
}
.font {
text-shadow: 0 1px 0 #000;
}
</style>
<span class="font">The quick brown fox jumps over the lazy dog.</span>
If you’re planning on using text shadows that are blurred (the third “option” in the text-shadow property), I don’t know how you would accomplish that with pure CSS, and no images.
View the demo.

4. Fancy Font

Fancy Font
We’ve dreamed about it for a long time now, but you can finally display “fancy fonts” on the web without relying on JavaScript. Of course this causes some issues with allowing paid fonts to be distributed over the internet. Anyhow, I present you with @font-face.

Classic Way

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript" src="js/cufon.js"></script>
<script type="text/javascript" src="js/loyal.js"></script>
<script type="text/javascript">
$(function(){
Cufon.replace('.classic .font');
});
</script>
<style type="text/css">
.font {
font-size: 20px;
}
</style>
<span class="font">The quick brown fox jumps over the lazy dog.</span>
I decided to use Cufón to replace the text. I’m not going to explain how to use it because Jeffrey has an awesome screencast already.

CSS3 Way

<style type="text/css">
@font-face {
font-family: 'Loyal';
src: url('loyal.ttf');
}
.font {
font-family: Loyal;
font-size: 20px;
}
</style>
<span class="font">The quick brown fox jumps over the lazy dog.</span>
We create a font family with @font-face and then use it as a value for font-family. Michael Owens wrote an article here about a month ago which explains @font-face quite well.
View the demo.

5. Opacity

Opacity
If you’ve visited the Envato website redesign lately, you might have noticed that there are a lot of transparent elements. Though this is achieved with transparent PNGs, you can achieve a similar effect by using the opacity property. Now, the opacity property has been around for a while, but our beloved IE has its own properties.

Classic Way

<style type="text/css">
.box {
opacity: .6; // all modern browsers (this is CSS3)
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)"; // IE 8
filter: alpha(opacity=60); // IE 5-7
}
</style>
<div class="box">
<!--CONTENT-->
</div>

CSS3 Way

<style type="text/css">
.box {
opacity: .6;
}
</style>
<div class="box">
<!--CONTENT-->
</div>
With CSS3, we just eliminated two properties that were specific to IE, isn’t that great?!
View the demo.

6. RGBA

RGBA
Everyone knows what RGB stands for (red, green, blue), but what does the A stand for? It stands for alpha, which refers to the transparency.
Other than rounded corners, RGBA is my next most used CSS3 property. Sometimes I just want to add a few light white/black background to navigation links when a user hover overs them. It’s much easier than creating a new image for each color; however, with a little PHP it makes things a lot easier.

Classic Way

Seeing as how this isn’t a PHP article, I won’t be going over the PHP. Just save this file as rgba.php and when you need a certain RGBA color, make the background “color” as url(rgba.php?r=R&g=G&b=B&a=A).
<?php
$image = imagecreatetruecolor(1, 1);
$r = (int)$_GET['r'];
$g = (int)$_GET['g'];
$b = (int)$_GET['b'];
$a = (float)$_GET['a'];
$white = imagecolorallocate($image, 255, 255, 255);
$color = imagecolorallocatealpha($image, $r, $g, $b, 127*(1-$a));
imagefill($image, 0, 0, $white);
imagefilledrectangle($image, 0, 0, 1, 1, $color);
header('Content-type: image/png');
imagepng($image);
?>
Now just apply that to a div…
<style type="text/css">
.box {
background: url(rgba.php?r=239&g=182&b=29&a=.25);
}
</style>
<div class="box">
<!--CONTENT-->
</div>

CSS3 Way

<style type="text/css">
.box {
background: rgba(239, 182, 29, .25);
}
</style>
<div class="box">
<!--CONTENT-->
</div>
View the demo.

7. Background Size

Background Size
The background size property is an amazing thing to have on your tool belt when you’re creating a liquid layout. An example of this could be when you have a background image for a container that is for the sidebar. The classic way of doing this would require tweaking to have the image repeat along the y-axis, but with CSS3 it’s like adding another background property.

Classic Way

<style type="text/css">
.box {
position: relative;
overflow: hidden;
}
.box img {
position: absolute;
top: 0;
left: 0;
width: 50%;
height: 50%;
z-index: 100;
}
.box .content {
position: absolute;
z-index: 200;
}
</style>
<div class="box">
<div class="content">
<!--CONTENT-->
</div>
<img src="http://nettuts.s3.amazonaws.com/423_screenr/200x200.jpg" alt="" />
</div>

CSS3 Way

<style type="text/css">
.box {
background: #ccc url(http://nettuts.s3.amazonaws.com/423_screenr/200x200.jpg) no-repeat;
-webkit-background-size: 50%; /* Safari */
-o-background-size: 50%; /* Opera */
-khtml-background-size: 50%; /* Konqueror */
}
</style>
<div class="box">
<!--CONTENT-->
</div>
Unfortunately, this property isn’t implemented into Firefox (V3.5.2) at the time of this writing.
View the demo.

8. Multiple Backgrounds

Multiple Backgrounds
Ah, multiple backgrounds. Now this give developers a very powerful tool. I can think of so many things that require multiple divs just to have more than one background. The most common place I can see this being helpful is in a header section of the website, but that’s just the first thing I thought of.

Classic Way

<style type="text/css">
.box {
width: 200px;
height: 150px;
background: url(images/bg.png) repeat-x;
}
.box2 {
width: 100%;
height: 100%;
background: url(images/text.png) center center no-repeat;
}
</style>
<div class="box">
<div class="box2">
<!--CONTENT-->
</div>
</div>
The classic method is pretty obvious, just wrap the div with another div and so on for each background you need. Produces lovely looking code, doesn’t it?

CSS3 Way

<style type="text/css">
.box {
width: 200px;
height: 150px;
background: url(images/text.png) center center no-repeat, url(images/bg.png) repeat-x;
}
</style>
<div class="box">
<!--CONTENT-->
</div>
The syntax is really easy to pick up on this one. All you do for the multiple backgrounds is add a comma in between each one! However, once again, this is a limited property and is only in Safari.
View the demo.

9. Columns

Columns
This is the most interesting CSS3 property I’ve come by. It’s not something you see a lot in web design. Myself, I’ve only seen newspaper-like columns once or twice; however, I love how the effect looks when done correctly. Normally you would separate the content into divs and float those divs, but I found a jQuery plugin which dynamically renders the columns.

Classic Way

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript" src="js/jquery.columnize.js"></script>
<script type="text/javascript">
$(function(){
$('.columns').columnize({
columns: 2
});
});
</script>
<style type="text/css">
.column {
padding-right: 10px;
}
.column.last {
padding: 0;
}
</style>
<div class="columns">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla elementum accumsan mi. Maecenas id dui a magna tempor pretium. Quisque id enim. Proin id tortor. Curabitur sit amet enim vitae quam pharetra imperdiet. Nulla diam ante, pellentesque eu, vestibulum non, adipiscing nec, eros. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Duis a nunc. Donec non dui a velit pulvinar gravida. Nunc rutrum libero vel tortor. Duis sed mi eu metus tincidunt ullamcorper. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. In purus lorem, aliquam ac, congue ac, vestibulum quis, felis. Aliquam non sapien.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla elementum accumsan mi. Maecenas id dui a magna tempor pretium. Quisque id enim. Proin id tortor. Curabitur sit amet enim vitae quam pharetra imperdiet. Nulla diam ante, pellentesque eu, vestibulum non, adipiscing nec, eros. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Duis a nunc. Donec non dui a velit pulvinar gravida. Nunc rutrum libero vel tortor. Duis sed mi eu metus tincidunt ullamcorper. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. In purus lorem, aliquam ac, congue ac, vestibulum quis, felis. Aliquam non sapien.</p>
</div>
I’ve added a little padding to the columns just so the text isn’t smashed up against each other.

CSS3 Way

<style type="text/css">
.columns {
-moz-column-count: 2;
-webkit-column-count: 2;
}
</style>
<div class="columns">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla elementum accumsan mi. Maecenas id dui a magna tempor pretium. Quisque id enim. Proin id tortor. Curabitur sit amet enim vitae quam pharetra imperdiet. Nulla diam ante, pellentesque eu, vestibulum non, adipiscing nec, eros. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Duis a nunc. Donec non dui a velit pulvinar gravida. Nunc rutrum libero vel tortor. Duis sed mi eu metus tincidunt ullamcorper. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. In purus lorem, aliquam ac, congue ac, vestibulum quis, felis. Aliquam non sapien.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla elementum accumsan mi. Maecenas id dui a magna tempor pretium. Quisque id enim. Proin id tortor. Curabitur sit amet enim vitae quam pharetra imperdiet. Nulla diam ante, pellentesque eu, vestibulum non, adipiscing nec, eros. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Duis a nunc. Donec non dui a velit pulvinar gravida. Nunc rutrum libero vel tortor. Duis sed mi eu metus tincidunt ullamcorper. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. In purus lorem, aliquam ac, congue ac, vestibulum quis, felis. Aliquam non sapien.</p>
</div>
There are a handful of other CSS3 column properties that you can apply, but for demonstrative purposes, I only specified the number of columns. If you’d like to learn more about these other properties, check out the multi-column page at CSS3.info.
View the demo.

10. Border Image

Border Image
I had no clue about the border image property until I upgraded to Firefox 3.5 and went to Chris Spooner’s website and saw that his post images had image borders. I personally don’t have any interest in this property, but that’s not going to stop me from explaining how to achieve it.

Classic Way

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript" src="js/jquery.borderImage.js"></script>
<script type="text/javascript">
$(function(){
$('.classic .box').borderImage('url(images/border.png) 27 27 27 27 round round');
});
</script>
<style type="text/css">
.box {
border-width: 20px;
}
</style>
<div class="box">
<!--CONTENT-->
</div>
Instead of spending the time creating multiple divs and repeating the background image around the div, I found a jQuery plugin that does the work for me. It’s called borderImage and works just like it should.

CSS3 Way

<style type="text/css">
.box {
border-width: 20px;
-webkit-border-image: url(images/border.png) 27 round;
-moz-border-image: url(images/border.png) 27 round;
border-image: url(images/border.png) 27 round;
}
</style>
<div class="box">
<!--CONTENT-->
</div>
As you can see, the border image property is a bit odd. W3 explains how it gets calculated MUCH better.
View the demo.

11. Animations

Animations
Alright, who doesn’t love to see some element gently slide to the left or fade in when you hover over something? Animations are great to increase user interface, but make sure that you don’t go over board! The only browsers that support CSS3 animations are Webkit based browsers. The only other way to display animations is to use JavaScript. I’ll be using jQuery because it’s my favorite JavaScript library (if you haven’t guessed by now).

Classic Way

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript">
$(function(){
$('.box').hover(function(){
$(this).stop().animate({
top: '20px'
}, 300);
}, function(){
$(this).stop().animate({
top: '0'
}, 300);
});
});
</script>
<style type="text/css">
.box {
position: relative;
}
</style>
<div class="box">
<!--CONTENT-->
</div>

CSS3 Way

<style type="text/css">
.box {
position: relative;
-webkit-transition: top 300ms linear;
}
.box:hover {
top: 20px;
}
</style>
<div class="box">
<!--CONTENT-->
</div>
Both of these code snippets do the same thing: slide the div 20 pixels down over the course of 300 ms. Remember, the CSS3 code only works in Webkit browsers!
View the demo.

Conclusion

There you have it: 11 CSS techniques that will become much easier with CSS3 in the (hopefully near) future. Obviously, it’ll be a while before we can 100% depend on these properties across all browsers.
Don’t forget to review these other Nettuts+ tutorials that discuss CSS3:

FitNesse: Slim Data Types

A tutorial on the data types in Slim tables.



Slim Data Types from unclebob on Vimeo.