0

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?

Sam
  • 1,134
  • 2
  • 20
  • 39
  • 3
    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: http://stackoverflow.com/questions/1504459/getting-the-screen-resolution-using-php – Cameron Hurd Oct 25 '16 at 12:08
  • 1
    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 Oct 25 '16 at 12:14
  • Thanks everyone. Looks like I'm barking up the wrong tree here and need to focus on a JS solution. – Sam Oct 25 '16 at 12:16
  • 1
    @Sam yes, JS is probably the best way to go. You can use [matchMedia()](https://developer.mozilla.org/en/docs/Web/API/Window/matchMedia) and change the img src based on the result. Changing the src should trigger an image download. – apokryfos Oct 25 '16 at 12:28
  • Thanks @apokryfos, I'll look into this :) – Sam Oct 25 '16 at 12:31

2 Answers2

1

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
}
Lee
  • 3,854
  • 5
  • 19
  • 55
  • This answers my question using a PHP solution, thank you. As the solution returns a true value for tablets too, I'll be looking into a JS solution. – Sam Oct 25 '16 at 12:21
0

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.

Eilat
  • 53
  • 1
  • 5
  • 1
    This has the disadvantage of loading the same image, which is wasteful on mobile if the image is large (especially since data is often not free). – apokryfos Oct 25 '16 at 12:58
  • well, if you want to change the image instead of the class, then use 'document.getElementById("imageid").src= imgPath + imgName + ''_mobile" + imgExt' – Eilat Oct 25 '16 at 13:09