You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调整WooCommerce商品长描述位置并实现带格式查看更多功能

WooCommerce商品长描述截断并保留格式的解决方案

你当前的代码直接切割HTML字符串,容易破坏标签结构(比如截断到<p>标签中间),导致后续内容格式失效或直接显示。要解决这个问题,需要通过DOM操作拆分内容,保证HTML结构完整,同时实现「查看更多/收起」的交互。


方案一:按指定字符数截断并保留格式

1. 替换PHP代码

把你当前的函数替换为以下代码:

add_action( 'woocommerce_single_product_summary', 'custom_template_single_long_description', 30 );
 
function custom_template_single_long_description() {
    global $product;
    $long_description = $product->get_description();
    
    // 长描述为空则不输出
    if ( empty( $long_description ) ) return;
    
    // 输出带容器的长描述
    echo '<div class="product-long-description">';
        echo '<div class="description-visible">' . wp_kses_post( $long_description ) . '</div>';
        echo '<div class="description-hidden" style="display:none;"></div>';
        echo '<a href="#" class="toggle-description">查看更多</a>';
    echo '</div>';
    
    wc_enqueue_js( "
        jQuery(document).ready(function($) {
            var charLimit = 100; // 可自定义截断字符数
            var $visible = $('.description-visible');
            var $hidden = $('.description-hidden');
            var $toggle = $('.toggle-description');
            
            // 获取纯文本内容判断长度
            var fullText = $visible.text().trim();
            if (fullText.length <= charLimit) {
                $toggle.hide();
                return;
            }
            
            // 遍历DOM元素拆分内容,保证标签完整
            var tempDiv = $('<div>').html($visible.html());
            var currentLength = 0;
            var visibleElements = [];
            
            tempDiv.contents().each(function() {
                var elemText = $(this).text().trim();
                if (currentLength + elemText.length <= charLimit) {
                    visibleElements.push(this);
                    currentLength += elemText.length;
                } else {
                    // 截断当前元素文本并添加省略号
                    var remainingChars = charLimit - currentLength;
                    var truncatedText = elemText.substr(0, remainingChars) + '...';
                    
                    if ($(this).is('text')) {
                        visibleElements.push(document.createTextNode(truncatedText));
                        // 剩余文本移到隐藏容器
                        $hidden.prepend(document.createTextNode(elemText.substr(remainingChars)));
                    } else {
                        var clonedElem = $(this).clone();
                        clonedElem.text(truncatedText);
                        visibleElements.push(clonedElem[0]);
                        // 剩余内容移到隐藏容器
                        var remainingElem = $(this).clone();
                        remainingElem.text(elemText.substr(remainingChars));
                        $hidden.prepend(remainingElem);
                    }
                    
                    // 后续所有元素移到隐藏容器
                    $(this).nextAll().appendTo($hidden);
                    return false; // 停止遍历
                }
            });
            
            // 更新可见容器内容
            $visible.empty().append(visibleElements);
            
            // 切换按钮交互逻辑
            $toggle.click(function(e) {
                e.preventDefault();
                $hidden.toggle();
                var btnText = $(this).text() === '查看更多' ? '收起' : '查看更多';
                $(this).text(btnText);
                
                if ($hidden.is(':visible')) {
                    // 展开:把隐藏内容移回可见容器
                    $visible.append($hidden.contents());
                    $hidden.empty();
                } else {
                    // 收起:重新拆分内容
                    currentLength = 0;
                    visibleElements = [];
                    tempDiv = $('<div>').html($visible.html());
                    
                    tempDiv.contents().each(function() {
                        var elemText = $(this).text().trim();
                        if (currentLength + elemText.length <= charLimit) {
                            visibleElements.push(this);
                            currentLength += elemText.length;
                        } else {
                            var remainingChars = charLimit - currentLength;
                            var truncatedText = elemText.substr(0, remainingChars) + '...';
                            
                            if ($(this).is('text')) {
                                visibleElements.push(document.createTextNode(truncatedText));
                                $hidden.prepend(document.createTextNode(elemText.substr(remainingChars)));
                            } else {
                                var clonedElem = $(this).clone();
                                clonedElem.text(truncatedText);
                                visibleElements.push(clonedElem[0]);
                                var remainingElem = $(this).clone();
                                remainingElem.text(elemText.substr(remainingChars));
                                $hidden.prepend(remainingElem);
                            }
                            
                            $(this).nextAll().appendTo($hidden);
                            return false;
                        }
                    });
                    
                    $visible.empty().append(visibleElements);
                }
            });
        });
    " );
}

2. 添加CSS样式

将以下样式添加到主题的style.css文件或自定义CSS面板:

.product-long-description {
    margin-top: 1.5rem;
}

.toggle-description {
    display: inline-block;
    margin-top: 1rem;
    color: #007cba;
    text-decoration: none;
}

.toggle-description:hover {
    text-decoration: underline;
}

方案二:按段落截断(更简洁)

如果只需要显示第一段,隐藏后续所有内容,可使用这个更简单的方案:

修改PHP代码

add_action( 'woocommerce_single_product_summary', 'custom_template_single_long_description', 30 );
 
function custom_template_single_long_description() {
    global $product;
    $long_description = $product->get_description();
    
    if ( empty( $long_description ) ) return;
    
    echo '<div class="product-long-description">';
        echo wp_kses_post( $long_description );
        echo '<a href="#" class="toggle-description">查看更多</a>';
    echo '</div>';
    
    wc_enqueue_js( "
        jQuery(document).ready(function($) {
            var $descWrap = $('.product-long-description');
            var $firstPara = $descWrap.find('p:first');
            var $remainingContent = $firstPara.nextAll();
            var $toggle = $('.toggle-description');
            
            if ($remainingContent.length === 0) {
                $toggle.hide();
                return;
            }
            
            // 把第一段以外的内容包裹在隐藏容器里
            $remainingContent.wrapAll('<div class=\"description-hidden\" style=\"display:none;\"></div>');
            
            $toggle.click(function(e) {
                e.preventDefault();
                $('.description-hidden').toggle();
                $(this).text($(this).text() === '查看更多' ? '收起' : '查看更多');
            });
        });
    " );
}

同样添加方案一中的CSS样式即可。


关键说明

  • 两种方案都通过DOM操作拆分内容,避免直接切割HTML字符串,确保段落、换行等格式完全保留。
  • 方案一可自定义截断字符数,适合需要精确控制显示长度的场景;方案二更简单,适合只需要显示第一段的需求。
  • 代码中使用wp_kses_post()保证输出的HTML安全,避免XSS风险。

内容的提问来源于stack exchange,提问作者Alchemy Creative

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 04:08:11