Why HTML5?

I was recently asked to qualify why I had “upgraded” a website to utilise HTML5. All I had actually done was throw in a few semantic tags where it seemed appropriate and remove some unnecessary attributes. The client was concerned that the spec wasn’t complete and even suggested using HTML5 tags with an XHTML strict doctype. This was my response:

The HTML5 specification is different to your typical software specification. The W3C is no innovator: it does not lay down rules for browser vendors to follow. Vendors lead the way and their technology ideas are ultimately accepted, rejected, or tweaked to become part of the W3C specification. It’s highly unlikely the HTML5 specification will ever be fully complete. The only point when it could happen is when vendors and the W3C draw a line in the sand and move onto HTML6 (or whatever they name the next standard). If you wait for the final HTML5 specification, you’ll miss out.

http://blogs.sitepoint.com/2010/07/20/5-reasons-why-you-can-use-html5-today/

To say it’ll never be complete is a little pessimistic. Some experts in the industry believe it could be complete as soon as 2012. You get the idea though.

In terms of what the site is doing with HTML5 we’re not actually leveraging much of what HTML5 has to offer. Firstly we’re saving bandwidth by omitting attributes that all browsers already assume default values for, like the script type=”text/javascript” and stylesheet type=”text/css” attributes. Not to mention the new doctype, which is completely backwards compatible with existing doctypes in that it invokes standards mode in all browsers. Actually, in terms of your website it would be better to use a HTML5 doctype than an XHTML strict doctype, since the page is being served as text/html content-type by Apache, which is incorrect – the correct content-type for XHTML documents being application/xhtml+xml.

The second, and only other feature of HTML5 we’re actually using is semantic tags (http://bit.ly/1CzNqy). These allow us to create a document that is more accessible, in terms of search engine optimisation and for use of assistive technologies like screen readers. By using semantic tags instead of generic containers such as the div tag, our document is easier to understand when viewed by tools that don’t “see” page styles i.e. the design and layout of the page. For example, if your business name is within a paragraph tag it is likely to get lost in other content and not be returned in search engine results. But if you put it within a heading 1 tag, search robots know to give it more importance. Obviously this example doesn’t involve any HTML5 tags, but you should easily be able to see how the same principle can be applied to the new HTML5 elements, and how this principle will gain more and more importance as HTML5 becomes more widely adopted.

…and that is really the idea behind HTML5, everything that is being proposed, is being done so in a) a backwards compatible way and b) to cement features that already exist in one form or another. Pragmatically, that is what makes it viable to use features of HTML5 right now. Most existing browsers treat unknown tags as a generic HTML inline element and they can be styled to suit purpose.

Your one and only concern should be that there is a bug in IE 6, 7 and 8 that means they don’t recognise HTML5 tags. Fortunately there is a workaround, although it requires JavaScript to be enabled. If your visitor is using IE, without JavaScript enabled, your site will look differently to how it would normally look. It won’t make the site inaccessible, but some stylistic properties won’t be applied to page elements, so the page will appear a bit more like a text document than a website. Globally, I’ve seen stats showing that between 0.4% and 7% of browsers have JavaScript turned OFF. Potentially a very small percentage of your web traffic – which will probably be even less considering it only effects IE users, but it depends on your audience. Check your webstats and make a judgement call. For the majority of the time, the benefits outweigh the cost of supporting the fringe cases and I would recommend using HTML5 on your website now, as I have done for a number of clients I have worked with recently.

Modernizr progressives or exceptions?

Modernizr, what an interesting tool you are. How do I use your class names in my CSS files? You’ve given me a choice and I’m not sure what to use:

.multiplebgs div p {
  /* properties for browsers that
     support multiple backgrounds */
}
.no-multiplebgs div p {
  /* optional fallback properties
     for browsers that don't */
}

There are two ways to view this, bottom up, and top down. They both have their advantages and disadvantages, and I’m going to attempt to highlight these for you, so you can make your own decision.

Bottom up

For the “bottom up” way of doing things, we define a lowest common denominator. A set of styles that will work with all the browsers your website is designed to target. The intersection of all the features of all your browsers, if you want to put it that way. From here, we use Modernizr to progressively enhance the user’s browsing experience for browsers that support particular features. An example may help:

a.btn {
  background:transparent url(../img/btn-red.gif) no-repeat scroll 0 0;
  padding:5px;
  display:inline-block;
  width:40px;
}
.borderradius a.btn {
  background-color:red;
  background-image:none;
  border-radius:5px;
}

The advantages being:

  • A clearly defined baseline that works on all browsers we’re coding for
  • If we aren’t able to determine client features (because for example, Modernizr is not available: the CDN is down, or the client doesn’t have JavaScript enabled) we know that the baseline styles will be used and will ensure the site looks acceptable regardless

The disadvantages are:

  • We end up writing more and more CSS as we utilise new features that become available
  • It doesn’t encourage a particularly forward thinking coding practice. You’re essentially coding for the browser with the lowest feature set
  • If you want to change the baseline styles because of a redesign or perhaps your baseline is raised, you’re probably going to have to change overridden styles in the progressive enhancement style blocks as well

Top down

The “top down” approach is where we define styles for new browsers, and then use the “no-” prefix classes to define exceptions for browsers that don’t support the feature we’re exploiting. e.g.

a.btn {
  border-radius:5px;
  background-color:red;
  padding:5px;
  display:inline-block;
  width:40px;
}
.no-borderradius a.btn {
  background:transparent url(../img/btn-red.gif) no-repeat scroll 0 0;
}

We’re forward thinking, assuming everyone viewing our site is using these great new features and coding in fallbacks for the exceptions to the rule. Our view is that one day, all browsers will support the styles we’re using…and we’re adding in exceptions for in the mean time. The advantages are:

  • We end up writing less CSS, as we don’t have to override properties we’ve previously declared that the browser doesn’t understand
  • Our mindset is altered slightly, encouraging us to make use of and exploit new browser features that allow us to code and prototype faster
  • As our browser baseline increases, it’s really easy to remove exceptions that are no longer used

The disadvantages are:

  • We’re totally relying on Modernizr and the browser having JavaScript enabled. Without JavaScript the “no-” prefixed classes are not added to the <html> element and the browser is left trying to style things that aren’t supported or use style declarations that don’t exist (as far as the browser knows).

Well, sort of. You could always use the “no-js” class on the <html> element which Modernizr normally removes and replaces with “js” (to indicate JavaScript is available). You’d define your styles as above, but then define a lowest common denominator style set, for when you don’t know what features a browser does or doesn’t support. That’s kind of overkill though.

So, that’s basically it. When I first thought about it my gut reaction was to sit in the bottom up camp, but after thinking about it, and considering the audience for the project I’m working on it makes more sense to use the top down approach. Especially now that I’ve written it down like this. I’m hoping it’ll help others to make the right decision.

How to use CakePHP Session data in your Model validate rules

CakePHP models don’t allow you to access the session object. It is argued that this isn’t the MVC way. I tend to agree. Your controller should really pass any needed session data to the model…somehow.

My use case is that my model needs to validate that when a new user is created, it is given a “group” with equal or lesser privileges than the creator’s group.

Whilst they wouldn’t be able to use the create user form to do this (as the form only lists groups they can assign), we still need to guard against it on the server as it would be trivial to submit a specially crafted POST request with a group ID of a group with higher privileges.

My model needed to access the logged in user’s group ID from the Auth component (which stores its data in the session). So that when my model data was validated, I could check for a valid group ID, based on the group ID of the current user.

I knew I needed to make use of custom validation methods, but how could I get hold of the current user’s group ID? The Auth component isn’t available in the Model, so, what could I do?

Luckily, CakePHP’s AppModel defines a function called “validates”. Which allows you to check whether a model’s data is valid, but crucially it allows you to pass custom options to be made available in the “beforeValidate” callback.

So instead of simply saving my model data to the database, I call this function, passing my current user’s group ID and THEN call save (passing it a parameter to tell it not to bother validating the data again).

In my model, I overrode the “beforeValidate” callback function, which defines (on the fly) a new validation rule: a custom validation method, that takes the current user’s group ID as a parameter. My custom validation method can then check the model data against the current user’s group ID to see if it is valid. WIN.

Below I’ve included some example code to illustrate how this works. In this example I pass the whole Session object to the custom validation function. Which is slightly overkill. I think you should really just pass the data you need. Create a model that looks something like:

class MyModel extends AppModel {

    var $validate = array(
        // Your usual validation rules for all fields
    );

    function beforeValidate($options) {
        
        if(!empty($options) && isset($options['Session'])) {
            
            $this->validate['fieldName'] = array(
                'ruleName' = array(
                    'rule' => array('validationFunction', $options['Session'])
                )
                // + your default validation rule(s) for this field
            );
            
        } else {
            
            // Either...
            unset($this->validate['fieldName']);
            // If you have no normal rules for this field
            // Or...
            //$this->validate['fieldName'] = array(
                // Your default validation rule(s) for this field
            //);
        }
    }

    function validationFunction($check, $session) {
        
        // Do your checks with session data
        return true; // or false
    }
}

You use this in your controller like so:

class MyController extends AppController {

    var $uses = array('MyModel');
    var $components = array('Session');

    function action() {
		
        if(!empty($this->data)) {

            $this->MyModel->create($this->data['MyModel']);

            // Validate, passing custom options to be made available in the beforeValidate callback
            if($this->MyModel->validates(array('Session' => $this->Session)) === true) {

                // Save, without validation
                $this->MyModel->save(null, false);
            }
        }
    }
}