Optimizing User Experience: Customizing Drupal's Error Pages
401, 403, and 404 - we've all encountered these HTTP status codes throughout our exploration of the World Wide Web at least once in our lives. How do you feel when these error pages appear instead of what you're looking for?
Not finding what you're looking for is beyond frustrating. Therefore, these pages need to be as non-frustrating as possible to compensate for the initial disappointment and encourage users to continue browsing the website.
While error pages come included by default when building a website, the real question is: Should we leave them simple and unstyled, or should we try making the user's experience with them more engaging?
During DrupalCamp London, I discovered that many developers face the challenge of creating and customizing these pages. It all starts with designers trying to make everything engaging and non-stressful. Then, developers work to customize and bring these designs to life.
In my experience, you shouldn't just "let them be." These pages can have small, quirky elements that help users forget they didn't get their expected result - to forget and forgive the error.
Almost all my past projects have had styled error pages. I feel it's my responsibility to request designs for these pages whenever they might be overlooked.
How to Customize Error Pages in Drupal
Let's look at the different methods available:
Drupal 7 Approach
In Drupal 7, you have two main approaches:
Using the generic error template:
// page--error.tpl.php
<div class="error-page">
<?php if ($messages): ?>
<div class="messages">
<?php print $messages; ?>
</div>
<?php endif; ?>
<div class="error-content">
<?php print render($page['content']); ?>
</div>
</div>
2. Creating specific templates for each error type using a hook in your theme:
// template.php
function YOURTHEME_preprocess_page(&$variables) {
// Get the current HTTP status code
$status = drupal_get_http_header("status");
if ($status == "404 Not Found") {
// Create template suggestion for 404
$variables['theme_hook_suggestions'][] = 'page__404';
}
elseif ($status == "403 Forbidden") {
// Create template suggestion for 403
$variables['theme_hook_suggestions'][] = 'page__403';
}
elseif ($status == "401 Unauthorized") {
// Create template suggestion for 401
$variables['theme_hook_suggestions'][] = 'page__401';
}
}
Then create specific template files:
// page--404.tpl.php
<div class="error-404">
<h1>Page Not Found</h1>
<p>Sorry, but the page you were looking for could not be found.</p>
<?php print theme('search_block_form'); // Optional: Add a search form ?>
</div>
// page--403.tpl.php
<div class="error-403">
<h1>Access Denied</h1>
<p>You don't have permission to access this page.</p>
<?php if (!$logged_in): ?>
<?php print drupal_render(drupal_get_form('user_login_block')); ?>
<?php endif; ?>
</div>
You can then style these templates using your theme's CSS:
.error-404, .error-403 {
text-align: center;
padding: 50px 20px;
max-width: 600px;
margin: 0 auto;
}
.error-404 h1, .error-403 h1 {
font-size: 48px;
color: #e74c3c;
margin-bottom: 20px;
}
.error-404 p, .error-403 p {
font-size: 18px;
line-height: 1.6;
color: #555;
}
By implementing these customizations, you can create error pages that not only inform users about what went wrong but also provide a better user experience with helpful options like search functionality or login forms when appropriate.
Remember to clear your theme registry cache after adding new template files for Drupal to recognize them in bash
drush cc all
Drupal 8+ Approach
For Drupal 8 and above, the implementation is different and more structured. Here's how to do it:
1. First, create a theme suggestion in your THEMENAME.theme file:
/**
* Implements hook_theme_suggestions_page_alter().
*/
function THEMENAME_theme_suggestions_page_alter(array &$suggestions, array $variables) {
$route_name = \Drupal::routeMatch()->getRouteName();
if ($route_name == 'system.403') {
$suggestions[] = 'page__403';
}
if ($route_name == 'system.404') {
$suggestions[] = 'page__404';
}
}
2. Create your Twig templates for the error pages:
{# page--404.html.twig #}
{% extends "page.html.twig" %}
{% block content %}
<div class="error-page error-404">
<h1>{{ 'Page Not Found'|t }}</h1>
<div class="error-message">
<p>{{ 'The requested page could not be found.'|t }}</p>
</div>
{% if search_form %}
<div class="search-block">
{{ search_form }}
</div>
{% endif %}
</div>
{% endblock %}
{# page--403.html.twig #}
{% extends "page.html.twig" %}
{% block content %}
<div class="error-page error-403">
<h1>{{ 'Access Denied'|t }}</h1>
<div class="error-message">
<p>{{ 'You do not have permission to access this page.'|t }}</p>
</div>
{% if not logged_in %}
<div class="login-block">
{{ drupal_block('user_login_block') }}
</div>
{% endif %}
</div>
{% endblock %}
Add your CSS styling:
/* error-pages.css */
.error-page {
text-align: center;
padding: 4rem 2rem;
max-width: 800px;
margin: 0 auto;
}
.error-page h1 {
font-size: 3rem;
color: #e74c3c;
margin-bottom: 1.5rem;
}
.error-message {
font-size: 1.2rem;
line-height: 1.6;
color: #555;
margin-bottom: 2rem;
}
.search-block,
.login-block {
max-width: 400px;
margin: 2rem auto;
padding: 1rem;
background: #f8f9fa;
border-radius: 4px;
}
For more advanced customization, you can also create a custom controller:
// src/Controller/CustomErrorController.php
namespace Drupal\your_module\Controller;
use Drupal\Core\Controller\ControllerBase;
use Symfony\Component\HttpFoundation\Response;
class CustomErrorController extends ControllerBase {
public function error404() {
$build = [
'#theme' => 'error_404',
'#search_form' => \Drupal::formBuilder()->getForm('Drupal\search\Form\SearchBlockForm'),
];
return $build;
}
public function error403() {
$build = [
'#theme' => 'error_403',
'#login_form' => \Drupal::formBuilder()->getForm('Drupal\user\Form\UserLoginForm'),
];
return $build;
}
}
Don't forget to clear the cache after making these changes:
drush cr
Remember these important points:
- Always test your error pages in a development environment first
- Make sure your error pages maintain your site's branding
- Include helpful navigation options
- Consider adding a search functionality
- Make the error message clear but friendly
- Provide clear next steps for users
These customizations will help create a better user experience even when things go wrong. The key is to turn a potential frustration point into an opportunity to help users find what they're looking for or discover something new on your site.
I am sure there might be other ways to do this, but these are the methods I usually use and so far, they’ve never failed me.
So what is your favorite method of customizing an error page?