Skip to main content
Login Join
Snippet · PHP

Hero Section Video or Image Banner Shortcode Using ACF field.

Shared by Tanvir Ahmed · September 20, 2026 · @add_shortcode

1 view
Back to Snippets

By using these snippet, You can use acf field video or image as hero section banner.
first you need to create acf field project_video or project_image

then we use them to make the actually what we wanna show on hero section.

Use this shortcode to see the magic.

add_shortcode('project_background_media', 'project_background_media_shortcode');
function project_background_media_shortcode() {

    // Try the dedicated video field first
    $result = resolve_media_field('project_video', 'video');

    // Fall back to the image field (which might itself contain a video)
    if (empty($result)) {
        $result = resolve_media_field('project_image');
    }

    if (empty($result)) {
        return '';
    }

    if ($result['type'] === 'video') {
        return sprintf(
            '<video class="dynamic-bg-media" autoplay muted loop playsinline preload="auto">
                <source src="%s" type="video/mp4">
            </video>',
            esc_url($result['url'])
        );
    }

    if ($result['type'] === 'image') {
        return sprintf(
            '<img class="dynamic-bg-media" src="%s" alt="Background media" loading="lazy">',
            esc_url($result['url'])
        );
    }

    return '';
}

/**
 * Resolves an ACF field (array or URL string) to a URL + media type.
 *
 * @param string      $field_name    ACF field name to check.
 * @param string|null $forced_type   Optional: force type instead of detecting (e.g. 'video').
 * @return array|null  ['url' => ..., 'type' => 'video'|'image'] or null if empty/invalid.
 */
function resolve_media_field($field_name, $forced_type = null) {
    $field = get_field($field_name);

    if (empty($field)) {
        return null;
    }

    $url = '';
    $type = $forced_type;

    // ACF File/Image field returning an array
    if (is_array($field) && !empty($field['url'])) {
        $url = $field['url'];

        if (!$type) {
            $mime = isset($field['mime_type']) ? $field['mime_type'] : '';
            if (strpos($mime, 'video') !== false) {
                $type = 'video';
            } elseif (strpos($mime, 'image') !== false) {
                $type = 'image';
            }
        }
    }
    // ACF field returning a plain URL string
    elseif (is_string($field)) {
        $url = $field;

        if (!$type) {
            $ext = strtolower(pathinfo($url, PATHINFO_EXTENSION));
            if (in_array($ext, ['mp4', 'webm', 'ogg'])) {
                $type = 'video';
            } elseif (in_array($ext, ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg'])) {
                $type = 'image';
            }
        }
    }

    if (empty($url) || empty($type)) {
        return null;
    }

    return ['url' => $url, 'type' => $type];
}

Tested on

WordPress 7.1 PHP 8.3 ACF

Reported by the author on September 20, 2026. WPFolks has not verified this.

Know a different way to do this? Add your approach as a variation so folks can compare them side by side.
Submit a variation

0 comments