Create mobile navigation header with settings integration

I’ll not answer your questions in order, but in a way that make me easy follow a logical path.

I’m assuming I should be using the wp_is_mobile();

wp_is_mobile() is a good way to go. In my experience it recognizes majority of mobile devices, and if you don’t care about an ipotetic and very low percentual of devices not be recognized, you can take it and go on.

Last point to be made, I know I could do this by modifying the get_header() function call directly but from the little bit of reading I’ve done I don’t think I want to do this. Correct me if I’m wrong!

You are perfectly right. If you modify get_header(), next time WordPress get an update your edit is lost. And I bet you don’t want that.

I believe I need to hook into the 'wp_head' or 'activate_wp_head' action hook, is this correct?

Well, not. The latter is completely unrelated, because it fires in site activation page. The first fires on regular frontend pages, but inside the tag <head>, (usually just before it is closed), but you want to output something, so it goes inside <body>, so that hook can’t help you.

Unluckily there is not standard way to implement things in body of templates, that is completely territory of theme.

However the great majority of WordPress themes use a get_header() and from OP seems that your theme makes no exception.

The possibility to act on that functions, are more than one, the first and simplest is direcly edit the template file, and where there is the get_header() change it in:

    if ( wp_is_mobile() ) {
       get_header( 'mobile' );
    } else {
       get_header();
    }

as you can see in docs, get_header() accepts an optional argument that change the file it requires. In fact, get_header() called with no arguments require a file named header.php in theme root, but if you pass a string, it requires a file named header-{$name}.php.

Passing a string you can make it load a custom file and there put everything you want to output (probably copying mostly from header.php); and you are done.

This approach needs that you act directly on template file. If you are the developer of the theme, than you can consider this approach, but if your theme comes from somewhere (downloaded, bought..) then I suggest to don’t do that, because theme can be updated by developer, and if you have edited the original files that’s a big problem.

Aside from update issue that approach needs that you have to modify all the templates that call get_header(), e.g. index.php, single.php… and all the other templates your theme provide.

As a seasoned programmer you surely know that repeating things is not a good thing.

Surely better is the child theme approach.

Few lines above, I’ve said the get_header() require header.php from theme root folder.

That’s not completely true.

If the current theme is a child theme, first that function looks for a header.php file in child theme folder, if not found there load the one in parent theme (and if not found there load a file shipped with core).

That means that if you build a child theme you can create a custom header.php, and there, thanks to a if ( wp_is_mobile() ) conditional, you can do different things for mobile devices: in this way any template will call get_header() will require your file instead of the original one.

Also, if parent theme is updated, you can get the update with no problem. The linked page in Codex should contain enough informations to make you able to build a child theme: it’s very easy, indeed.

This seems a perfect solution, but there is a possibility: you are already using a child theme, and you can’t modify it because it is developed by 3rd party, and you don’t want to loose (for good reasons) the possibility of any update.

Unluckily in WordPress you can’t create a child theme of a child theme, so your only option is build a plugin.

That will not be easy, not because build a plugin is hard, it is pretty easy indeed, the problem is that get_header() is not filterable, and your only chance is to create a sort of “fake” theme putting all templates in plugin folder and use 'template_include' filter hook to make WordPress load templates from your plugin instead of from theme.

I was forced to do something like that for a client work, and is was frustrating.


Edit 2014/10/09

Something about building a plugin for the scope.

Normally, a plugin should be independent from current theme, because if user switch theme, plugin are still active and continue to do their work.
But if a plugin, like in your case, have to contain template files, consider it independed from theme, is pretty delusive.

The way to go, is to look at all the templates file your themes has (as said, this plugin is connected to theme), but you don’t need to look at all files, but only at first level templates.

First level templates are the ones that are directly loaded by WordPress.

Look at template hierarchy scheme, first level templates are the ones mentioned there.

It’s very rare that a theme have all of them, so take note of which templates your theme is using.

Thanks to the filter 'template_include' mentioned few lines above, you can force WordPress to load another file instead of the one it normally loads.

Just a rough example. Let’s assume you visit the url for a singular post. WordPress normally loads the file single.php in your theme to show content.

If your plugin contains:

add_action( 'template_include', function( $template ) {

  if ( is_single() ) {
     $template = plugin_dir_path( __FILE__ ) . 'single.php';
  }
  return $template;

} );

The functions hooking ‘template_include’ (an anonymous function, above) receives as argument the template file WordPress is going to load, and whatever it returns will be loaded by WordPress.

In the snippet above I checked if current query is for single post and in that case load the 'single.php' file from plugin folder.

If you have to repeat for all the query types (is_page(), is_archive(), is_search() and so on), that’s overwhelming, but if in your plugin folder you have a version of all the 1st level templates your theme uses, you can do something like:

add_action( 'template_include', function( $template ) {

  $template = plugin_dir_path( __FILE__ ) . basename( $template );
  return $template;

} );

These few lines of code completely override the theme files and force WordPress to always load the templates, named in same way, but in your plugin folder, instead of in theme one.

Now, what those files in your plugin folder should contain? There you should try to write as less as possible, but it really depends on your theme.

Let’s assume the single.php from your theme contains only:

get_header();
get_template_part( 'navigation' );
get_template_part( 'content', get_post_type() );
get_sidebar();
get_footer();

This is a very good thing for you, because you can copy it in your plugin folder and modify it like so:

if ( wp_is_mobile() ) {
   require_once . plugin_dir_path( __FILE__ ) . 'mobile-header.php';
} else {
  get_header();
}
get_template_part( 'navigation' );
get_template_part( 'content', get_post_type() );
get_sidebar();
get_footer();

So almost all the content is still loaded from theme because get_header() get_template_part(), get_sidebar() and get_footer() load templates form theme folder, and you only override the header for mobile devices.

But if your theme template files contain a lot of html markup, the only way to go is copy and paste that markup in plugin templates too.

The bad things are:

  • when you switch theme, you have to completely rewrite your plugin, or if the new theme you install is not a child theme, is better delete your plugin and go for child theme way.

  • if theme is updated, your plugin will not be touched in any way, but probably, if the update have modified the markup of theme templates (that is not certain, a lot of times theme updates are for bugs in functions.php) you will probably need to update the markup in your plugin templates too.

Yes, it’s annoing, and now you know the reason of my frustration I mentioned above.


Final question, where should I put this code? I’m sure it depends on a
couple of the previous answers, which is why I asked it last!

As said above, if your current theme is not a child theme or is a child theme that you developed by yourself, the simple addition or editing of header.php will do much of the work.

Regarding the part that visualize and save the options, it can be done in one or more files required from child theme functions.php if you can go for the child theme way, otherwise it can be just one or more files of the plugin.

I want to set colors for background and font colors in the dashboard
settings area. How do I go about doing this?

I can only suggest WordPress Settings API. In linked page in Codex you should found enough informations to be able to start coding it, also have a look to the links in the “External References” paragraph, you’ll find examples and clarifications.

After you have managed to make your setting page works, you will able to get all the settings for your header with a single get_option() call and make use of them to build your custom header.