Unobtrusive Dropdown Page Changer

Published by Chris Coyier

Using a <select> dropdown menu to create navigation isn't as common as it once was, but it's still around. It got ripped on pretty good for being an inaccessible / obtrusive. Indeed a lot of the scripts you'll find out there for creating a menu like this are this way. Bummer. Let's make one that works with OR without JavaScript!

View Demo

The OBTRUSIVE Way

<form>
    <select onchange="window.open(this.options[this.selectedIndex].value)">
        <option value="">Go to page...</option>
        <option value="http://css-tricks.com/">CSS-Tricks</option>
        <option value="http://digwp.com/">Digging Into WordPress</option>
        <option value="http://quotesondesign.com/">Quotes on Design</option>
    </select>
</form>

Inline JavaScript... it works, but only if JavaScript is enabled. Without, you'll have a dropdown menu that does absolutely nothing.

The UNOBTRUSIVE Way

<form id="page-changer" action="" method="post">
    <select name="nav">
        <option value="">Go to page...</option>
        <option value="http://css-tricks.com/">CSS-Tricks</option>
        <option value="http://digwp.com/">Digging Into WordPress</option>
        <option value="http://quotesondesign.com/">Quotes on Design</option>
    </select>
    <input type="submit" value="Go" id="submit" />
</form>

Pretty similar, but no inline JavaScript. Instead we give the form and ID we will use later to target. The form now POSTs to itself, and we have added a submit button, so the form is functional. The select now has a name value, so when the submit button is pressed, it will POST a value.

At the very top of our page, we'll check for a POST value from that form. If it is there, we'll redirect the page to that value.

<?php
	if (isset($_POST['nav'])) {
		 header("Location: $_POST[nav]");
	}
?>

No JavaScript needed at all, the page redirect is handled entirely via server-side PHP. NOTE: this is just the way-simplified PHP. You should probably sanitize that submitted value before passing it to the header function (esp. if running PHP prior to 4.4.2 or 5.1.2) to prevent "header injection" attacks.

We can make it behave identically to the obtrusive method though, with just a few lines of jQuery.

  1. Hide the submit button.
  2. When the select is changed...
  3. Redirect to value of option
$(function() {

    $("#submit").hide();

    $("#page-changer select").change(function() {
        window.location = $("#page-changer select option:selected").val();
    })

});

View Demo

Update

Reader David Vandenbroek writes in:

I found that using:

<select onChange="window.open(this.options[this.selectedIndex].value)"> 

opens a Popup warning dialog, and if allowed, a new window on iPhone/iPad when iOS Safari has the setting 'Block Pop-ups' set to OFF. When the setting is set to ON, nothing happens.

To avoid both undesirable behavior, I used :

<select onChange="window.location.replace(this.options[this.selectedIndex].value)"> 

instead.