Subscribe to PHP Freaks RSS

Images and WordPress

syndicated from on August 7, 2019

My new WordPress project has multiple photographs per post and as I wanted them to work in an efficient manner for multiple screen resolutions. The secret to this is the srcset and sizes attributes on the img tag.

It turns out that WordPress will create multiple sized thumbnails when you upload an image. It will also add the srcset and sizes attributes into your img tags for you if your image tag has a class of wp‑image‑{id} where {id} is the id of the image in the database.

Image sizes

The set of sizes of images that WordPress creates by default is rather small (you get widths of 150px, 300px, 768px, & 1024px). As I'm uploading 6000px wide photos, having some intermediate sizes greater than 1024 is useful to reduce the amount of data for desktop screens.

You can add new ones using the add_image_size() method which is best done after the theme is set up:

add_action('after_setup_theme', static function () {
    add_image_size('xl', 1500);
    add_image_size('2xl', 2000);
    add_image_size('3xl', 2500);
    add_image_size('4xl', 3000);
    add_image_size('5xl', 4000);
    add_image_size('6xl', 5000);

The third parameter to add_image_size() is the height constraint, which I don't set as I don't want it to be taken into account for portrait orientation pictures.

Note that even though you've added additional sizes, WordPress will ignore any bigger than 1600 pixels unless you tell it otherwise by adding a filter to max_srcset_image_width:

add_filter('max_srcset_image_width', static function($max_width){
    return $max_width < 6000 ? 6000 : $max_srcset_image_width;

If you change the set of image sizes after you've uploaded some images then you can create the new images using the wp‑cli media regenerate command or install the Regenerate Thumbnails plugin and run it from the Tools menu in your admin.

Adding wp‑image‑{id} class to posts

If you use the WordPress admin site to create your posts, then it automatically set the wp‑image‑{id} class for you on our img tags. I use MarsEdit, a desktop client that uses the XML-RPC API, for creating my articles and it doesn't set this class yet, so I needed to write a plug in for this.

To do this, we put a filter on the xmlrpc_wp_insert_post_data hook to inspect the content of the post and update if needed.

add_filter('xmlrpc_wp_insert_post_data', function ($data) {
  if ($data['post_type'] ?? '' === 'post') {
    $content = wp_unslash($data['post_content'] ?? '');

// Find all <img> tags to add the "wp-image-{id}" class if (preg_match_all('/<img.*>/im', $content, $images)) { foreach ($images[0] as $img) { // Find the url in the src attribute if (preg_match('/src="([^"]+)/i', $img, $srcList)) { // Retrieve the id for this image. $postId = attachment_url_to_postid($srcList[1]); if (!$postId) { // This image isn't in the database, so don't touch it continue; }

// Add the wp-image-{id} class if it doesn't exist for this image $list = []; if (stripos($img, 'class') === false || preg_match('/class="([^"]+)/i', $img, $list)) { $classes = $list[1] ?? ''; $hasClassAttribute = (bool)count($list);

if (!preg_match('/wp-image-([0-9]{1,10})/i', $classes)) { // wp-image-{id} class does not exist on this img $classes .= ' wp-image-' . $postId;

if ($hasClassAttribute) { // Update the img tag with the new class attribute $newImg = preg_replace('/class="[^"]*/', 'class="'.$classes, $img); } else { // Insert class attribute into the img tag $newImg = str_replace('<img ', '<img class="'.$classes.'" ', $img); } // Replace the original <img> with our updated one $content = str_replace($match, $newImg, $content); }


} } }

$data['post_content'] = wp_slash($content); }

return $data; });

Note that the post's content

Truncated by Planet PHP, read more at the original (another 3636 bytes)