How to use a browser as a kiosk

When it comes to engaging with customers, interactive screens are an important tool to have in your arsenal. They need to be visually attractive, easy to use, and effective at conveying their message, whether that’s providing information or a particular service. For that reason, web applications are a good way of implementing such tools, because they are inherently visual and optimised for on-screen interaction. So how do you go about setting up and securing your kiosk application?

The context

You’ll find interactive screens in lots of places these days. When I visited the Warner Bros Studios last year I noticed they had several touch-screen computers dotted around, enabling visitors to explore some additional information about how they made the Harry Potter films. It was animated, styled like you’d expect a Harry Potter display to look, and was designed to be an engaging way for people to explore, and without needing an extra employee to operate it. It was a self-service kiosk.

I occasionally make kiosk applications for big shows. You know the kind of thing – events taking place at giant exhibition halls, where hundreds of companies rock up with their stands to try to sell you stuff. These days you’ll find many of them using interactive screens to grab the attention of the crowds as they pass, allowing them to engage with their brand in a more touchy-feely way. I tend to make these interfaces using web technologies, simply because they are primarily designed for on-screen interaction.

The problems

To come across as a professional kiosk, it should satisfy these criteria:

  • It should be full-screen, not showing any browser controls.
  • It should not reveal the underlying operating system.
  • It should not allow users to get out of the application.
  • It should not need staff to periodically reset it.
  • It should be completely self-explanatory, and not require a member of staff to explain how to use it.
  • It should respect people’s privacy.

Pressing F11 to enable full-screen mode in the browser is a good start, but it’s clearly not enough.

Opening your application in kiosk mode

All mainstream browsers come with a kiosk mode. The basic principle in all cases is to create a desktop shortcut with a special parameter in the target, and then make sure that shortcut is opened when the computer is started. Here is the process, assuming you’re using Chrome on Windows:

  • Right-click on an existing Chrome shortcut (e.g. in your start menu) and select Send To > Desktop (create shortcut).
  • Right-click on the new shortcut on your desktop and select Properties.
  • In the Target box, add --kiosk to the end, putting in the URL of your web application.
  • Drag the shortcut into the startup folder of your start menu.

You should now find that when you log into the computer it will automatically load up your web application in full-screen mode. Users will not be able to use the back button, see or change the URL, or open a new tab. However, other features will still work, so we’ll need to lock those down too.

Preventing people exiting kiosk mode

If your kiosk uses an external keyboard, you could easily just hit Alt-F4 to close the application, and – bingo – they’ll be looking at the desktop with free reign over pretty much anything. Not great. People could also try to print, save a bookmark, or pretty much anything else that could be done with a keyboard shortcut.

One solution here is to intercept those keypresses using something like AutoHotkey. I won’t go into too much detail here, there are plenty of resources on their website to point you in the right direction. But, essentially, you’ll want to create a little script to detect when certain combinations of keys are pressed, and do absolutely nothing with them. It will be as if those keys haven’t been pressed at all, which means that the browser/computer won’t do anything. Depending on what browser you’re using, you may have different shortcuts to intercept, so it might be worth looking up a list of keyboard shortcuts that browser uses, and intercept all of them. Don’t forget to also catch any operating system shortcuts, so anything including the Windows key or function keys. You basically only want people pressing the letter and number keys.

Another option is to use a touch-screen computer instead, and not give people access to a keyboard at all. You’ll want to deactivate any operating system gestures though. And if you want to accept user input, you may want to consider using an on-screen keyboard. I wouldn’t rely on the operating system’s built-in on-screen keyboard, because that typically gives people access to the whole keyboard, which means you’ll need to catch them with AutoHotkey. A good alternative option is jQBTK (jQuery Bootstrap Touch Keyboard), which is a little jQuery plugin that generates a keyboard using Bootstrap components, making it easy to integrate and easy to style too. It’s a shameless plug, admittedly, because I wrote that particular script! But I haven’t come across anything better yet.

Application design

There are some things to remember when actually building your web application, too. For starters, be aware of your screen resolution, because you may not want people to be scrolling like they might on a normal web page. Because you know the size of the viewport, you don’t necessarily need to worry about responsive design or even browser compatibility – as long as it works on your kiosk machine, that’s all that matters.

Here are some other brief pointers to keep in mind:

  • Don’t include links to other websites.
  • Make sure the controls are a suitable size.
  • Make sure it’s really REALLY obvious how to use it.
  • Test it beforehand, ideally with someone who has never seen it before.
  • Think about error messages – are you happy for them to appear in operating system default windows, or would it be better to have it consistently styled within your app?
  • Include time-outs, so that if someone leaves your kiosk half-way through it will automatically reset itself after a certain delay, ready for the next person. But make sure it doesn’t reset while people are still using it!

Security and privacy

Beyond stopping people from exiting your app or doing unexpected things with it, there are other security-related things to bear in mind. Since you’re not revealing the URL, you probably* don’t need to worry too much about the usual XSS or SQL-injection concerns you might have on a ‘proper’ website. But remember that people will be using your web app in a public space – do they want their actions to be visible by other people?

An example would be any sort of data collection. If you’re asking people to enter their name, email address, or indeed any personal information into your app, they will be hesitant if they think the person behind them in the queue can see what they’re putting in. So think about the size of your form elements – keep them big enough to be easily visible by the person using it, but not big enough that other people around would be able to read it.

Also remember to set autocomplete="false" on your HTML inputs, so that the browser doesn’t try to put in details that someone else has already submitted!

Finally, NEVER ask people to log in on a public screen. Imagine the havoc that could be caused if someone logged in and then forgot to log out again. Depending on the context, there may be ways of doing it, if you’re really careful. But unless it’s absolutely critical I would avoid it completely.

* Actually, you should ALWAYS think about XSS and SQL-injection. It’s good practice, even if you never expect it to be a problem in your context. You don’t want some clever-clogs coming along and manually entering something in your email form that wipes all your data.

Final remarks

Anything I’ve missed? I’m sure there must be. Do let me know in the comments whether there are any other best practices you would employ when building a kiosk app.

Animated star field on a Javascript canvas

I was watching the film Pixels the other night.  Not the best film ever (by a long way), but it did get me reminiscing about all the cool stuff I programmed when I was a lad.  Back when I made text adventure games and simple animations in QBASIC.  Back when I programmed games on my TI-83 graphical calculator during History lessons.  Ah, those were the days.

So I wondered – how easy would it be to remake some of those programs in the technology I use today?  Specifically, can I recreate my horizontally animated star field that I made in QBASIC, only this time using Javascript?

As it turns out, yes I can.

First of all, we set up a basic HTML5 page, with just a canvas  element on it.  There’s also some CSS to make sure it will work in full-screen and has a black background.

The Javascript is where it gets fun.  And I’m not using jQuery or any other helper libraries.

We set up the canvas width and height here rather than in the CSS, because otherwise it will scale rather than actually get bigger.

Next we create a few variables to hold things like our stars and settings.  You can probably guess what they’ll be used for.

Here’s the function that creates a star.

We’re setting everything to be pretty random here.  Note that Math.random()  creates a number between 0 and 1, so we’ll need to put that into context later.  We Math.sqrt()  the random number for the distance, so that it’s weighted more towards closer stars; these will move faster, so we need more of them there.  The logic in the colour is simply giving us a star that is mostly white but with a slight tint between red and yellow.  It’s worth checking out hsl() and hsla() if you haven’t already, it’s pretty useful!

Now we can initialise our stars array.

Next we’ve got a function to draw the stars.  I’ve put it in a function because we’ll be calling it multiple times shortly.

First off we clear whatever might be on the canvas already.  Modern browsers handle output buffering quite well, so we don’t need to bother about manually double-buffering to avoid the flickering.

Before we draw each star, we move it.  How far it moves depends how close it is to us, and we’re using Math.pow()  to weight it correctly.  This is the inverse of the Math.sqrt()  we used when setting the distance of the star.  We’re also transforming that 0-1 value into something relative to the canvas width.  We also check whether the star has moved off-screen, and reset it if we need to.

And then we actually draw the star on the canvas.  I’ve given it a semi-transparent stroke, to simulate a blur effect.

Finally, we call the updateStars()  function every 30 milliseconds so we get a nice smooth animation.

Here’s the final result.  You can easily change the number of stars and the speed using the variables at the top.

How to make an object oriented WordPress plugin

If you’re thinking of creating a WordPress plugin, whether small or large, for your own use or the whole world to benefit from, it’s important to start right.  Most of the example code on the WordPress documentation shows the functionalities in a procedural layout, because that makes it easier to explain.  But best practice is to use modern programming techniques – classes, inheritance, closures, and so on.

This tutorial will take you through the process of creating a very basic WordPress plugin, but created the right way.  This is partly intended to be a helpful reminder to me next time I’m creating a plugin, but hopefully others will find it useful too!

What we’ll be making

This plugin will provide an options screen in the WordPress back-end for the admin to specify how many things he has.  On the front-end, we’ll use a shortcode to display a form to ask visitors how many things they’ve got.  We’ll handle the form submission, store the number of things the visitor has in our database, and then use another shortcode to display how many things we all have in total.

It’s a pretty lame plugin, really.  But it will allow us to go through the process of making an options page, creating shortcodes, using templates, and handling form submissions.

Step 1: Naming conventions

An important thing to decide before you even put fingers to the keyboard is what to call your plugin.  Even if you’re the only person who will ever use it, you need to be sure that someone else isn’t using the same plugin name so that you don’t run into issues later.  A quick search in the plugin directory will answer your question.  And remember that it’s about the internal name, not the display name; you’ll see what I mean in a moment.  If you’ve ever asked yourself how many Daves you know, you’ll understand why unique naming is important.

First create a folder under /wp-content/plugins/  with the name of your plugin, for example /wp-content/plugins/md-things-plugin/ .  The folder name should be unique in the entire WordPress plugin ecosystem.  In theory I suppose you could use a random string here, but that would just look weird, so don’t do that.

Next, create a PHP file in that folder with the same unique name, in this case md-things-plugin.php .  For clarity it’s important that the names match, not because WordPress will get confused but because you might, or another developer who looks at the code.

Step 2: The class

Here’s our first bit of code, in md-things-plugin.php.

The comment block at the top is important, as that’s what will be displayed in your WordPress plugins page to tell everyone what the plugin is.  Technically the plugin name here doesn’t need to be unique, but it helps you be sure which plugin you’re activating!  You can probably work out what the other comments are about.

Next, we create the class, again using that unique name.  We wouldn’t want to run into issues where other plugins are using the same class name!  We’ll create a __construct()  function, which we’ll put stuff into later.  And then, finally, we simply use a variable to create an instance of the class.  The variable itself won’t be used directly, but it’s a way of making sure the class is run.

Step 3: Activate and deactivate

The first thing you do when you install a plugin is activate it.  Some plugin don’t need to do anything when they activate, but if yours does then you’ll need to catch that event and do something with it.  In our case, our plugin will need to set up a database table to store the number of things visitors have.

First off, we only want to listen out for activation/deactivation when we’re logged in as an administrator, so we’ll use is_admin()  to conditionally check.  And we’ll use register_activation_hook()  to listen out for the activation event.

There are a couple of bits of magic here.  First, notice the array in the register_activation_hook()  call.  In the WordPress documentation the first example (which is the one people read first) just has a string containing the name of the function, but since we’re using an object oriented approach our function is in a class, and using array(&$this,'activate')  is the way to do it.  It’ll go off and find the public function activate()  in the current class.  Neat!

In the activate()  function itself, we’re using the global $wpdb  object, which is how we safely access the database.  I won’t go into too much detail here on how to use the WordPress database, you can look that up yourself.  But what I do want to highlight is the dbDelta()  function.  That looks at the SQL code we’ve provided, and applies it to the database.  If the table doesn’t already exist, it makes it.  So when the plugin is activated, that table will be created too, assuming it wasn’t there already.

For deactivation it’s pretty much the same deal, but using register_deactivation_hook() .  It’s up to you whether you do anything with the database you created on activation – you may want to leave it all there, or truncate the data, or drop the table completely.  Up to you.

Step 4: The options page

This step is a little more messy, in my opinion, but I’ll try to make it clear what’s going on.  Once again, we’re only interested in the options page if we’re looking at the back-end of WordPress, so we’ll add our listener in there.

The first action uses the same technique used before of sending the event to a function within our class; I’ll show you what goes in there in a moment.

But you’ll notice that the second action we’re listening for doesn’t reference a class function, but uses a closure instead.  Why?  Personal preference really.  I didn’t see the point in creating a whole new function just for one line of code.  Keeping it in a closure doesn’t affect the functionality, and keeps the class tidy and easy to understand.  In this case, all we’re saying is that when the WP admin screen initialises we want to make sure there is a setting available for our options page to use.  Again, that will become clear later.

So, let’s look at the first action we set up, which listens for the admin_menu  action.  This allows us to add a menu item to the WordPress sidebar.  The function looks something like this:

You’ll need to refer to the documentation for add_management_page()  to see the full range of options available, but in this case we’re adding a menu item to the sidebar (as a subitem of ‘Tools’) that will be called “MD Things”, which will only be visible if the logged in user has permissions to manage_options  (so usually an Administrator).  It’s only one line, so why not put it in a closure like the other action?  Notice the last argument – we’re referring to $this , which wouldn’t work in the context of a closure.  That last bit is important, because that references another function in our class that actually displays the options page:

First of all it checks that we actually have permission to view the options page, and chucks us out if we haven’t.  It’s an unlikely scenario to have to cater for, but best to be safe.  Then we tell WordPress that our plugin uses an option variable, using get_option() .  And, finally, we show the options page itself.  This approach is my personal preference, and don’t feel you have to include the ‘.tpl’ bit in the filename if you prefer a different convention.  Here’s what options.tpl.php  looks like:

There are some styling conventions in WordPress, although I’ve found they’re not particularly well documented, so the best thing I can recommend is to look at the HTML of an existing plugin options page and replicate it.

But functionally, that’s it.  When you hit the submit button WordPress will automatically handle the form submission and save your data in the setting for this plugin.  You don’t need to worry about database access or parsing or anything… WordPress just works.

Something else that saves our bacon is that we’re saving all our settings as an array of values.  We register one option for the plugin via register_setting() , and we store all our settings as an array within that option, for example in the input above name="md_things_plugin[mythings]" .  The beauty of this is that if our plugin needed more settings, we simply add another element to the array, rather than having to create more options with register_setting() .  Nice and tidy.

Step 5: Asking for visitor input

We’re going to need a shortcode to display a form.  Again, the WordPress documentation would have you believe that this is done procedurally, but it doesn’t have to be.  I like to separate my functionality from my display, so I use template files to keep things tidy.

I’m using a closure again, because it’s tidy, but you could use a class function if you prefer.  All I’m doing here is including the template file, which looks something like this:

Now if we put that [md_things_form]  shortcode on a WordPress page or post somewhere, it will show our form.  When the form is submitted, it will be sent to WordPress’s internal admin-post.php  file, which we can hook into to process the form ourselves.  Here’s how we do that, again adding to the __construct()  function:

admin_post_  listens for post data sent to the admin-post.php  file, nopriv_  listens only to post requests that come through from someone who is not logged in, and md_things_visitor  is the identified we passed from the form submit button.  We can then route the request to a class function:

This inserts a new row in our database table, storing the value the visitor entered into the form.  I’m using intval()  to validate the input, but you might want to use something else depending on the format you expect.  Then it redirects back to the page we came from, as specified in the other input in the form (if anyone knows of a better way of doing this, let me know!).

As an added bonus, we can make that form template include a bit more information.  For instance, this bit of code would show the value our administrator put into the WordPress options page:

We can also create a static function in our class and reference it directly from the template:


Hopefully that’s given you enough to get started writing your own object oriented WordPress plugin.  If I’ve missed anything, or if you’ve spotted any mistakes, let me know in the comments below!

Controller routes in Silex

I’ve been using Laravel 4 for a while now, and occasionally Kohana too, but in my current project I’m trying out Silex.  It’s a micro-framework, which means it only gives you the bare-bones rather than bucketloads of features, but that keeps it lightweight and gives the developer a sense that they’ve actually achieved something rather than just plugging pre-made boxes together!

One of the features I was quite comfortable and familiar with was the MVC approach of having routes and controllers.  Silex, being a micro-framework intended primarily to allow an entire app to exist in one index.php file, didn’t at first seem able to do this.  However, after a little hunting around I found it was possible, and I’d like to share it here for my own reference as much as anyone else’s.

Starting point

For reference, I’m using Silex 1.2 on PHP 5.4, and I have Composer installed on my test environment.  YMMV.

Let’s assume the following directory structure:

  • root
    • public
      • index.php
    • vendor
      • autoload.php
    • composer.json

All of Silex and the Symfony libraries are in vendor, and our app currently exists just in index.php.  For the sake of demonstration we’ll use some very basic code that looks like this:

In simple terms, this sets up Silex, sets two routes, and runs.  Simple enough.  But the functionality and their associated routes are all in closures, and for a larger app this could easily get out of control.

Implementing ControllerProviderInterface

Silex includes a nice interface called  ControllerProviderInterface  which can help us out.  It requires the following to exist:

Basically, unless you have that  connect()  function and return the right thing, your class doesn’t implement the interface properly.  That’s not a bad thing though, because the  connect()  function is where all the magic happens.


First, let’s set up a namespace so we don’t run into other people’s code.  Open up composer.json and add your namespace:

I’m calling our namespace “MyApp” for the sake of demonstration.  Save the file and update with Composer:


Next, we need to create the class file we’ve just referenced.  It’s important that what we specified in composer.json actually matches our files, so pay attention, otherwise you’ll get files not being found at runtime.

We’ve told composer that our MyApp namespace can be found in /src/MyApp, so that’s where we create our class file, for demonstration purposes called MyClassController.php.

  • root
    • public
      • index.php
    • vendor
      • autoload.php
    • src
      • MyApp
        • MyClassController.php
    • composer.json

The directory needs to match what we specified in composer.json, and it’s good practice to give it the same name as our actual namespace too.

Now we can create our MyClassController.php class:

It doesn’t do anything yet, but we’ll flesh it out in a moment.  What we’ve done here is specified our namespace, made sure we can access the right components, and implemented the interface.  Now comes the fun part.

Defining routes

We’ve created a function in our class called  home() , and told the controller to route GET requests to that function.  Make sure you correctly specify the namespace and class name too.  I won’t bore you with the details of why this works (read the documentation for that), but it does.  At least, it will do once we update our index.php file to use it properly…


So instead of defining our routes in index.php, we now let the class handle the routes itself, keeping index.php clean and succinct and allowing for more complex functionality to be extracted into separate files as needed.


Putting all this together, we have the following complete files:

Now (hopefully), we’ve got exactly the same functionality we had at the start, except that it’s much more organised and arguably more powerful.


Introducing… Rockagotchi


Remember Tamagotchis?  That craze of pocket-sized digital pets that you fed and cared for in the 90s?  Well, this is one of those.  Except it’s a rock.

The idea for this project started around 15 years ago, when everyone but me had a Tamagotchi.  Being a bit of a nerd-in-the-making I decided to create my own, so with my meagre programming knowledge and a trial version of Visual Basic 2.0 I created the world’s very first Rockagotchi.  Sadly, no one but me ever saw it.  So when I suddenly remembered the idea recently I decided it was worth recreating for the 21st century.  This time I used HTML5, CSS3 and jQuery.

Go to Rockagotchi

Frequently Asked Questions

How do I use it?

Click the link above.  Providing you have a reasonably modern computer and browser (IE9 or above, or pretty much any other browser) you should be fine.  If what you see doesn’t look like the image above, you need to crawl out of the dark ages and upgrade your browser.

Once launched, give your rock a name and press the buttons on the right to interact with it.

Can I overfeed my Rockagotchi?

It’s a rock.  It doesn’t eat.

How do I increase my Rockagotchi’s happiness level?

It’s a rock.

How do I increase my Rockagotchi’s energy level?

It’s a rock.

Is it possible to kill my Rockagotchi?

It’s a rock.

I’m afraid of the dark and I’m worried that turning the lights off on my Rockagotchi might psychologically damage it.  Is there a night-light or dimmer option I can use?

Seriously.  It’s a rock.

Can I use Rockagotchi on my phone?

You can try.

How do I reset my Rockagotchi?

Press F5.  Or CTRL-R.  Or click the refresh button in your browser toolbar.  Or turn your computer off and on again.

Wait.  Does this thing actually DO anything??

No.  It’s a rock.  Deal with it.

Can I steal the code and make millions by selling it to a huge multinational company?

Erm… I’d rather you didn’t.  It’s not exactly groundbreaking code underneath anyway, so I’d be very surprised if there were “millions” involved…

If I give you an idea for a new feature, will you pay me to use it?


I’m a web developer and I’ve looked at your code.  There’s a much better way of doing it than that.  When can we expect an update?

Yes, I know it’s rather roughshod.  It was created in a hurry.  And since it makes me no money I’m in no hurry to roll out improvements.  That said, if it gives me a warm sense of developer-satisfaction then I might consider changing the code for something more beautiful or elegant.  But it’s not a priority right now.

What’s the personality profile of this so-called rock?  What is its gender?  Sexual orientation?  Favourite colour?  Nationality?

It’s a rock.


Some of you may have noticed that most of the images on my blog have been missing for some time.  Actually, if I’m honest, I very much doubt if anyone has noticed.  Let’s face it, who reads blog posts from last year?  Hmm?  Anyone?  No, I thought not.  Nonetheless, the images were missing, and it was only this evening that I managed to resolve the issue.

The problem started when I moved from my old hosting provider, PearTreeUK, to my new hosting provider, WebhostingUK.  I was determined to be clever, being a professional web developer, and decided to merge a load of old domains onto one master domain and host my blog there, so now you’ll find that, and all redirect to  Seamlessly.  Well, almost seamlessly.  The trouble was, despite all my cleverness, I forgot to download all the images on my blog before cancelling the old hosting.  Foolish fool.

So while everything worked, it looked rather bare.  For the most part it wasn’t a huge issue, but believe it or not there are actually some blog posts that Google quite likes, such as my demonstration of OpenTTD junctions, which is somewhat underwhelming without the images.

Thankfully, the folks at PearTreeUK have their heads screwed on.  I emailed them on the off-chance that they might have my old data lying around somewhere, half hoping that they didn’t (because that would be careless and unprofessional).  The reply came back positive, and thankfully it’s not unprofessional at all – they actually have a policy in place to hang onto expired accounts’ backups for several months before automatically deleting them.  Which is a very wise policy.  And it meant that they were able to provide me with a full backup of my blog, including images.  So I downloaded the images, put them in the right place, fiddled with my .htaccess file to make sure I didn’t get any straggling 404s, and hey-presto my images are back!  Feel free to take a wander through my archives if you like, to marvel at my newly-found old images.

As an extra bonus, I’m pleased to say that something else fairly significant was also recovered at the same time.  I had been writing a pregnancy diary during 2009, before Samuel’s birth, and I’d put it online (though hidden from public eyes) so that I could update it from wherever I happened to be.  It seemed like a good idea at the time.  Anyway, I kind of forgot it was there, so when I came to migrate all my websites from the old web host I completely forgot to take a backup of that diary.  Thankfully, the backup PearTree were able to send me included all that hard work.  One day I’ll finish off the last few weeks worth of entries (which are currently only in note form) and maybe make it public.  Might make an interesting read.  Maybe.

pShadow – a jQuery extension for gorgeous drop shadows

What’s pShadow?

pShadow, short for ‘paper shadow’, is a jQuery extension that adds realistic drop shadows to HTML elements, which works in Internet Explorer (IE8, IE7, IE6 with some clever trickery), Firefox, Chrome, Safari, Opera, and any other modern browser you care to mention.  It’s free to download and use, and you can see an example on the demo page.

Cut to the chase – how do I get it?

Download pShadow1.0 and unzip it somewhere.  You’ll see pshadow.js and 2 png images, and I’ve included the jQuery script too (but feel free to download it fresh from the jQuery site if you prefer).

In the <head> section of your HTML file, add the following lines:

Now all elements in your markup with the class .someElement will have a lovely drop shadow!

The options

There is more than one way to skin a cat.  By the same token, there is more than one way to use pShadow.  Below are some options you can set.

There are 2 built-in shadow types, using one of the 2 .png images bundled in the zip.  Choose which one you want to use by setting the type parameter to either ‘corners’ (default) or ‘middle’.  See the demo page to see the difference.

You can set how deep the shadow is, i.e. the vertical height of it, by setting the depth parameter to a number (assumes pixels).

You can vary the strength (i.e. the darkness) of the shadow by setting the strength parameter to a value from 1 to about 5.  See the technical stuff below for an explanation of what those numbers mean, but 1 is lightest and 5 is probably the highest you’ll need to go.

And of course you can combine those options into one array, and even chain other functions on afterwards.

How it works

Okay, here’s the more technical low-down on how this all works, and what makes it so special.

We all know that modern browsers (apart from IE anyway) support the lovely CSS3 box-shadow property.  But there are times when we need to cater for IE too, and sometimes a simple box-shadow just doesn’t cut the mustard.  The pShadow jQuery extension does what all great performers do – it masters the art of illusion.

The shadow itself is actually a .png image, carefully designed to sit on the bottom edge of an element and give impression of depth and shadow, as if the element was a piece of paper sitting on your screen.  No shadows are needed on the other edges, because the bottom shadow does all the work for you.  Your eyes do the rest and turn it into a 3-dimensional object.

pShadow uses jQuery to take (nearly) any element, or set of elements, and dynamically adds the .png image to it, positioning it carefully so that it lines up with the bottom edge of the element.  In the case of self-closing elements like <img />, pShadow adds the shadow element immediately following it in the markup, and positions it absolutely to the target element’s position on the screen.  In the case of non-self-closing elements like <div></div> the shadow is added inside it and then positioned relative to the parent.  Then it scales the width of the image to match the target object.  And, to my knowledge, that can’t all be done purely with CSS.

The darkness of the shadow (known in the code as the ‘strength’) is a quick and dirty approach but generally works well.  There is still only one .png image, but if you layer them on top of each other it gets progressively darker.  If you leave the parameter to its default setting, or set it to 1, it will place just one copy of the shadow under the element.  If you set it to 3, you’ll effectively get 3 shadows stacked on top of each other, making it darker.  By my reckoning the scale can sensibly go up to about 5, although there is technically no limit.  And if you want more control you can create your own shadow image that’s really really light and stack loads of them on top of each other, if you really want to…


No, it’s not perfect.  Yes, you can break it.  No, I can’t guarantee to be able to fix every issue you have with it.  Here are some things I’m already aware of:

  • PNG images are not totally supported in IE6, because it forgets to take transparency into account.  However, there are a number of ways to force IE6 to do transparency, so do a Google search for “IE6 transparency” and use any of the solutions there!
  • If you apply a shadow to a self-closing element like an image, and then move the position of that element, the shadow won’t follow it.  Because the shadow is positioned absolutely to where the target element was relative to the page, if you then move the target element the position of the shadow would need to be updated too.  That’s beyond the scope of pShadow at the moment.
  • If you have CSS targeting images, there’s a possibility that you might affect the shadow elements too.  I’ve tried to cancel out some typical CSS parameters, but it’s no silver bullet, so beware.
  • pShadow doesn’t take into account rounded corners, so if you’re using a hefty rounded corner on an element then the shadow might look a little odd.  Tough luck, I’m afraid.
  • Also, pShadow doesn’t currently handle nested pShadowed elements perfectly.  Hopefully that’s something I’ll find a fix for though!

Frequently Asked Questions (or at least questions that I imagine might be asked frequently)

Is pShadow free?

Yes.  It is.  And always will be.

Do I have to use jQuery?

Yes.  Technically you could achieve it all in raw Javascript, but it wouldn’t be as elegant, nor anywhere near as easy to use.  And I have no plans to convert it to use any other Javascript framework.

Can I apply pShadow to any element?

Yes.  But I can’t guarantee it’ll work in every case.  It’ll definitely work for <div>, <p>, <h1> etc, <img>, and any other element that a browser will treat as if it’s a block element like <div>.  It won’t work quite right with <input>, <textarea>, <button> yet, but that might come later.  And I’m sure you’ll all tell me if other elements don’t work either.

Can I use pShadow?

Yes.  You can use it on your personal blog.  You can use it on your company website.  You can use it on your corporate intranet.  You can use it in your web application.

However, you can’t use it on your oven.  Or your car.  Or your girlfriend.  Or your sense of pride.  Or the sunset.

What happens if I have a problem with pShadow?

Leave a comment below and I’ll see what I can do to help.  Unfortunately I have a 9 to 5 job to attend to, so I can’t provide unlimited tailored support, and you can’t employ my services either, even for money.

When is the next version of pShadow due?

It’s not.  Not as such.  This is a little personal project of mine, initially knocked up in an afternoon.  I hope to find time to tweak it as necessary, as and when people point out critical failures, but there is no roadmap for development.

Officially the end of the line

You should read this if you have previously received services from Matthew Dawkins Web Design or ChapterNine Web Design.

Matthew Dawkins Web DesignChapterNine Web Design

It’s officially over, and my what a journey it has been!  Way back in 2005 I was approached by the St Albans Diocese Youth Service and asked if would be able to design them a new website or three.  And so my freelance business began, primarily offering web design services for churches and Christian organisations.  The business grew, I took on more clients, and I started providing services such as web hosting too.

But, like all good things, it had to come to an end.  In October 2010 I got a ‘real’ job – a full time position as a web developer for another company, and my own business had to be gracefully turned off.  After a lot of dallying and helping clients out with migrations to other web hosts, today finally sees the final milestone completed.  My old websites are being taken offline and my reseller hosting package cancelled.

I would like to take this opportunity to thank everyone who I’ve had dealings with over the years who have made it all worthwhile.  Thanks to Rob for being so helpful, especially in those stressful downtime moments, and for resetting the firewall every time I blocked myself by trying to remote MySQL into something!  Thanks to Ralph giving me plenty of work to do, and for being cause for much entertainment.  Thanks to Anthony for getting me started in the hosting business.  Thanks to Liz for getting me my first job.  Thanks to Ellie for putting up with me, for bringing me cake batter at just the right moments, and for reminding me of the time.  Thanks to David for lending me your clients while you were away.  Thanks to Elliot for giving me work when times were quiet, and for looking after several of my clients when I started closing down.  Thanks to antoniojl for selling me the G5 Mac that’s been so useful the last few years.  Thanks to Phill for the opportunity to collaborate with you on a revolutionary idea.  And thanks to God for leading me down this path, for reminding me at regular intervals that I was still on the right track, for providing for me in so many different ways, and for showing me clearly when the time was right to move on.

Will I offer my services again in a freelance capacity?  Possibly.  I can’t rule it out.  But, that said, one of the lessons I learnt very early on (and had to either ignore or find ways round) was that I’m not a natural businessman.  I hate invoicing people, I find it hard to charge a realistic price for my talent, and I still don’t understand all the jargon of the Self Assessment Tax Return form.  For now, God has led me somewhere new and I’m really enjoying it, so I won’t be hurrying back to being my own boss.  But if you do have questions for me, feel free to ask, and if I get a free moment between family and church commitments I’ll try to answer!

So, for now, it’s adios, au revoir, auf wiedersehen, aloha, arrivederci, hagoonea’, tot ziens, and a fond farewell to all my old clients, colleagues, and various previously-important icons on my desktop.

Shiny and new (part 2)

Yes, this is my second post today, and with the same title, but on a completely different topic.

Some time ago, as some of my faithful readers will know, I got a new job.  That meant getting rid of… I mean, encouraging my old clients to go elsewhere for their services.  Getting everyone’s web hosting moved to new providers was a bit of a challenge, and understandably there were some people who were none too pleased at having to move at all, and others who didn’t have the first idea what might be involved.  So I’ve helped as much as I can, given that I’m no longer actually working from home.

So the time is nearly upon me where all my clients will be migrated, and all that’s left is my own sites.  At that point, I’ll need to move my own sites to a new host too, as I can’t afford the reseller package I’d been using.  An upshot of that is that I can’t really afford to be running lots of personal sites for free, as I used to through my business.  What’s needed is a careful rationalisation of my online presence, to ensure continuity and sustainability.

So here’s what’s going to happen.  ChapterNine ( will cease to exist, although I’ll keep the domain for now and just forward that on to another page on another website.  Minipix ( will also be shut down, again with the domain forwarding on elsewhere.  Now, before you all get cross and up in arms and worried that I’m shutting down my blog, I must stress that I have no intention of stopping blogging, nor of losing the last 10 years’ worth of personal history.  What’s actually going to happen is that my blog will be moved to, which will no longer serve as a business website but will be my personal website instead.  So everything you see here on will soon appear on instead.  Some of the stuff on ChapterNine will appear there too, as will some of the material currently on  It’s all a bit confusing, but it’ll make sense once it’s done – basically it’ll all be in one place instead of on three separate sites.

I’m still in the process of building the new site (I’m a web designer after all, I can’t just move it and have done with it, I’ve got design myself a completely new theme to go with it!), but I’m hoping it’ll be sorted out at some point this month.  And, as I’ve said, I’ll keep the old domain names now, so all your old bookmarks and links should continue to work.  It’ll just all appear in one shiny new website over on

Making my blog more personal

Successful bloggers, and indeed writers in most fields, will tell you that the key to success is to pick your target market and stick to it.  No surprise, then, that the most read blogs are ones where their authors talk religiously about their chosen topic, whether that be a blog about programming methods or a blog about one man’s journey to become a vintage bus driver.

In spite of this well-acknowledged fact, you’ll notice that my blog is still littered with a whole plethora of categories, covering all sorts of topics and areas of life.  I have chosen not to focus on one target audience, but to write infrequently about everything instead.

Now, finally, I’ve got round to introducing a way for you, the reader, to take control of my blog and only show the articles you’re actually interested in.