2
\$\begingroup\$

In my latest project I am using fullscreen background images for each page. I decided to write some code to fetch the different thumbnail sizes and then use it as a background for the appropriate viewport size using media queries. I also made sure that in the case of big screens the smallest image loads first so that the visitor is mostly never greeted with a blank or loading background. I set the image as the featured image of the page and then call it using this code-

$args = array(
            'post_type' => 'attachment',
            'numberposts' => 1,
            'post_status' => null,
            'post_parent' => $post->ID,
            'post_mime_type' => 'image'
            );

            $attachments = get_posts( $args );

            if ( $attachments ) :
                foreach ( $attachments as $attachment ) :
                    $img_thelargeArr = wp_get_attachment_image_src( $attachment->ID, "full");
                    $img_medArr = wp_get_attachment_image_src( $attachment->ID, "med");
                    $img_mediumArr = wp_get_attachment_image_src( $attachment->ID, "medium");

                    $img_thelarge = $img_thelargeArr[0];
                    $img_med = $img_medArr[0];
                    $img_medium = $img_mediumArr[0];
                endforeach;
            endif;

And then in the page.php (or whichever template file with full background) itself I added the following style tag to display images providing fallback for bigger screen sizes so that the background loads progressively.

<style media="screen">
 @media (min-width: 1800px) {
body { background: url(<?php echo $img_thelarge; ?>) no-repeat center center fixed;
background-size: cover; }
html.multiplebgs body { background: url(<?php echo $img_thelarge; ?>), url(<?php echo    $img_med; ?>), url(<?php echo $img_medium; ?>);
background-size: cover;
background-repeat: no-repeat; }
} 

@media (min-width: 1000px) and (max-width: 1799px) {
body { background: url(<?php echo $img_thelarge; ?>) no-repeat center center fixed;
background-size: cover; }
html.multiplebgs body { background: url(<?php echo $img_thelarge; ?>), url(<?php echo $img_med; ?>), url(<?php echo $img_medium; ?>);
background-size: cover;
background-repeat: no-repeat; }

}

@media (min-width: 400px) and (max-width: 999px) {
body { background: url(<?php echo $img_med; ?>) no-repeat center center fixed;
background-size: cover; }
html.multiplebgs body { background: url(<?php echo $img_med; ?>), url(<?php echo $img_medium; ?>);
background-size: cover;
background-repeat: no-repeat; }
}

@media (max-width: 399px) {
body { background: url(<?php echo $img_medium; ?>) no-repeat center center fixed;
background-size: cover; }
}
</style>

This works as expected but I am using this for a bunch of other page templates as well and was wondering if I can move this code to a single PHP file and reference it from each of these templates. I don't know OOP so need help to figure this out. There is only one variation in one of the templates I am using $post->ID instead of $attachment->ID.

How do I set this up as a function that can be referenced from an external PHP file in the theme folder itself? Is it possible to use JavaScript to add inline styles instead of a style tag on the pages? How do I go about this?

\$\endgroup\$
3
  • \$\begingroup\$ Your "how do I do this" questions will have to be answered on SO, Code Review is just for reviewing working code. \$\endgroup\$
    – cimmanon
    Mar 7 '14 at 15:53
  • \$\begingroup\$ I posted it on SO too. But just got a couple of downvotes and no answers. I am quite new to SE so can't understand why this is happening...I am guessing that if you review this code you can help me make it better...is that alright? \$\endgroup\$ Mar 8 '14 at 13:32
  • \$\begingroup\$ If you clearly define the problem and chop it down to just enough code to reproduce it, your question will be better received. Long questions tend to intimidate potential answerees (just don't be so brief that it is difficult to tell what you're asking for). \$\endgroup\$
    – cimmanon
    Mar 8 '14 at 14:30
2
\$\begingroup\$

If the browser doesn't support the property/value combination in its entirety, it will ignore it. There's no need to do feature detection for this.

body { background: url(<?php echo $img_med; ?>) no-repeat center center fixed; }
body { background: url(<?php echo $img_med; ?>), url(<?php echo $img_medium; ?>);
background-size: cover;
background-repeat: no-repeat; }

If you care about older Android devices, you'll want to provide prefixed versions of background-size.

Make use of the cascade! The first media query is no media query at all

body {
    background: url(<?php echo $img_medium; ?>) no-repeat center center fixed;
    -webkit-background-size: cover;
    background-size: cover;
}

@media (min-width: 400px) {
    body {
        background-image: url(<?php echo $img_med; ?>);
        background-image: url(<?php echo $img_med; ?>), url(<?php echo $img_medium; ?>);
    }
}

@media (min-width: 1000px) {
    body {
        background-image: url(<?php echo $img_thelarge; ?>);
        background-image: url(<?php echo $img_thelarge; ?>), url(<?php echo $img_med; ?>), url(<?php echo $img_medium; ?>);
    }
}

/* cut out the 1800px media query since it looked identical to the 1000px one */
\$\endgroup\$
2
  • \$\begingroup\$ Ah! that does make sense. I should get rid of the query in the first one. And haven't tested it on older android devices. Is there a site I can do that? Or is the emulator on Chrome good enough. Which devices should I target? \$\endgroup\$ Mar 8 '14 at 13:43
  • \$\begingroup\$ I've not used the Chrome emulator, but I have used the Android emulator. It is super super slow (and you need to jump through a bunch of hoops to get more than 1 version available). I find that Safari 5 (there's one for Windows) is fairly close to Android 2.3's browser. I think 2.3 is the only old one worth caring about (it had 40% of the Android share last year, not sure on current numbers). \$\endgroup\$
    – cimmanon
    Mar 8 '14 at 14:18
1
\$\begingroup\$

I'm not familiar with Wordpress, so it's just a minor note about duplication. You could extract out some duplication to a method:

function get_attachment_image($attachment, $type) {
    $img_array = wp_get_attachment_image_src($attachment->ID, $type);
    return $img_array[0];
}

Usage:

foreach ( $attachments as $attachment ) :
    $img_thelarge = get_attachment_image($attachment, "full");
    $img_med = get_attachment_image($attachment, "med");
    $img_medium = get_attachment_image($attachment, "medium");
endforeach;

Another note: If I'm right the code only uses the last attachment, therefore the foreach loop could be changed to direct access to the last element of $attachments.

And a final one: what's the difference between med and medium? Isn't med an abbreviation for medium? It's confusing, better names might help.

\$\endgroup\$
2
  • \$\begingroup\$ Ah! I should name it better. Actually med and medium are just size names I assigned. The wp_get_attachment_image() takes a size argument which I have defined elsewhere. med has a width of 500px while medium is WordPress default and has a width of 300px. \$\endgroup\$ Mar 8 '14 at 13:38
  • 1
    \$\begingroup\$ if I can shift this code to just one other PHP file then I don't there is a need for that function you are suggesting. But I agree it is much more elegant. Will try that. Thanks. \$\endgroup\$ Mar 8 '14 at 13:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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