embedding 2 short codes in one page breaks layout

zoloherald

New member
hi all!
i'm a total newbie to php, but thanks to chat gpt I'm managing to save some money on wp-plug ins :)

i'm trying to create a template for a stylized box display of my products with an easy short code + product ID that I could embed in my various pages.
i'm inserting it to wordpress using snippets.
honestly, i'm very pleased with the result, it works very well when there is one short code embedded in one of my pages. but when I try to embed two of them in the same page (with the same id or different ones) my entire page layout breaks. What am I missing?

I've also tried to isolate the styles and java - functionality worked for a single embedded short code, 2 of them breaks the page - i've included it all here in the php.

I'd love your help!!


PHP:
function boxed_product_shortcode($atts) {
    $atts = shortcode_atts(
        array(
            'product_id' => 0,
        ),
        $atts,
        'boxed_product'
    );

    // Check if a product ID is provided
    if ($atts['product_id'] > 0) {
        $product = wc_get_product($atts['product_id']);

        if (!$product) {
            return 'Product not found';
        }

        // Check if the product has a limit of 1 item per order
        $limit_one_per_order = $product->is_sold_individually();

        // Use the product's featured image if available
        $product_image_id = $product->get_image_id();
        if ($product_image_id) {
            $image_url = wp_get_attachment_url($product_image_id);
        }
    } else {
        // Set a default image URL
        $image_url = 'https://i.imgflip.com/87jmvx.jpg';
    }

    // Extract product tags
    $product_tags = wp_get_post_terms($atts['product_id'], 'product_tag');
    $tag_names = array_map(function ($tag) {
        return $tag->name;
    }, $product_tags);

    // Determine the primary tag
    function get_primary_tag($tags) {
        $priority_tags = ['main', 'studio', 'office', 'market', 'school'];

        foreach ($priority_tags as $priority_tag) {
            if (in_array($priority_tag, $tags)) {
                return $priority_tag;
            }
        }

        return 'main';
    }

    $primary_tag = get_primary_tag($tag_names);

    ob_start(); ?>

   <!-- <div class="boxed-product <?php ///echo in_array('studio', $tag_names) ? 'studio-tagged' : ''; ?>"> -->
        <div class="boxed-product boxed-product-<?php echo esc_attr($atts['product_id']); ?> <?php echo in_array('studio', $tag_names) ? 'studio-tagged' : ''; ?>">

        <h6 class="zProduct"><?php echo esc_html($product->get_title()); ?></h6>
        <img
            src="<?php echo esc_url($image_url); ?>"
            alt="<?php echo esc_attr($product->get_title()); ?>"
        />
        <div class="productCardBottom">
            <p class="short-description"><?php echo esc_html($product->get_short_description()); ?></p>
            
            <?php if ($limit_one_per_order) : ?>
                <h6 class="price"><?php echo wc_price($product->get_price()); ?></h6>
                <h6 class="bundle-title">Bundle</h6>
            <?php else : ?>
                <h6 class="price"><?php echo wc_price($product->get_price()); ?></h6>
                <div class="quantity-controls">
                    <button class="quantity-button" data-action="decrease">-</button>
                    <input type="number" class="quantity-field" value="1" min="1" step="1">
                    <button class="quantity-button" data-action="increase">+</button>
                </div>
            <?php endif; ?>

            <button class="add-to-cart-button" data-product-id="<?php echo $atts['product_id']; ?>"><h6>Add to Cart</h6></button>
        </div>
    </div>
    
    <style>
        :root {
            --main-color: #90EE90; /* lightgreen */
            --studio-color: #E9E06D; /* yellow */
            --office-color: #FFA500; /* orange */
            --market-color: #800080; /* purple */
            --school-color: #228B22; /* forestgreen */
            --default-color: #4caf50; /* default color */
        }

        .boxed-product {
            display: grid;
            grid-template-columns: 1fr;
            grid-template-rows: 1fr 1fr;
            background-color: #fffbcb;
            max-width: 10vw;
            max-height: 30vh;
        }

        .studio-tagged img {
            border-bottom: 8px solid var(--<?php echo esc_attr($primary_tag); ?>-color, var(--default-color));
        }

        .zProduct {
            grid-column: 1;
            grid-row: 1;
            z-index: 1;
            color: #fffbcb;
            align-self: end;
            padding: 0;
            margin: 0 0 8px 0; /* Add 8px padding to the top and bottom */
        }

        .boxed-product img {
            width: 10vw;
            height: 15vh;
            object-fit: cover;
            grid-column: 1;
            grid-row: 1;
        }

        .productCardBottom {
            grid-column: 1;
            grid-row: 2;
            display: flex;
            flex-direction: column;
            gap: 8px;
        }

        .productCardBottom p.short-description,
        .price {
            font-family: 'Nunito Sans', sans-serif;
            font-weight: 400;
            text-transform: none;
            line-height: 1.5em;
            color: black;
            text-indent: 0;
            padding: 0;
            margin: 0;
        }
        .short-description {
            display: -webkit-box;
            -webkit-line-clamp: 2;
            -webkit-box-orient: vertical;
            overflow: hidden;
        }
        .quantity-controls {
            display: flex;
            flex-direction: row;
            align-items: center;
            justify-content: space-between;
            margin-top: 8px;
            z-index: 3;
        }

        .quantity-button {
            width: 30px;
            height: 30px;
            background-color: var(--<?php echo esc_attr($primary_tag); ?>-color, var(--default-color));
            color: white;
            border: none;
            border-radius: 50%;
            cursor: pointer;
            font-size: 16px;
            line-height: 1.5em;
        }

        .quantity-field {
            width: 50px;
            height: 30px;
            text-align: center;
            border: 1px solid #ddd;
            border-radius: 5px;
            margin: 0 8px;
            font-size: 14px;
        }

        .add-to-cart-button {
            width: 100%; /* Set the width to 100% of the container */
            color: white;
            padding: 10px;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            background-color: var(--<?php echo esc_attr($primary_tag); ?>-color, var(--default-color));
            z-index: 3;
        }
        .add-to-cart-button h6 {
            padding: 0;
            margin: 0;
            line-height: 1.5em;
        }
        .bundle-title {
            font-family: 'Nunito Sans', sans-serif;
            font-weight: 600;
            text-transform: none;
            line-height: 1.5em;
            color: black;
            text-indent: 0;
            padding: 0;
            margin: 0;
        }
    </style>
<script>
    // JavaScript to handle adding the product to the cart
    document.addEventListener('DOMContentLoaded', function () {
        var addToCartButtons = document.querySelectorAll('.add-to-cart-button');

        addToCartButtons.forEach(function (addToCartButton) {
            addToCartButton.addEventListener('click', function () {
                var productId = addToCartButton.getAttribute('data-product-id');
                var quantity = 1; // Quantity is always 1 for bundle mode

                // Check if the product is limited to 1 item per order (bundle mode)
                var isBundle = addToCartButton.closest('.boxed-product').classList.contains('limit-one-per-order');

                // Use AJAX to add the product to the cart
                jQuery.ajax({
                    type: 'POST',
                    url: wc_add_to_cart_params.ajax_url,
                    data: {
                        action: 'woocommerce_add_to_cart',
                        product_id: productId,
                        quantity: isBundle ? 1 : quantity, // Set quantity to 1 for bundle mode
                    },
                    success: function (response) {
                        alert('Product has been added to the cart!\nQuantity: ' + quantity);
                    },
                    beforeSend: function() {
                        // Add loading state or other UI feedback if needed
                    },
                    complete: function() {
                        // Remove loading state or other UI feedback if needed
                    },
                    error: function(error) {
                        console.error('Failed to add product to cart:', error);
                    },
                });
            });
        });
    });
</script>




    <?php
    return ob_get_clean();
}

add_shortcode('boxed_product', 'boxed_product_shortcode');
 
Please check below code :

function boxed_product_shortcode($atts) {
$atts = shortcode_atts(
array(
'product_id' => 0,
),
$atts,
'boxed_product'
);
// PHP code
ob_start(); ?>
<div class="boxed-product boxed-product-<?php echo esc_attr($atts['product_id']); ?> <?php echo in_array('studio', $tag_names) ? 'studio-tagged' : ''; ?>">
<!-- HTML code -->
</div>
<style>
/* Scoped styles for this specific instance */
.boxed-product-<?php echo esc_attr($atts['product_id']); ?> {
/* your specific styles */
}
/* remaining style */
</style>
<script>
// Scoped JavaScript for this specific instance
document.addEventListener('DOMContentLoaded', function () {
var addToCartButton = document.querySelector('.boxed-product-<?php echo esc_attr($atts['product_id']); ?> .add-to-cart-button');

if (addToCartButton) {
// JavaScript code
}
});
</script>

<?php
return ob_get_clean();
}
add_shortcode('boxed_product', 'boxed_product_shortcode');
 
It seems like your issue is related to CSS and HTML structure when you're trying to embed multiple shortcodes on the same page. Looking at your code, I see that you're using absolute units (vw and vh) for sizing, which might not be ideal for responsive layouts, especially when you have multiple elements interacting.

Avoid Absolute Units: Instead of using vw and vh, consider using relative units like percentages or flexbox/grid for layout. This will ensure that your elements scale appropriately with the container.

Isolate Styles: It's good that you've encapsulated your CSS within the shortcode, but there might still be some conflicts with other styles on your page. You could try adding a unique class or ID to the container of each shortcode and scope your CSS styles more specifically to avoid conflicts.

you can add a dynamic class based on the product ID to the container of each shortcode:

<div class="boxed-product boxed-product-<?php echo esc_attr($atts['product_id']); ?>">
 
Back
Top