Combining media queries with image sizes

I have a set of image sizes for WordPress that look like this:

add_image_size('1039', 1039, 697);
add_image_size('960', 960, 644);
add_image_size('800', 800, 537);
add_image_size('768', 768, 515);
add_image_size('640', 640, 429);
add_image_size('480', 480, 322);
add_image_size('320', 320, 215);
add_image_size('240', 240, 161);

So basically each defined image size has the name of it’s own width (and I forced the ‘1039’ to be the maximum allowed upload size), and these widths correspond to eight different media sizes, which I set using this:

Read More
div.container {width: 1039px;}
@media only screen and (min-width: 960px) and (max-width: 1038px) {div.container {width: 960px;}}
@media only screen and (min-width: 800px) and (max-width: 959px) {div.container {width: 800px;}}
@media only screen and (min-width: 768px) and (max-width: 799px) {div.container {width: 768px;}}
@media only screen and (min-width: 640px) and (max-width: 767px) {div.container {width: 640px;}}
@media only screen and (min-width: 480px) and (max-width: 639px) {div.container {width: 480px;}}
@media only screen and (min-width: 320px) and (max-width: 479px) {div.container {width: 320px;}}
@media only screen and (max-width: 319px) {div.container {width: 240px;}}

Now, I with this basic setting and any chosen image as background-image (with a size of 1039×697) it will just resize the div.container when a different media views it. However, I want to apply the image-sizes I added, so that it applies the correct image-size to fit the size of the media used (rather than load the huge image and resize it with CSS, it should load the image that is fitted for that resolution).

At current I use this solution:

var body = jQuery('body').css("width");
var body = parseInt(body);
var image = jQuery('.container').css("background-image");
if (body >= 1039) {
    var img_width = 1039;
    var img_height = 697;
} else if (body >= 960 && body < 1039) {
    var img_width = 960;
    var img_height = 644;
    var image = image.replace('.jpg")', '-'+img_width+'x'+img_height+'.jpg")');
} else if (body >= 800 && body <= 960) {
    var img_width = 800;
    var img_height = 537;
    var image = image.replace('.jpg")', '-'+img_width+'x'+img_height+'.jpg")');
} else if (body >= 768 && body < 800) {
    var img_width = 768;
    var img_height = 515;
    var image = image.replace('.jpg")', '-'+img_width+'x'+img_height+'.jpg")');
} else if (body >= 640 && body < 768) {
    var img_width = 640;
    var img_height = 429;
    var image = image.replace('.jpg")', '-'+img_width+'x'+img_height+'.jpg")');
} else if (body >= 480 && body < 640) {
    var img_width = 480;
    var img_height = 322;
    var image = image.replace('.jpg")', '-'+img_width+'x'+img_height+'.jpg")');
} else if (body >= 320 && body < 480) {
    var img_width = 320;
    var img_height = 215;
    var image = image.replace('.jpg")', '-'+img_width+'x'+img_height+'.jpg")');
} else if (body >= 240 && body < 320) {
    var img_width = 240;
    var img_height = 161;
    var image = image.replace('.jpg")', '-'+img_width+'x'+img_height+'.jpg")');
} else if (body < 240) {
    var img_width = 240;
    var img_height = 161;
    var image = image.replace('.jpg")', '-'+img_width+'x'+img_height+'.jpg")');
}
jQuery('.container').css("background-image", image);

And this does in fact apply the correct image for the right media, but it is fully dependent on JavaScript being enabled.

Is there some way I could achieve the same result using just CSS? Or perhaps there is a more elegant solution to this? If so I would love to hear how!

Related posts

Leave a Reply

2 comments

  1. First off, kudos to this pretty cool solution.

    I think you’re on the right track and not sure how much more you could do. You could certainly replicate the above with PHP & CSS, thus not requiring jQuery. It would require you to have an array of your sizes and just loop through them. This would be a PHP file in your /CSS directory, and can be enqueued like any other stylesheet.

    <?php
    
    // Tag as CSS file
    
    header("content-type: text/css");
    
    include '../../../../wp-load.php';
    
    ob_flush();
    
    // Pull in Sizes & Image Size Names
    
    $array = array (
        'size1' => array ( 'b_min' => '960', 'b_max' => '1039', 'img_size' => '1039' ),
        'size2' => array ( 'b_min' => '800', 'b_max' => '960', 'img_size' => '960' )
    );
    
    // Loop
    
    foreach ( $array as $size ) : 
    
        echo '@media only screen and (min-width: ' . $size->b_min . 'px) and (max-width: ' . $size->b_max . 'px) {';
    
             echo 'div.container {background-image: /* Your image url code */ }';
    
        echo '}';
    
    endforeach;
    
    ?>
    

    This would solve your reliance on javascript.

  2. Many thanks to the answer from Noel Tock, I got a solution that works great; created style.css.php inside the theme folder, which contains:

    <?php
    header('Content-type: text/css');
    global $media_sizes;
    $background = get_option('background');
    $background_height = get_option('background_height');
    $front_background = get_option('front_background');
    $back_background = get_option('back_background');
    ?>
    <?php
    foreach ($media_sizes as $size) {
        echo '@media only screen';
        if ($size['min']) {
            echo  ' and (min-width: ' . $size['min'] . 'px)';
        }
        if ($size['max']) {
            echo ' and (max-width: ' . $size['max'] . 'px)';
        }
        echo ' {' . "n";
        $back = $background['image'];
        $front_back = $front_background['image'];
            $front_back = str_replace('.jpg', '-'.$size['min'].'x'.$size['height'].'.jpg', $front_back);
        $back_back = $back_background['image'];
            $back_back = str_replace('.jpg', '-'.$size['min'].'x'.$size['height'].'.jpg', $back_back);
        echo '.content {width: '.$size['min'].'px; height: '.$size['height'].'px;}' . "n";
        echo '.wrapper {width: '.$size['min'].'px; height: '.$size['height'].'px;}' . "n";
        if ($size['min'] > 480) {
            echo '.container#front {min-height: '.($size['height']+75).'px; background-image: url("'.$back.'");}' . "n";
            echo '.container#back {min-height: '.($size['height']+125).'px; background-image: url("'.$back.'");}' . "n";
        } else {
            echo '.container#front {background-image: url("");}' . "n";
            echo '.container#back {background-image: url("");}' . "n";
        }
        echo '.container#front .wrapper .content {background-image: url("'.$front_back.'");}' . "n";
        echo '.container#back .content {background-image: url("'.$back_back.'");}' . "n";
        echo '}' . "n";
    }
    ?>
    

    Which outputs the following:

    @media only screen and (min-width: 1039px) {
        div.container {background: url("example-1039x697.jpg");}
    }
    @media only screen and (min-width: 960px)and (max-width: 1038px) {
        div.container {background: url("example-960x644.jpg");}
    }
    @media only screen and (min-width: 800px)and (max-width: 959px) {
        div.container {background: url("example-800x537.jpg");}
    }
    @media only screen and (min-width: 768px)and (max-width: 767px) {
        div.container {background: url("example-768x515.jpg");}
    }
    @media only screen and (min-width: 640px)and (max-width: 639px) {
        div.container {background: url("example-640x429.jpg");}
    }
    @media only screen and (min-width: 480px)and (max-width: 479px) {
        div.container {background: url("");}
    }
    @media only screen and (min-width: 320px)and (max-width: 319px) {
        div.container {background: url("");}
    }
    @media only screen and (min-width: 240px)and (max-width: 239px) {
        div.container {background: url("");}
    }
    

    And to get it into WordPress I used the following in functions.php:

    function example_vars($public_query_vars) {
        $public_query_vars[] = 'example_vars';
        return $public_query_vars;
    }
    add_filter('query_vars', 'example_vars');
    function example_dynamic_css(){
        $css = get_query_var('example_vars');
        if ($css == 'true'){
            include_once (TEMPLATEPATH . '/style.css.php');
            exit;
        }
    }
    add_action('template_redirect', 'example_dynamic_css');
    

    And in header.php:

    <link rel="stylesheet" href="<?php bloginfo('url'); ?>/?example_vars=true" type="text/css" media="screen" />
    

    And this all results in the Media Queries being dynamically generated using options from the database, and completely without JavaScript.