1
\$\begingroup\$

I wanted to create a set of functions that would allow me to easily implement images for multiple screen resolutions in my custom page templates.

WordPress offers some functionality for implementing responsive images but this assumes that the image will be 100% of the viewport with up until the maximum size of the image.

How could my code been improved?

/**
 * Returns all registered images sizes as an associative array.
 * 
 * Thanks to https://gist.github.com/eduardozulian/6467854
 */
function relative_get_all_image_sizes() {
    global $_wp_additional_image_sizes;

    $image_sizes = array();
    $default_image_sizes = array( 'thumbnail', 'medium', 'large', 'full' );

    foreach ( $default_image_sizes as $size ) {
        $image_sizes[$size] = array(
            'width'  => intval( get_option( "{$size}_size_w" ) ),
            'height' => intval( get_option( "{$size}_size_h" ) ),
            'crop'   => get_option( "{$size}_crop" ) ? get_option( "{$size}_crop" ) : false,
        );
    }

    if ( isset( $_wp_additional_image_sizes ) && count( $_wp_additional_image_sizes ) ) :
        $image_sizes = array_merge( $image_sizes, $_wp_additional_image_sizes );
    endif;

    return $image_sizes;
}

/**
 * Will return an array of img attributes of a given $attachment_id
 * 
 * $attachment_id - The attachment id of the image
 * $html_class - When given this will be included in the returned array
 * $mobile, $tablet, $desktop - viewport width or pixel value you would like the image to take up on each screen size
 * $fallback_size - This is the size that will be used for the `src` attribute
 * 
 * returns an array of attributes: src, srcset, alt, class
 * 
 */
function relative_get_img_src( $attachment_id, $html_class = '', $mobile = '100vw', $tablet = '50vw', $desktop = '33px', $fallback_size = 'full' ) {
    if ( ! is_numeric( $attachment_id ) ) {
        return false;
    }

    $available_img_sizes = relative_get_all_image_sizes();

    $attributes = array(
        'src'    => '',
        'srcset' => array(),
        'alt'    => get_post_meta( $attachment_id, '_wp_attachment_image_alt', TRUE ),
        'class'  => $html_class,
    );

    foreach ( $available_img_sizes as $name => $data ) {
        $image = wp_get_attachment_image_src( $attachment_id, $name );

        if ( ! $image ) {
            continue;
        }

        if( $name === $fallback_size ) {
            $attributes['src'] = $image[0];
        }

        $attributes['srcset'][] = $image[0] . ' ' . $image[1] . 'w';
    }

    $attributes['srcset'] = join( ', ', $attributes['srcset'] );

    $viewport_sizes = array(
        'mobile' => apply_filters( 'relative_mobile_viewport_max_width', '414px' ),
        'tablet' => apply_filters( 'relative_tablet_viewport_max_width', '1366px' ),
    );

    $attributes['sizes'] = '(max-width: ' . $viewport_sizes['mobile'] . ') ' . $mobile . ', (max-width: ' . $viewport_sizes['tablet'] . ') ' . $tablet . ', ' . $desktop;  

    return $attributes;
}

/**
 * Returns a fully formatted image element from a given attachment_id
 * 
 * Essentially a wrapper of relative_get_img_src but formats the array returned from that function into an img element.
 * For more info see relative_get_img_src
 * 
 */
function relative_get_img_element( $attachment_id, $html_class = '', $mobile = '100vw', $tablet = '50vw', $desktop = '33px', $fallback_size = 'full' ) {
    $atts = relative_get_img_src( $attachment_id, $html_class, $mobile, $tablet, $desktop, $fallback_size );

    if ( empty( $atts['src'] ) ) {
        return false;
    }

    $img = '';

    foreach($atts as $att => $val) {
        $img .= $att . '="' . $val . '" ';
    }

    return "<img {$img} >";
}


Based on the following usage:

$contact_image = get_field('contact_image', 'bdt-options');

echo relative_get_img_element( $contact_image['id'], 'round-10', '100vw', '41vw', '467px', 'ipad_m_2_3' );

I get the following:

<img src="https://example.com/img-461x307.png" srcset="https://example.com/img-150x150.png 150w, https://example.com/img-300x200.png 300w, https://example.com/img-1024x683.png 990w, https://example.com/img.png 1440w, https://example.com/img-256x171.png 256w, https://example.com/img-461x307.png 461w, https://example.com/img-768x512.png 768w, https://example.com/img-840x560.png 840w, https://example.com/img-1242x828.png 1242w, https://example.com/img-1440x960.png 1440w, https://example.com/img.png 1440w, https://example.com/img.png 1440w, https://example.com/img.png 1440w, https://example.com/img-570x380.png 570w, https://example.com/img-935x623.png 935w, https://example.com/img.png 1440w, https://example.com/img.png 1440w" alt="some alt example" class="round-10" sizes="(max-width: 414px) 100vw, (max-width: 1366px) 41vw, 467px">
\$\endgroup\$
  • \$\begingroup\$ As far as I'm aware it works in all cases. If you can see a way that it doesn't let me know and I will update \$\endgroup\$ – mrmadhat Jun 7 at 9:41
  • 1
    \$\begingroup\$ One tip: when you want to check isset() and has count(), !empty() is the way. \$\endgroup\$ – mickmackusa Jun 7 at 9:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.