1

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:

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 1039x697) 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!

2 Answers 2

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.

5
  • That's a great idea! Few errors in the PHP above (that's an array, not an object), but I made it into a working example, will post result in a few minutes.
    – OleVik
    Commented Jan 12, 2012 at 0:29
  • Hmmm, having some issues with getting generated data into the file. Basically, I need the php file that generates the CSS to get hold of some variables from functions.php, but how do I pass variables to the file when it is enqueued using wp_enqueue_style?
    – OleVik
    Commented Jan 12, 2012 at 1:05
  • wp-load needs to have the right path and then you'll be able to call any options you want or other data through the conventional means :)
    – Noel Tock
    Commented Jan 12, 2012 at 7:15
  • I really want to avoid the wp-load method due to the increase in server load (ottopress.com/2010/dont-include-wp-load-please). A temporary solution I've applied is hooking <style></style> into wp_head, but I am hoping for some better solution.
    – OleVik
    Commented Jan 12, 2012 at 14:40
  • Cool, there certainly are ways to reduce the above, or state it in a different area.
    – Noel Tock
    Commented Jan 12, 2012 at 15:59
1

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.