0
votes

I'm using the ACF plugin with WordPress to output images. Within my functions.php file, I have two image sizes:

<?php
    add_image_size( 'full', 1024, 400, true );
    add_image_size( 'square', 540, 540, true );

To work with img srcset and ACF, I have the following helper code within functions.php:

<?php
    function responsive_image($image_id,$image_size,$max_width){

        // check the image ID is not blank
        if($image_id != '') {

            // set the default src image size
            $image_src = wp_get_attachment_image_url( $image_id, $image_size );

            // set the srcset with various image sizes
            $image_srcset = wp_get_attachment_image_srcset( $image_id, $image_size );

            // generate the markup for the responsive image
            echo 'src="'.esc_url($image_src).'" srcset="'.esc_attr($image_srcset).'" sizes="(max-width: '.$max_width.') 100vw, '.$max_width.'"';

        }
    }
?>

Within my theme, I then have:

<img <?php responsive_image(get_field( 'image' ), 'full', '1024px'); ?>  alt="<?= esc_attr( get_field('alt') ); ?>">

This outputs the following on the front-end:

<img src="test-1024x400.jpg" srcset="test-1024x400.jpg 1024w, test-300x117.jpg 300w, test-768x300.jpg 768w" sizes="(max-width: 1024px) 100vw, 1024px" alt="Image Alt">

The image cropping for this image is wide (full) at 1024px by 400px.

For mobile, I would like to switch this out to (square) 540px by 540px. I know I can achieve this by having an additional img tag with a mobile class, switching between the two images using display: none and display: block. The only downside to this method is the extra image that needs to loaded.

Is there way within the theme PHP that I can load conditional WordPress image sizes depending on the viewport?

2
You'll have a bad time trying to detect the screen resolution on the server side. Some reading here, on how you might use js to tell the server what a browser's height/width are, but it's never a given: stackoverflow.com/questions/1504459/… - Cameron Hurd
The viewport can change at any time when I resize my browser. A fully responsive site needs to handle this client-side using CSS and Javascript, the server cannot make any decisions here in any sane manner. - deceze
Thanks everyone. Looks like I'm barking up the wrong tree here and need to focus on a JS solution. - Sam
@Sam yes, JS is probably the best way to go. You can use matchMedia() and change the img src based on the result. Changing the src should trigger an image download. - apokryfos
Thanks @apokryfos, I'll look into this :) - Sam

2 Answers

1
votes

You can use some Wordpress functions that return boolean values to display different output for certain user agents.

But be warned this will return true if either a mobile phone OR a tablet is used. It cannot differentiate between the two.

https://codex.wordpress.org/Function_Reference/wp_is_mobile

A simple example:

if( wp_is_mobile() ) {
    // display your mobile/tablet related item here
} else {
    // display the desktop alternative here
}
0
votes

Ok, this is a little bit more complex. PHP is a server-side language, so you cannot get the viewpoint with it. To be able to change the site according to viewpoint, you need to use a client-side language, like JavaScript!

You don't have to create two images and show/hide them, it is easier and more efficient to change the class of the image according to the viewpoint.

HTML:

<img src="/path/to/img" class="imgs">

CSS:

.mobile {
    width: 540px;
    height: 540px;
    overflow: hidden;
    // whatever style you want for mobile view
}
.normal {
    width: 1024px;
    height: 400px;
    overflow: hidden;
    // whatever style you want for normal view
}

JS:

var cw = document.documentElement.clientWidth; // get horizontal viewpoint
var ch = document.documentElement.clientHeight; // get vertival viewpoint
if (cw <= 540 || ch <= 540) { // if it is mobile
    var images = document.GetElementByClassName('imgs'); // get all images (where class is 'imgs')
    for (var i = 0; i < images.length; ++i) {
        images[i].className = "imgs mobile"; // add class 'mobile'
    }
}
else {
    var images = document.GetElementByClassName('imgs');
    for (var i = 0; i < images.length; ++i) {
        images[i].className = "imgs normal"; // add class 'normal'
    }
}

So, basically every time, the page loads, JS checks the viewpoint and changes the class of the images accordingly.