CSTLdesign News

Ensuring Your Theme Has Retina Support

With all of the high resolution screens available today, it only makes sense that your WordPress theme includes support for displaying higher quality images. That means adding functionality to create these images on top of a way to load the right one depending on the screen resolution of the end user.

There are quite a few plugins available for regular WordPress users that will add retina support to their site. Doing a search in the WordPress plugin directory brings up these ones as the top five:

Each plugin approaches adding retina support differently, though they all pretty much use the same two components: a detection script and a retina-ready image creation function. For developers who wish to add this feature directly to their themes, the first thing you need to do is include the right JS file to detect the user’s screen resolution.


Display Detection

It only makes sense to display a higher quality image if the end user is using a retina display. For our purposes, the best way is with JavaScript. I like to use a script called retina.js by Imulus. It weighs in at only 4kb and adds all the front-end functionality you need to detect a retina display and load the right image.

Let’s Enqueue

Copy over the retina.js file into your theme’s /js folder. It needs to be in the right place in order to enqueue it.

Add the following to your theme’s functions.php file:

add_action( 'wp_enqueue_scripts', 'retina_support_enqueue_scripts' );
/** * Enqueueing retina.js * * This function is attached to the 'wp_enqueue_scripts' action hook. */
function retina_support_enqueue_scripts() { wp_enqueue_script( 'retina_js', get_template_directory_uri() . '/js/retina.js', '', '', true );
}

That’s really all you need for the detection side of things. Next comes the functions to create the higher quality images.


Creating the Images

You need to make sure that each time an image is uploaded, a higher quality version is created and stored with @2x added to the filename. The detection script will search for that suffix in order to load the retina-ready version of the image if required.

Set It Up

In order to make sure that a retina-ready image is created automatically whenever an image is uploaded, you need to hook into the appropriate WordPress filter. The correct one to use is wp_generate_attachment_metadata.

This goes in your theme’s functions.php file:

add_filter( 'wp_generate_attachment_metadata', 'retina_support_attachment_meta', 10, 2 );
/** * Retina images * * This function is attached to the 'wp_generate_attachment_metadata' filter hook. */
function retina_support_attachment_meta( $metadata, $attachment_id ) { foreach ( $metadata as $key => $value ) { if ( is_array( $value ) ) { foreach ( $value as $image => $attr ) { if ( is_array( $attr ) ) retina_support_create_images( get_attached_file( $attachment_id ), $attr['width'], $attr['height'], true ); } } } return $metadata;
}

The above function checks to see if the uploaded file is an image. If it is, then it processes it using the retina_support_create_images() function.

Make the Image

With everything in place to check if an image has been uploaded, the next thing you need is a function to process and create a retina-ready higher quality version.

This needs to also go in your theme’s functions.php file:

/** * Create retina-ready images * * Referenced via retina_support_attachment_meta(). */
function retina_support_create_images( $file, $width, $height, $crop = false ) { if ( $width || $height ) { $resized_file = wp_get_image_editor( $file ); if ( ! is_wp_error( $resized_file ) ) { $filename = $resized_file->generate_filename( $width . 'x' . $height . '@2x' ); $resized_file->resize( $width * 2, $height * 2, $crop ); $resized_file->save( $filename ); $info = $resized_file->get_size(); return array( 'file' => wp_basename( $filename ), 'width' => $info['width'], 'height' => $info['height'], ); } } return false;
}

Now a new retina-ready image will be created at double the size of the original. Plus @2x will be added to the filename so that the detection script can work its magic correctly on the front-end.

That’s pretty much all you need, though adding one extra function is a good idea in order to help clean things up whenever an image is deleted.

Clean It Up

If a user deletes an image from the Media Library you might as well trash all the extra retina-ready images that were created too.

Place this final code block into your theme’s functions.php file:

add_filter( 'delete_attachment', 'delete_retina_support_images' );
/** * Delete retina-ready images * * This function is attached to the 'delete_attachment' filter hook. */
function delete_retina_support_images( $attachment_id ) { $meta = wp_get_attachment_metadata( $attachment_id ); $upload_dir = wp_upload_dir(); $path = pathinfo( $meta['file'] ); foreach ( $meta as $key => $value ) { if ( 'sizes' === $key ) { foreach ( $value as $sizes => $size ) { $original_filename = $upload_dir['basedir'] . '/' . $path['dirname'] . '/' . $size['file']; $retina_filename = substr_replace( $original_filename, '@2x.', strrpos( $original_filename, '.' ), strlen( '.' ) ); if ( file_exists( $retina_filename ) ) unlink( $retina_filename ); } } }
}

Conclusion

It doesn’t take a lot to get your theme ready for retina support. With just a few functions and one extra JavaScript file, your users can make sure that their images will always look great on every type of screen.

If you have any comments or feedback on anything you read above, please feel free to discuss it below.