Boostrap Carousel Block

How To Code a Bootstrap Carousel Block for WordPress

Learn How To code a Bootstrap Carousel Block for your WordPress theme. ACF Pro required.

Today I will show you how to code a Boostrap Carousel Block for Gutenberg that allows you to use the Bootstrap Carousel in WordPress. I will use Advanced Custom Fields Pro, as I always use this plugin my projects.

If you’re familiar with WordPress and Bootstrap, then you probably know that Bootstrap is a popular framework for building responsive websites. It has been my go to framework since I started building WordPress websites in 2014.

One of the most useful components of Bootstrap is the Carousel, which allows you to display a series of images in a slideshow format.

I hope it goes without saying, that this tutorial requires you to include Bootstrap in your project. This tutorial is for Bootstrap v.5.2.x. If you are not already using Bootstrap, then you can get started with Bootstrap here.

Now, if you’re not interested in the tutorial, but just the code. Either skip to the end, or go to my Github Repo to find the code and setup guide there.

Let’s start!

Step 1: Install and Activate Advanced Custom Fields Pro

The first step is to install and activate the Advanced Custom Fields Pro plugin. This plugin allows you to create custom fields for your Gutenberg Block, which I’ll use to create the Carousel content.

As a WordPress Theme Developer, I can recommend you to invest in ACF Pro, as it makes much of your work easier, when working directly with clients.

Step 2: Registering a new Gutenberg block

First, we need to register a new block component in our functions.php file in our WordPress theme. Unless this is core functionality in your custom WordPress theme, then I recommend you to use a Child theme.

Add the following lines of code to your functions.php file.

add_action('acf/init', 'my_acf_blocks_init');
function my_acf_blocks_init() {

    // Check function exists.
    if( function_exists('acf_register_block_type') ) {

            // Register a carousel block.
        'name'              => 'bootstrap-carousel',
        'title'             => __('Carousel'),
        'description'       => __('A slideshow component for cycling through elements—images or slides of text—like a carousel.'),
        'render_template'   => 'template-parts/blocks/bootstrap-carousel/bootstrap-carousel.php',
        'category'          => 'formatting',
        'keywords'          => array( 'carousel', 'bootstrap' ),
        'enqueue_assets' 	=> 	function()
            wp_enqueue_style( 'css-bootstrap-carousel', get_stylesheet_directory_uri() . '/template-parts/blocks/bootstrap-carousel/bootstrap-carousel.css', array(), '1.0.0' );

Step 3: Adding your template file and stylesheet

After successfully registering your block, then it is time to set up your render_template and CSS file. Go to your theme and create the following directory path /template-parts/blocks/bootstrap-carousel/. Inside the /bootstrap-carousel/ folder you need to add to files.

  1. bootstrap-carousel.php
  2. bootstrap-carousel.css

The first one is your render_template and the second one is where your CSS goes.

Inside the render_template you add the following code.


 * Carousel Block Using Bootstrap v5.2.x
 * @param   array $block The block settings and attributes.
 * @param   string $content The block inner HTML (empty).
 * @param   bool $is_preview True during AJAX preview.
 * @param   (int|string) $post_id The post ID this block is saved to.

// Create id attribute allowing for custom "anchor" value.
$id = 'bootstrap-carousel-id-' . $block['id'];
if( !empty($block['anchor']) ) {
    $id = $block['anchor'];

// Create class attribute allowing for custom "className" and "align" values.
$className = 'bootstrap-carousel';
if( !empty($block['className']) ) {
    $className .= ' ' . $block['className'];
if( !empty($block['align']) ) {
    $className .= ' align' . $block['align'];

<div id="<?php echo esc_attr($id); ?>" class="<?php echo esc_attr($className); ?>">


Now your base render_template is ready.

The stylesheet called bootstrap-carousel.css is the same directory. This is to make sure the styles are only applied when the block is used on a page. This way we avoid unnecessary styles being loaded to keep the project lean and clean.

For now, my CSS file looks like this:

/* =Bootstrap Carousel
-------------------------------------------------------------- */

Step 4: Basic Bootstrap Carousel Example

For my carousel, I want a Carousel with Captions, and controls, but no indicators. For that I go to the Bootstrap documentation and copy the With Captions example. Then I insert this into my render_template. Last, but not least, I clean it up, so that it looks like this.

<div id="<?php echo esc_attr($id); ?>" class="<?php echo esc_attr($className); ?>">
    <div id="bootstrapCarouselACF" class="carousel slide" data-bs-ride="false">
        <div class="carousel-inner">
            <div class="carousel-item active">
                <img src="..." class="d-block w-100" alt="...">
                <div class="carousel-caption d-none d-md-block">
                    <h5>First slide label</h5>
                    <p>Some representative placeholder content for the first slide.</p>
            <div class="carousel-item">
                <img src="..." class="d-block w-100" alt="...">
                <div class="carousel-caption d-none d-md-block">
                    <h5>Second slide label</h5>
                    <p>Some representative placeholder content for the second slide.</p>
            <div class="carousel-item">
                <img src="..." class="d-block w-100" alt="...">
                <div class="carousel-caption d-none d-md-block">
                    <h5>Third slide label</h5>
                    <p>Some representative placeholder content for the third slide.</p>
        <button class="carousel-control-prev" type="button" data-bs-target="#bootstrapCarouselACF" data-bs-slide="prev">
            <span class="carousel-control-prev-icon" aria-hidden="true"></span>
            <span class="visually-hidden">Previous</span>
        <button class="carousel-control-next" type="button" data-bs-target="#bootstrapCarouselACF" data-bs-slide="next">
            <span class="carousel-control-next-icon" aria-hidden="true"></span>
            <span class="visually-hidden">Next</span>

Step 5: Creating Custom Fields using ACF Pro

After my initial setup, it’s time for me to head back into WordPress. Here’s where the Pro version of ACF is needed as I’ll be using the Repeater Field option.

  1. Go to the ACF menu (in older versions it’s called “Custom Fields”.
  2. Go to Field Groups and press Add New.
  3. Name your Field Group something like “Bootstrap Carousel.
  4. Add a new Field with the Field Type Repeater.

Working with the Repeater field

Inside the Repeater field I have the option to create so called Sub Fields. These are fields that only exist inside the Repeater Field. Here I need to create an image, a headline, and a paragraph option.

Here is how I created my image field.
Field Label: Image
Field Name: carousel_image

Then we want the option of a caption. I’ll start off with a caption headline.

Field Label: Heading
Field Name: carousel_caption_heading

Then finally, a paragraph section for more descriptive text.

Field Label: Paragraph
Field Name: carousel_caption_paragraph

When to show the Custom Fields.

To make sure my Custom Fields are only shown when my block is selected, I go to the Settings tab. For Location Rules I select to Show this field group if: Block is equal to Carousel.

I save my changes and go to a page to add my newly created block. This is how it looks like, after I added my Carousel Block to a page.

Step 6: Adding Repeater loop to my render_template

Time to return to my render_template. Find the <div class="carousel-inner"> as this is where our repeater fields belong. Remove everything inside the <div> and replace it with this code:

<?php if( have_rows( 'bootstrap_carousel_repeater' ) ): ?>
    <?php while( have_rows( 'bootstrap_carousel_repeater' ) ): the_row(); 
        // Load the sub_fields created in ACF
        $image = get_sub_field('carousel_image');
        $heading = get_sub_field('carousel_caption_heading');
        $paragraph = get_sub_field('carousel_caption_paragraph');
        if (get_row_index() == 1) {
            $active = ' active';
        } else {
            $active = '';
        <div class="carousel-item carousel-item-<?php echo get_row_index(); ?> <?php echo $active; ?>">
            // Check if there's an image selected 
            if( !empty( $image ) ): ?>
                <figure class="adaptive">
                    <picture class="adaptive-photo">
                        <img src="<?php echo esc_url($image['url']); ?>" alt="<?php echo esc_attr($image['alt']); ?>" />
            <?php endif; ?>
            <div class="carousel-caption">
                <?php if( $heading || $paragraph) : ?>
                <div class="carousel-caption__inner">
                    // Check if the headline field is empty
                    if( !empty( $heading ) ): ?>
                            <?php echo $heading; ?>
                    <?php endif; ?>
                    // Check if the paragraph field is empty
                    if( !empty( $paragraph ) ): ?>
                            <?php echo $paragraph; ?>
                    <?php endif; ?>
                <?php endif; ?>
    <?php endwhile; ?>
<?php endif; ?>

The code adds your image, headline and paragraph and sets the first of your images to be active, as this is important for Bootstrap. Without the active class, nothing would be shown on the page.

This is how my Bootstrap Carousel Block is currently looking like.

Step 7: Cleaning up the caption placement

Personally, I’m not too happy about how the default Bootstrap Caption looks like. Therefor I added a bit of different structure in the carousel-item. That allowed me to style the look using my CSS file. You can add your own style or be inspired by mine.

/* =Bootstrap Carousel
-------------------------------------------------------------- */
.carousel-caption {
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;

.carousel-caption__inner {
    max-width: 89.375rem;
    background: rgba(0,0,0,0.25);
    padding: 1rem 2rem;
    margin: 0 .75rem;
    text-align: left;

.carousel-caption__inner h5 {
    color: #fff;

.carousel-caption__inner p {
    margin-bottom: 0;

.carousel-item .adaptive .adaptive-photo {
    height: 560px;

In case you are missing my .adaptive-photo style, that makes sure the image are always scaled correct to avoid stretching:

/* =Adaptive photo
-------------------------------------------------------------- */
.adaptive {
    display: flex;
    flex-wrap: wrap;

.adaptive .adaptive-photo {
    flex-grow: 1;
    height: /* set a default height */;

.adaptive .adaptive-photo img {
    max-height: 100%;
    min-width: 100%;
    height: 100%;
    width: 100%;
    object-fit: cover;
    object-position: center;
    vertical-align: bottom;

Skipping to the end

Was this all a bit much, and you would just like my source code? Fair enough. I’ve added it to Github for you to easily Copy and Paste it into your project. You’re also welcome to check out my Github Repo for the Bootstrap Carousel Block.