Snippets

Daniel Shaw Background responsive images for an archive page

Created by Daniel Shaw last modified
/**
 * This is tested and works, but will most likely need to be adjusted depending on your particular set-up. Have added some comments that may help with tweaking.
 *
 * The function below will loop through all projects and generate CSS for each project image. Roughly works like this:
 *
 * - Loops through all project posts
 * - For each project, CSS is generated for the image sizes and stored in an array
 * - The CSS class for each project image needs to be unique, so the post thumbnail ID is used to help generate the CSS class name
 * - This means you'll need to set up your archive template to match the CSS class name dynamically from the post thumbnail ID
 * - When all projects have been looped through, all of the required CSS has been generated and is printed inline to the `<head>`
 *
 * Example output:
 * I have two projects with featured images attached:
 * - project 1 has an image with post thumbnail ID of 10
 * - project 2 has an image with post thumbnail ID of 20
 *
 * The generated CSS will be:
 * <style id="[stylesheet-handle]-css-inline-css">
 * .banner-10{background-image:url(https://example.com/wp-content/uploads/2021/02/project-1-500x500.jpg);}@media(min-width:75em){.banner-10{background-image:url(https://example.com/wp-content/uploads/2021/02/project-1-1600x600.jpg}}
 * .banner-20{background-image:url(https://example.com/wp-content/uploads/2021/02/project-2-500x500.jpg);}@media(min-width:75em){.banner-20{background-image:url(https://example.com/wp-content/uploads/2021/02/project-2-1600x600.jpg}}
 * </style>
 *
 * On the front end, your image containers will need to have matching CSS classes applied:
 * <div class="banner-10">Project 1</div>
 * <div class="banber-20">Project 2</div>
 */

function responsive_background_images_for_archive_page() {

    // wp_add_inline_style must reference an existing stylesheet
    wp_enqueue_style( 'theme-css', get_template_directory_uri() . '/style.css' );

    // Initialise an array to hold each loop of generated CSS.
    $projects_css = array();

    // Target all the project posts that need CSS generated.
    $args = array(
        'post_type'      => 'post',        // If your projects are a custom post type, set this value to the post type name.
     // 'category_name'  => 'projects',    // If your projects are posts with a "projects" category, set this value to the category name.
        'posts_per_page' => -1,            // Set this to a reasonable cap when live.
    );

    $projects = new WP_Query( $args );

    // Loop through all projects.
    if ( $projects->have_posts() ) {
        while ( $projects->have_posts() ) {
            $projects->the_post();

            // Get the featured image for this project.
            $featured_id = (int)get_post_thumbnail_id();

            if ( !empty ( $featured_id ) ) {
            
                // Get the featured image sizes for this project.
                $banner_s = wp_get_attachment_image_src( $featured_id, 'banner-s' )[0];
                $banner_l = wp_get_attachment_image_src( $featured_id, 'banner-l' )[0];

                // Generate the CSS for this project. Note the difference here is the CSS class name has included the post thumbnail ID to make it unique.
                $project_css = '.banner-' . $featured_id . '{background-image:url(' . esc_url ( $banner_s ) . ');}@media(min-width: 75em){.banner-' . $featured_id . '{background-image:url(' . esc_url( $banner_l ) . ');}}';

                // Store the CSS for this project before the next project loop starts
                array_push( $projects_css, $project_css );
            }
        }
    }

    /*
    echo '<pre>';
    var_dump( $archive_css );
    echo '</pre>';
    */
    // Uncommenting the above will print the final generated CSS to the front-end, might be helpful for quick testing...

    $archive_css = implode( '', $projects_css ); // wp_add_inline_style() expects a string.

    // Set the CSS inline
    wp_add_inline_style( 'theme-css', $archive_css );

}

add_action( 'wp_enqueue_scripts', 'responsive_background_images_for_archive_page' );

Comments (1)

  1. Daniel Shaw

    One more thought: adding an is_archive() check before running anything inside this function will make sure this only runs in the relevant place and doesn’t affect your single project posts (if your projects are a custom post type: is_post_type_archive(NAME_OF_YOUR_POST_TYPE) is the one to use).

HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.