Generating Responsive Background Image Sizes in PHP

I haven’t tested your code, but I recently spent a few hours hacking something together to solve the same issue — making background images set via the WordPress customizer load responsively. Feel free to use / modify the code below to your needs, and send any questions my way. I’m not a PHP expert by any measure, however.

3 things to note about the code below:

  1. I’m assuming you have already set up your customizer code, or are ok with just adding this CSS somewhere else via an echo / filter.
  2. This code uses a function to get an attachment’s ID based on its URL that was created by Micah Wood, who in turn credits this function developed by Andrey Savchenko (a.k.a. “Rarst”). I’ve included it as the second function below, but be sure to check out both links for more info.
  3. I’ve only targeted -webkit- with the pixel density, if you want to add other vendor prefixes (eg: -o-), that could be done.

Responsive Customizer Backgrounds

    /**
     * Create CSS Rules for Responsive BGs set via the WordPress Customizer.
     *
     * @uses get_attachment_id()            Gets attachment id from $img_url
     * @link https://wpscholar.com/blog/get-attachment-id-from-wp-image-url/
     *
     * @param string $selector              The css selector set via customizer
     * @param string $img_url               The attachment url set via customizer
     *
     * @return string $responsive_css       CSS rules on success, 0 on failure
     */

    function responsive_customizer_bgs($selector="", $img_url="") {

      // return var
      $responsive_css = 0;

      // get attachment id based on url (uses helper func)
      $image_id = get_attachment_id( $img_url );

      // get the src string from WP
      $srcset_string = wp_get_attachment_image_srcset( $image_id, 'full' );

      // parse srcset string into [url][int][width-or-pixel-density]
      preg_match_all(
        "/([^\s]*)\s(\d*)([w|x])/",
        $srcset_string,
        $srcset_matches,
        PREG_SET_ORDER
      );

      // check if regex match was successful
      if( is_array($srcset_matches) ) {

          // cast int string into integer
          for ($i=0; $i < count($srcset_matches); $i++) {
              $srcset_matches[$i][2] = (int) $srcset_matches[$i][2];
          }

          // sort array of sizes by integer
          usort($srcset_matches, function($a, $b) {
            return $a[2] >= $b[2] ? -1 : 1;
          });

          // indexed loop to walk multi-dimensional array returned by regex
          for ($i=0; $i < count($srcset_matches); $i++) {
              // set media query statement based pixel size or pixel density
              if ($srcset_matches[$i][3] === 'w') {
                  $media_query_match="max-width: " . $srcset_matches[$i][2] . 'px';
              } else if ($srcset_matches[$i][3] === 'x') {
                  $media_query_match="-webkit-min-device-pixel-ratio: " . $srcset_matches[$i][2];
              }

              // create css rules and add to return string
              $responsive_css .= PHP_EOL
                . '@media only screen and (' . $media_query_match . ') {' . PHP_EOL
                . '  ' . $selector . ' {' . PHP_EOL
                . '    background-image: url(' . $srcset_matches[$i][1] . ');' . PHP_EOL
                . '  }' . PHP_EOL
                . '}';

          }

          // return that beautiful responsiveness
          return $responsive_css;

      }

    }

Get Attachment ID Via URL

    /**
     * Get an attachment ID given a URL.
     * 
     * @param string $url
     *
     * @return int Attachment ID on success, 0 on failure
     */
    function get_attachment_id( $url ) {
        $attachment_id = 0;
        $dir = wp_upload_dir();
        if ( false !== strpos( $url, $dir['baseurl'] . "https://wordpress.stackexchange.com/" ) ) { // Is URL in uploads directory?
            $file = basename( $url );
            $query_args = array(
                'post_type'   => 'attachment',
                'post_status' => 'inherit',
                'fields'      => 'ids',
                'meta_query'  => array(
                    array(
                        'value'   => $file,
                        'compare' => 'LIKE',
                        'key'     => '_wp_attachment_metadata',
                    ),
                )
            );
            $query = new WP_Query( $query_args );
            if ( $query->have_posts() ) {
                foreach ( $query->posts as $post_id ) {
                    $meta = wp_get_attachment_metadata( $post_id );
                    $original_file       = basename( $meta['file'] );
                    $cropped_image_files = wp_list_pluck( $meta['sizes'], 'file' );
                    if ( $original_file === $file || in_array( $file, $cropped_image_files ) ) {
                        $attachment_id = $post_id;
                        break;
                    }
                }
            }
        }
        return $attachment_id;
    }

Leave a Comment