
本文介绍如何通过原生 JavaScript 实现:当用户选择完一个单选组(radio)或达到复选框(checkbox)的 data-maxqty 限制时,自动平滑滚动至下一个 标题区块,提升多步骤表单的交互体验。
本文介绍如何通过原生 JavaScript 实现:当用户选择完一个单选组(radio)或达到复选框(checkbox)的 `data-maxqty` 限制时,自动平滑滚动至下一个 `
` 标题区块,提升多步骤表单的交互体验。
在餐饮类弹窗菜单(如披萨尺寸、饼底、配料等多级配置)中,用户需按顺序完成各模块的选择。为优化体验,我们希望:
✅ 点击任意 radio 按钮(单选)后,立即滚动到下一配置区块;
✅ 点击 checkbox 后,仅当当前组已选满 data-maxqty 个选项时,才触发滚动;
✅ 滚动目标为紧邻当前 的下一个 (即下一模块标题),确保视觉焦点自然下移。
✅ 核心实现逻辑
关键在于精准识别「当前选项组」与「是否已达上限」,并调用现代浏览器原生 API scrollIntoView() 实现平滑定位:
function scrollModalBodyToBottom() {
// 1. 统一计算当前组允许的最大选择数
const limit = this.type === 'radio'
? 1
: parseInt(this.dataset.maxqty ?? '1', 10);
// 2. 获取同 name 的所有已选选项(radio/checkbox)
const checked = Array.from(
document.getElementsByName(this.name)
).filter(el => el.checked);
// 3. 达到上限时,滚动至下一个 <h5> 标题
if (checked.length >= limit) {
const currentUl = this.closest('ul');
const nextHeading = currentUl?.nextElementSibling;
if (nextHeading && nextHeading.tagName === 'H5') {
nextHeading.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
}
}</h5>
✅ 完整初始化代码(无 jQuery 依赖)
以下代码使用纯 JavaScript + Bootstrap 5 事件机制,兼容动态渲染场景:
<script>
document.addEventListener('DOMContentLoaded', () => {
const modal = document.getElementById('toppings-properties-modal');
// 在模态框显示后绑定事件(避免 DOM 未就绪)
modal.addEventListener('shown.bs.modal', () => {
// 使用事件委托,避免重复绑定
document.querySelector('.modal-body').addEventListener('change', (e) => {
const target = e.target;
if (target.type === 'radio' || target.type === 'checkbox') {
scrollModalBodyToBottom.call(target);
}
});
});
function scrollModalBodyToBottom() {
const limit = this.type === 'radio'
? 1
: parseInt(this.dataset.maxqty ?? '1', 10);
const checked = Array.from(
document.getElementsByName(this.name)
).filter(el => el.checked);
if (checked.length >= limit) {
const currentUl = this.closest('ul');
const nextHeading = currentUl?.nextElementSibling;
if (nextHeading && nextHeading.tagName === 'H5') {
nextHeading.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
}
}
});
</script>
⚠️ 注意事项与最佳实践
-
结构依赖:本方案假设 HTML 中每个
后紧跟一个(如示例中的Crust Pizza [Giant]、Extra Cheese [Giant])。若结构变化,请将nextElementSibling替换为更鲁棒的查找方式(如currentUl.closest('.col-12').nextElementSibling.querySelector('h5')); -
data-maxqty必填:所有 checkbox 组必须设置data-maxqty属性(即使为1),否则默认按1处理; -
无障碍友好:
scrollIntoView({ block: 'start' })确保标题顶部对齐视口,避免被固定头部遮挡; -
性能优化:使用事件委托(
change代理到.modal-body)而非为每个 input 单独绑定,大幅提升动态列表性能; - 回退兼容:若用户取消已选选项导致未达上限,不会反向滚动——符合用户预期(滚动是“前进”提示,非强制导航)。
该方案轻量、可靠、语义清晰,无需额外依赖,可直接集成至现有 Bootstrap 5 弹窗系统,显著提升长表单的操作流畅度与完成率。










