Mobile Swiper Slider Code

User
create swiper slider for attahced that will work till 767 media put all code in elementor widget
widget will have
image,text repeatwer field
Assistant
Here's a full Elementor widget code that creates a **Swiper slider** (mobile-only up to 767px) using repeater fields for **image and text**—just like your reference image. It includes the necessary JavaScript and CSS to enable the slider.

### 🧩 Elementor Widget Code (PHP)

<?php
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly

class Mobile_Steps_Slider_Widget extends ElementorWidget_Base {

    public function get_name() {
        return 'mobile_steps_slider';
    }

    public function get_title() {
        return __('Mobile Steps Slider', 'custom-widgets');
    }

    public function get_icon() {
        return 'eicon-slider-device';
    }

    public function get_categories() {
        return ['general'];
    }

    protected function _register_controls() {

        $this->start_controls_section('steps_section', [
            'label' => __('Steps Items', 'custom-widgets'),
        ]);

        $repeater = new ElementorRepeater();

        $repeater->add_control('step_image', [
            'label' => __('Step Image', 'custom-widgets'),
            'type' => ElementorControls_Manager::MEDIA,
            'default' => [
                'url' => ElementorUtils::get_placeholder_image_src(),
            ],
        ]);

        $repeater->add_control('step_text', [
            'label' => __('Step Text', 'custom-widgets'),
            'type' => ElementorControls_Manager::TEXT,
            'default' => __('Sample Step Text', 'custom-widgets'),
        ]);

        $this->add_control('steps', [
            'label' => __('Steps', 'custom-widgets'),
            'type' => ElementorControls_Manager::REPEATER,
            'fields' => $repeater->get_controls(),
            'default' => [],
        ]);

        $this->end_controls_section();
    }

    protected function render() {
        $settings = $this->get_settings_for_display();

        if ( empty($settings['steps']) ) {
            return;
        }
        ?>

        <div class="mobile-steps-slider-wrapper">
            <div class="swiper mobile-steps-swiper">
                <div class="swiper-wrapper">
                    <?php foreach ( $settings['steps'] as $step ) : ?>
                        <div class="swiper-slide step-slide">
                            <div class="step-item">
                                <img src="<?php echo esc_url($step['step_image']['url']); ?>" alt="Step">
                                <p><?php echo esc_html($step['step_text']); ?></p>
                            </div>
                        </div>
                    <?php endforeach; ?>
                </div>
                <div class="swiper-pagination"></div>
            </div>
        </div>

        <style>
        @media (max-width: 767px) {
            .mobile-steps-slider-wrapper {
                padding: 20px 0;
            }
            .step-item {
                text-align: center;
            }
            .step-item img {
                max-width: 100px;
                margin: 0 auto 10px;
            }
            .step-item p {
                font-size: 16px;
                color: #333;
            }
        }
        </style>

        <script>
        document.addEventListener('DOMContentLoaded', function () {
            if (window.innerWidth <= 767) {
                new Swiper('.mobile-steps-swiper', {
                    loop: false,
                    pagination: {
                        el: '.swiper-pagination',
                        clickable: true,
                    },
                    spaceBetween: 20,
                });
            }
        });
        </script>

        <?php
    }
}

### ✅ Dependencies

Ensure **Swiper JS** and **CSS** are loaded globally or enqueue them in your theme/plugin:

function enqueue_swiper_assets() {
    wp_enqueue_style('swiper-css', 'https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.css');
    wp_enqueue_script('swiper-js', 'https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.js', [], null, true);
}
add_action('wp_enqueue_scripts', 'enqueue_swiper_assets');

Would you like me to convert this into a zip-ready plugin format?

User
also include swipper cdn
Assistant
Great — here's the **full Elementor widget code** with **Swiper CDN included directly in the render output**, so it works **without needing extra enqueuing**. This widget will show a **Swiper slider on devices ≤767px**, with repeater fields for **image + text**.

### ✅ Final Elementor Widget with Swiper CDN

<?php
if ( ! defined( 'ABSPATH' ) ) exit;

class Mobile_Steps_Slider_Widget extends ElementorWidget_Base {

    public function get_name() {
        return 'mobile_steps_slider';
    }

    public function get_title() {
        return __('Mobile Steps Slider', 'custom-widgets');
    }

    public function get_icon() {
        return 'eicon-slider-device';
    }

    public function get_categories() {
        return ['general'];
    }

    protected function _register_controls() {

        $this->start_controls_section('steps_section', [
            'label' => __('Steps Items', 'custom-widgets'),
        ]);

        $repeater = new ElementorRepeater();

        $repeater->add_control('step_image', [
            'label' => __('Step Image', 'custom-widgets'),
            'type' => ElementorControls_Manager::MEDIA,
            'default' => [
                'url' => ElementorUtils::get_placeholder_image_src(),
            ],
        ]);

        $repeater->add_control('step_text', [
            'label' => __('Step Text', 'custom-widgets'),
            'type' => ElementorControls_Manager::TEXT,
            'default' => __('Sample Step Text', 'custom-widgets'),
        ]);

        $this->add_control('steps', [
            'label' => __('Steps', 'custom-widgets'),
            'type' => ElementorControls_Manager::REPEATER,
            'fields' => $repeater->get_controls(),
            'default' => [],
        ]);

        $this->end_controls_section();
    }

    protected function render() {
        $settings = $this->get_settings_for_display();

        if ( empty($settings['steps']) ) {
            return;
        }
        ?>

        <div class="mobile-steps-slider-wrapper">
            <div class="swiper mobile-steps-swiper">
                <div class="swiper-wrapper">
                    <?php foreach ( $settings['steps'] as $step ) : ?>
                        <div class="swiper-slide step-slide">
                            <div class="step-item">
                                <img src="<?php echo esc_url($step['step_image']['url']); ?>" alt="Step">
                                <p><?php echo esc_html($step['step_text']); ?></p>
                            </div>
                        </div>
                    <?php endforeach; ?>
                </div>
                <div class="swiper-pagination"></div>
            </div>
        </div>

        <!-- Swiper CDN (JS + CSS) -->
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.css" />
        <script src="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.js"></script>

        <style>
        @media (max-width: 767px) {
            .mobile-steps-slider-wrapper {
                padding: 20px 0;
            }
            .step-item {
                text-align: center;
                padding: 10px;
            }
            .step-item img {
                max-width: 80px;
                margin: 0 auto 10px;
                display: block;
            }
            .step-item p {
                font-size: 15px;
                color: #333;
                margin: 0;
            }
        }
        </style>

        <script>
        document.addEventListener('DOMContentLoaded', function () {
            if (window.innerWidth <= 767) {
                new Swiper('.mobile-steps-swiper', {
                    loop: false,
                    pagination: {
                        el: '.swiper-pagination',
                        clickable: true,
                    },
                    spaceBetween: 20,
                });
            }
        });
        </script>

        <?php
    }
}

You can now:

– Add this widget to your custom Elementor plugin.
– Upload images and step titles.
– The slider activates only on mobile (≤767px).

Would you like this as a zip plugin or should I help register this widget inside your custom plugin structure?

User
make css style like attached for each slider
Assistant
To match the **design style of the attached image** in the mobile Swiper slider, I’ve updated the CSS inside your Elementor widget render method. The following style includes:

– Circular red background
– Icon/image centered inside the circle
– Text below
– Dashed curved connector (as close as possible in slider)
– White border ring

### ✅ Updated CSS inside widget (`render()` method):

Replace your “ block with this:

<style>
@media (max-width: 767px) {
    .mobile-steps-slider-wrapper {
        padding: 20px 0;
    }

    .swiper-slide.step-slide {
        display: flex;
        justify-content: center;
    }

    .step-item {
        display: flex;
        flex-direction: column;
        align-items: center;
        position: relative;
    }

    .step-item img {
        width: 64px;
        height: 64px;
        background-color: #e9205a; /* Main red color */
        border-radius: 50%;
        padding: 14px;
        border: 5px solid #fff;
        box-shadow: 0 0 0 4px #e9205a;
        object-fit: contain;
    }

    .step-item::after {
        content: '';
        position: absolute;
        top: 32px;
        right: -50%;
        width: 100%;
        height: 2px;
        border-top: 2px dashed #e9205a;
        z-index: -1;
    }

    .swiper-slide:last-child .step-item::after {
        display: none;
    }

    .step-item p {
        margin-top: 15px;
        font-size: 14px;
        font-weight: 500;
        color: #1a1a1a;
        text-align: center;
        max-width: 120px;
    }
}
</style>

### 🔁 Resulting Look on Mobile:
– Each step appears in a centered circle.
– Red/pink background with white ring border.
– Dotted line connecting to the next step (simulated with `::after`).
– Text is clean and clear underneath.

Let me know if you'd like:
– **A curved SVG path connector** like your image (requires custom SVG).
– **Different icons or shadow/glow effects.**
– This packed as a **ready-to-install Elementor plugin zip**.

User
<style>
.mobile-steps-slider-wrapper
    {
        display: none;
    }
@media (max-width: 767px) {
    .mobile-steps-slider-wrapper {
        padding: 20px 0;
        display: flex;
    }

    .swiper-slide.step-slide {
        display: flex;
        justify-content: center;
    }

    .step-item {
        display: flex;
        flex-direction: column;
        align-items: center;
        position: relative;
    }

    .step-item img {
        width: 64px;
        height: 64px;
        background-color: #e9205a; /* Main red color */
        border-radius: 50%;
        padding: 14px;
        border: 5px solid #fff;
        box-shadow: 0 0 0 4px #e9205a;
        object-fit: contain;
    }

    .step-item::after {
        content: '';
        position: absolute;
        top: 32px;
        right: -50%;
        width: 100%;
        height: 2px;
        border-top: 2px dashed #e9205a;
        z-index: -1;
    }

    .swiper-slide:last-child .step-item::after {
        display: none;
    }

    .step-item p {
        margin-top: 15px;
        font-size: 14px;
        font-weight: 500;
        color: #1a1a1a;
        text-align: center;
        max-width: 120px;
    }
}
</style>
<script>

</script>
<script>
document.addEventListener('DOMContentLoaded', function () {
            new Swiper('.mobile-steps-swiper', {
                slidesPerView: 1,
                spaceBetween: 30,
                loop: true,
                breakpoints: {
                    0: { slidesPerView: 1 },
                }
            });
        });
</script>
Assistant
Your issue is that the Swiper initialization is running **before** the slider is rendered in the DOM—especially in Elementor's editor or frontend load.

Also, you’re missing the `swiper-container` class on the main Swiper wrapper, and the slider CSS is hidden by default (`display: none`) unless the viewport is under 767px, but there’s no guarantee that Swiper sees it in time.

### ✅ Here's a corrected and working version:

Update the **render** function with these fixes:

1. Ensure `.swiper` is initialized only after it's visible.
2. Add a check for Elementor frontend/editor.
3. Use correct class hooks (`swiper` and `swiper-wrapper` are already correct).
4. Ensure `display: block` kicks in only after DOM is ready.

### ✅ Final Fixed `render()` Function:

Replace your `render()` content with this version:

protected function render() {
    $settings = $this->get_settings_for_display();

    if ( empty($settings['steps']) ) {
        return;
    }
    ?>
    <style>
    @media (max-width: 767px) {
        .mobile-steps-slider-wrapper {
            padding: 20px 0;
            display: block;
        }

        .swiper-slide.step-slide {
            display: flex;
            justify-content: center;
        }

        .step-item {
            display: flex;
            flex-direction: column;
            align-items: center;
            position: relative;
        }

        .step-item img {
            width: 64px;
            height: 64px;
            background-color: #e9205a;
            border-radius: 50%;
            padding: 14px;
            border: 5px solid #fff;
            box-shadow: 0 0 0 4px #e9205a;
            object-fit: contain;
        }

        .step-item::after {
            content: '';
            position: absolute;
            top: 32px;
            right: -50%;
            width: 100%;
            height: 2px;
            border-top: 2px dashed #e9205a;
            z-index: -1;
        }

        .swiper-slide:last-child .step-item::after {
            display: none;
        }

        .step-item p {
            margin-top: 15px;
            font-size: 14px;
            font-weight: 500;
            color: #1a1a1a;
            text-align: center;
            max-width: 120px;
        }
    }

    @media (min-width: 768px) {
        .mobile-steps-slider-wrapper {
            display: none;
        }
    }
    </style>

    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.css" />
    <div class="mobile-steps-slider-wrapper">
        <div class="swiper mobile-steps-swiper">
            <div class="swiper-wrapper">
                <?php foreach ( $settings['steps'] as $step ) : ?>
                    <div class="swiper-slide step-slide">
                        <div class="step-item">
                            <img src="<?php echo esc_url($step['step_image']['url']); ?>" alt="Step">
                            <p><?php echo esc_html($step['step_text']); ?></p>
                        </div>
                    </div>
                <?php endforeach; ?>
            </div>
            <div class="swiper-pagination"></div>
        </div>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.js"></script>

    <script>
    (function(){
        function initSwiper() {
            if (window.innerWidth <= 767) {
                new Swiper('.mobile-steps-swiper', {
                    loop: false,
                    spaceBetween: 30,
                    slidesPerView: 1,
                    pagination: {
                        el: '.swiper-pagination',
                        clickable: true,
                    },
                });
            }
        }

        if (document.readyState === 'loading') {
            document.addEventListener('DOMContentLoaded', initSwiper);
        } else {
            initSwiper();
        }

        // Also initialize in Elementor editor mode
        jQuery(window).on('elementor/frontend/init', function() {
            elementorFrontend.hooks.addAction('frontend/element_ready/widget', function($scope) {
                if ($scope.find('.mobile-steps-swiper').length > 0) {
                    initSwiper();
                }
            });
        });
    })();
    </script>
    <?php
}

Let me know if you'd like a desktop version or continuous curved path between circles like in the image (can be done using SVG overlays).

User
swipper not work make it owl carsel
Assistant
Thanks for the clarification! Below is the updated **Elementor widget** that uses **Owl Carousel** instead of Swiper and works on mobile (≤767px). It includes:

– Repeater for image + text.
– Owl Carousel initialized on frontend.
– Matching design from your screenshot.
– CDN for Owl Carousel CSS/JS is embedded.

### ✅ Final Elementor Widget Using Owl Carousel

<?php
if ( ! defined( 'ABSPATH' ) ) exit;

class Mobile_Steps_Slider_Widget extends ElementorWidget_Base {

    public function get_name() {
        return 'mobile_steps_slider';
    }

    public function get_title() {
        return __('Mobile Steps Slider', 'custom-widgets');
    }

    public function get_icon() {
        return 'eicon-slider-device';
    }

    public function get_categories() {
        return ['general'];
    }

    protected function _register_controls() {
        $this->start_controls_section('steps_section', [
            'label' => __('Steps Items', 'custom-widgets'),
        ]);

        $repeater = new ElementorRepeater();

        $repeater->add_control('step_image', [
            'label' => __('Step Image', 'custom-widgets'),
            'type' => ElementorControls_Manager::MEDIA,
            'default' => ['url' => ElementorUtils::get_placeholder_image_src()],
        ]);

        $repeater->add_control('step_text', [
            'label' => __('Step Text', 'custom-widgets'),
            'type' => ElementorControls_Manager::TEXT,
            'default' => __('Sample Step Text', 'custom-widgets'),
        ]);

        $this->add_control('steps', [
            'label' => __('Steps', 'custom-widgets'),
            'type' => ElementorControls_Manager::REPEATER,
            'fields' => $repeater->get_controls(),
            'default' => [],
        ]);

        $this->end_controls_section();
    }

    protected function render() {
        $settings = $this->get_settings_for_display();

        if (empty($settings['steps'])) {
            return;
        }
        ?>

        <!-- Owl Carousel CSS/JS -->
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/owl.carousel@2.3.4/dist/assets/owl.carousel.min.css" />
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/owl.carousel@2.3.4/dist/assets/owl.theme.default.min.css" />
        <script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/owl.carousel@2.3.4/dist/owl.carousel.min.js"></script>

        <style>
        @media (max-width: 767px) {
            .mobile-steps-slider-wrapper {
                padding: 20px 0;
                display: block;
            }

            .owl-carousel .item {
                text-align: center;
            }

            .step-item {
                display: flex;
                flex-direction: column;
                align-items: center;
                position: relative;
            }

            .step-item img {
                width: 64px;
                height: 64px;
                background-color: #e9205a;
                border-radius: 50%;
                padding: 14px;
                border: 5px solid #fff;
                box-shadow: 0 0 0 4px #e9205a;
                object-fit: contain;
            }

            .step-item p {
                margin-top: 15px;
                font-size: 14px;
                font-weight: 500;
                color: #1a1a1a;
                max-width: 120px;
            }
        }

        @media (min-width: 768px) {
            .mobile-steps-slider-wrapper {
                display: none;
            }
        }
        </style>

        <div class="mobile-steps-slider-wrapper">
            <div class="owl-carousel owl-theme" id="mobile-steps-carousel">
                <?php foreach ($settings['steps'] as $step) : ?>
                    <div class="item">
                        <div class="step-item">
                            <img src="<?php echo esc_url($step['step_image']['url']); ?>" alt="Step">
                            <p><?php echo esc_html($step['step_text']); ?></p>
                        </div>
                    </div>
                <?php endforeach; ?>
            </div>
        </div>

        <script>
        jQuery(document).ready(function($) {
            if (window.innerWidth <= 767) {
                $('#mobile-steps-carousel').owlCarousel({
                    loop: false,
                    margin: 20,
                    nav: false,
                    dots: true,
                    items: 1,
                });
            }
        });
        </script>

        <?php
    }
}

### ✅ Usage Notes:
– Add this to your custom Elementor widget plugin.
– Now uses **Owl Carousel** for better mobile compatibility.
– Only visible for screens ≤767px.
– Fully styled to match your circular red icons layout.

Would you like the desktop version shown as a horizontal flex layout instead of slider?

User
make display of sldier like exact attached
Assistant
Based on the attached close-up image, here's how to recreate **exactly that circular red slider item design** in your Elementor Owl Carousel mobile slider.

The style includes:

– A **solid red inner circle**
– An **outer semi-transparent pink border ring**
– **Pink dots** at top-left and bottom-left
– A **dashed line connector** to the next item

### ✅ Updated CSS (Use Inside Widget `render()` Function)

Replace your current “ block with this one:

<style>
@media (max-width: 767px) {
    .mobile-steps-slider-wrapper {
        padding: 20px 0;
        display: block;
    }

    .owl-carousel .item {
        text-align: center;
        position: relative;
    }

    .step-item {
        position: relative;
        width: 120px;
        height: 120px;
        margin: auto;
    }

    .step-circle {
        width: 100px;
        height: 100px;
        border-radius: 50%;
        background-color: #e9205a;
        border: 4px solid white;
        box-shadow: 0 0 0 5px rgba(233, 32, 90, 0.5);
        display: flex;
        align-items: center;
        justify-content: center;
        margin: auto;
        position: relative;
        z-index: 1;
    }

    .step-circle img {
        max-width: 40px;
        max-height: 40px;
        filter: brightness(0) invert(1); /* turns icon white */
    }

    .dot {
        width: 10px;
        height: 10px;
        background-color: #e9205a;
        border-radius: 50%;
        position: absolute;
        z-index: 2;
    }

    .dot.top-left {
        top: -8px;
        left: -8px;
    }

    .dot.bottom-left {
        bottom: -8px;
        left: -8px;
    }

    .dashed-line {
        position: absolute;
        top: 50%;
        left: 100%;
        width: 40px;
        height: 1px;
        border-top: 2px dashed #e9205a;
        z-index: 0;
        transform: translateY(-50%);
    }

    .step-item p {
        margin-top: 20px;
        font-size: 14px;
        font-weight: 500;
        color: #1a1a1a;
        text-align: center;
        max-width: 120px;
    }

    .owl-carousel .item:last-child .dashed-line {
        display: none;
    }
}

@media (min-width: 768px) {
    .mobile-steps-slider-wrapper {
        display: none;
    }
}
</style>

### ✅ Update HTML in the `render()` function:

Replace this part:

<div class="step-item">
    <img src="<?php echo esc_url($step['step_image']['url']); ?>" alt="Step">
    <p><?php echo esc_html($step['step_text']); ?></p>
</div>

With this:

<div class="step-item">
    <div class="dot top-left"></div>
    <div class="dot bottom-left"></div>
    <div class="step-circle">
        <img src="<?php echo esc_url($step['step_image']['url']); ?>" alt="Step">
    </div>
    <div class="dashed-line"></div>
    <p><?php echo esc_html($step['step_text']); ?></p>
</div>

### ✅ Final Touches
– Ensure uploaded images (icons) are **transparent SVG or PNG** for best results.
– The white icon is achieved with `filter: brightness(0) invert(1)`.

Would you like me to provide this as a ready-to-import Elementor widget/plugin zip file?

Leave a Comment

Your email address will not be published. Required fields are marked *