skip to Main Content

First of all, if there’s a better way, I’m open to suggestions.

I am allowed to change frontend, but not backend (CMS code). Every subpage of the website has an image that is loaded at the top of the page, just bellow navigation bar (after header.php). I can choose the image in CMS and it’s path is stored in database.

So let’s say an image (1920×1080) is named “image.jpg”. I need to load a resized image (640×360), which I generically named “image.mob.jpg” (and stored in the same place on server as original “image.jpg”) when image is loaded on a mobile device (really when screen width is less or equal 640px – I chose the number, perhaps it would be better to use 480px or 360px).

What I currently do

HTML

<body>
    ...

    <?php
        ...
        while ($row = mysqli_fetch_array($result)) {
            if (isset($_SESSION['screen_width']) && ($_SESSION['screen_width'] <= 640)) {
                // change "path/to/image.jpg" to "path/to/image.mob.jpg"
                $row['image'] = substr($row['image'], 0, -4).".mob".substr($row['image'], -4);
            } ?>

    <div class="image" style="background-image: url('<?=$row['image']?>)"> ... </div>
    ...

    <?php
        if (isset($_SESSION['screen_width']) AND isset($_SESSION['screen_height'])) {
            // echo 'Screen width: ' . $_SESSION['screen_width'];
        } else if (isset($_REQUEST['width'])) {
            $_SESSION['screen_width'] = $_REQUEST['width'];
            header('Location: ' . $_SERVER['PHP_SELF']);
        } else {
            echo '<script type="text/javascript">window.location.href = window.location.href+"?width="+screen.width;</script>';
        }
        // echo $_SESSION['screen_width'] = "<script>document.write(screen.width)</script>"; ?>

</body>

This is somewhat simplified but basically what happens is this. On first visit, there is no width stored in $_SESSION so it loads the big “image.jpg”. But before it actually loads it, it already executes javascript and reloads the page with $_GET variable width in the URL. All visits but the first already have width stored in session, so the URL is always SEO friendly again. Also image path is renamed and the site loads “image.mob.jpg” if screen width is 640px at most.

This works perfectly.

The problem is I need to have all site URLs SEO friendly at all times, so it’s not allowed to have it “https://seo-friendly.url?=width={screen.width}”, even if only just once.

As you can see in the last commented line I also tried with echo $_SESSION['screen_width'] = "<script>document.write(screen.width)</script>";, but obviously it doesn’t work on first page load since all PHP is executed before any JavaScript.

How do I solve this with AJAX (I need the whole code, cause I’m to dumb to understand other’s internet answers sigh) or if there is any better alternative.

Thank you in advance.

2

Answers


  1. Chosen as BEST ANSWER

    While the answer of @avcajaraville is very useful in general, it is the comment of @Paflow that helped me find the solution. No JavaScript involved.

    HTML

    <?php
        ...
        while ($row = mysqli_fetch_array($result)) {
            $mobile_image_path = substr($row['image'], 0, -4).".mob".substr($row['image'], -4);
            $image_id = "banner-image-" . $row['id_banner']; ?>
    
    <style>
        #<?=$image_id?> {
            background-image: url('<?=$row['image']?>');
        }
        @media (max-width: 640px) {
            #<?=$image_id?> {
                background-image: url('<?=$mobile_image_path?>');
            }
        }
    </style>
    <div class="image" id="<?=$image_id?>"> ... </div>
    

    I first used <style type="text/css" scoped>, but then I read scoped is deprecated and using just <style> inside of <body> is allowed.

    Not the fanciest way, but it works!


  2. As @Paflow pointed out, to do this in PHP is an unnecessary hassle and not the recommended or suited way of doing it.

    It is close to virtually impossible to get the viewport on an HTTP GET request. There are certain hacky ways of achieving this, but they need some sort of extra requests via JS.

    Your best option is to use HTML.

    srcset will have you covered!

    I would suggest something like:

    <img srcset="/image.jpg 640w" sizes="100vw" src="/image.mob.jpg" alt="Alt attribute. Fill me!">
    

    This will, by default load you image.mob.jpg image, which will be served then as a performant base image, and if your browser supports srcset and the viewport is bigger than 640px, you will get the /image.mob.jpg image.

    Say you want more sizes, then all you have is to add them to srcset attribute and specify different sizes:

    <img srcset="/image-huge.jpg 1990w, /image-big.jpg 1440w, /image.jpg 640w" sizes="100vw" src="/image.mob.jpg" alt="Alt attribute. Fill me!">
    

    MDN responsive images

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search