调整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
相关产品推荐
相关产品推荐

