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

如何创建含复杂HTML/CSS元素的Modal Popup并实现步骤切换?

问题描述

我有一套目的地选择页面代码,需要实现点击「Next」按钮触发模态弹窗,弹窗要支持复杂HTML/CSS样式,还要实现弹窗内的步骤切换功能。之前写的弹窗代码运行异常,还会影响网站其他部分的CSS,求完善。


修复后的完整代码

HTML

<div class="destination-options">
  <div class="destination" onclick="toggleSelection(this)">Serengeti National Park</div>
  <div class="destination" onclick="toggleSelection(this)">Ngorongoro Crater</div>
  <div class="destination" onclick="toggleSelection(this)">Lake Manyara National Park</div>
  <div class="destination" onclick="toggleSelection(this)">Tarangire National Park</div>
  <div class="destination" onclick="toggleSelection(this)">Arusha National Park</div>
  <div class="destination" onclick="toggleSelection(this)">Stone Town</div>
  <div class="destination" onclick="toggleSelection(this)">Beach Holiday</div>
  <div class="destination" onclick="toggleSelection(this)">Udzungwa National Park</div>
  <div class="destination" onclick="toggleSelection(this)">Olduvai Gorge</div>
  <div class="destination" onclick="toggleSelection(this)">Mountain Kilimanjaro Climbing</div>
  <div class="destination" onclick="toggleSelection(this)">I have not yet decided, please help me decide exciting places</div>
  <div class="destination" onclick="toggleSelection(this)">Volunteer</div>
</div>
<button id="continue-btn" onclick="openModal()">Next</button>

<!-- 模态弹窗 -->
<div id="custom-modal" class="destination-modal">
  <div class="modal-container">
    <!-- 步骤导航 -->
    <div class="modal-steps">
      <div class="step-item active" data-step="1">确认选择</div>
      <div class="step-item" data-step="2">填写信息</div>
      <div class="step-item" data-step="3">完成</div>
    </div>

    <!-- 步骤内容 -->
    <div class="modal-content-wrapper">
      <!-- 步骤1:确认目的地 -->
      <div class="step-content active" id="step1">
        <h3>已选目的地</h3>
        <div id="selected-destinations" class="selected-list"></div>
        <div class="modal-actions">
          <button onclick="closeModal()">取消</button>
          <button onclick="goToStep(2)">下一步</button>
        </div>
      </div>

      <!-- 步骤2:填写信息 -->
      <div class="step-content" id="step2">
        <h3>补充出行信息</h3>
        <div class="form-group">
          <label>出行人数</label>
          <input type="number" min="1" value="1">
        </div>
        <div class="form-group">
          <label>预计出行时间</label>
          <input type="date">
        </div>
        <div class="modal-actions">
          <button onclick="goToStep(1)">上一步</button>
          <button onclick="goToStep(3)">下一步</button>
        </div>
      </div>

      <!-- 步骤3:完成 -->
      <div class="step-content" id="step3">
        <h3>提交成功!</h3>
        <p>我们会尽快与您联系,为您定制专属行程</p>
        <div class="modal-actions">
          <button onclick="closeModal()">关闭</button>
        </div>
      </div>
    </div>
  </div>
</div>

CSS

/* 全局基础样式(保留原有功能) */
body {
  font-family: Arial, sans-serif;
  text-align: center;
  margin: 0;
}

h1 {
  font-size: 24px;
}

.destination-options {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 10px;
  text-align: center;
  padding: 20px;
}

.destination {
  flex: 0 1 auto;
  color: #202f1c;
  padding: 8px 16px;
  cursor: pointer;
  user-select: none;
  border-radius: 100px;
  border: 1px solid #A67c39;
  text-align: center;
  font-size: 14px;
  white-space: nowrap;
  margin: 5px;
  transition: all 0.3s ease;
}

.destination.selected {
  background-color: #A67C39;
  color: #15100B;
}

#continue-btn {
  background-color: #000000;
  color: white;
  border: none;
  border-radius: 100px;
  margin-top: 20px;
  padding: 10px 70px;
  font-weight: bold;
  cursor: pointer;
  transition: background-color 0.3s ease;
}

#continue-btn:hover {
  background-color: #A67c39;
}

@media screen and (max-width: 768px) {
  .destination {
    font-size: 12px;
    padding: 6px 12px;
  }
}

/* 弹窗专属样式(使用命名空间隔离,避免影响全局) */
.destination-modal {
  display: none;
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.7);
  z-index: 9999;
  overflow-y: auto;
}

.modal-container {
  background-color: #fff;
  border-radius: 16px;
  width: 90%;
  max-width: 500px;
  margin: 5% auto;
  padding: 24px;
  box-shadow: 0 8px 32px rgba(0,0,0,0.2);
  position: relative;
}

/* 步骤导航 */
.modal-steps {
  display: flex;
  justify-content: space-between;
  margin-bottom: 24px;
  padding-bottom: 16px;
  border-bottom: 1px solid #eee;
}

.step-item {
  flex: 1;
  text-align: center;
  font-weight: 500;
  color: #999;
  position: relative;
  cursor: pointer;
  padding-bottom: 8px;
}

.step-item.active {
  color: #A67C39;
}

.step-item.active::after {
  content: '';
  position: absolute;
  bottom: -1px;
  left: 0;
  width: 100%;
  height: 2px;
  background-color: #A67C39;
}

/* 步骤内容 */
.step-content {
  display: none;
}

.step-content.active {
  display: block;
  animation: fadeIn 0.3s ease;
}

@keyframes fadeIn {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
}

.selected-list {
  background-color: #f8f8f8;
  padding: 12px;
  border-radius: 8px;
  margin: 16px 0;
  text-align: left;
  line-height: 1.5;
}

/* 表单样式 */
.form-group {
  margin-bottom: 16px;
  text-align: left;
}

.form-group label {
  display: block;
  margin-bottom: 6px;
  font-weight: 500;
  color: #333;
}

.form-group input {
  width: 100%;
  padding: 8px 12px;
  border: 1px solid #ddd;
  border-radius: 8px;
  font-size: 14px;
  box-sizing: border-box;
}

/* 弹窗按钮组 */
.modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
  margin-top: 24px;
}

.modal-actions button {
  padding: 8px 20px;
  border: none;
  border-radius: 8px;
  font-weight: 500;
  cursor: pointer;
  transition: background-color 0.3s ease;
}

.modal-actions button:first-child {
  background-color: #f0f0f0;
  color: #333;
}

.modal-actions button:first-child:hover {
  background-color: #e0e0e0;
}

.modal-actions button:last-child {
  background-color: #A67C39;
  color: #fff;
}

.modal-actions button:last-child:hover {
  background-color: #8a642d;
}

JavaScript

let selectedDestinations = [];
let currentStep = 1;

// 目的地选择切换
function toggleSelection(element) {
  if (element.classList.contains("selected")) {
    element.classList.remove("selected");
    selectedDestinations = selectedDestinations.filter(item => item !== element.textContent.trim());
  } else {
    element.classList.add("selected");
    selectedDestinations.push(element.textContent.trim());
  }
}

// 打开弹窗
function openModal() {
  if (selectedDestinations.length === 0) {
    alert("请至少选择一个目的地");
    return;
  }
  
  // 更新弹窗内的已选目的地
  const selectedEl = document.getElementById("selected-destinations");
  selectedEl.innerHTML = selectedDestinations.map(dest => `<div>• ${dest}</div>`).join('');
  
  // 重置步骤到第一步
  currentStep = 1;
  updateStepDisplay();
  
  // 显示弹窗
  const modal = document.getElementById("custom-modal");
  modal.style.display = "block";
}

// 关闭弹窗
function closeModal() {
  const modal = document.getElementById("custom-modal");
  modal.style.display = "none";
}

// 切换步骤
function goToStep(stepNum) {
  currentStep = stepNum;
  updateStepDisplay();
}

// 更新步骤显示状态
function updateStepDisplay() {
  // 更新步骤导航
  document.querySelectorAll('.step-item').forEach(item => {
    item.classList.remove('active');
    if (parseInt(item.dataset.step) === currentStep) {
      item.classList.add('active');
    }
  });
  
  // 更新步骤内容
  document.querySelectorAll('.step-content').forEach(content => {
    content.classList.remove('active');
  });
  document.getElementById(`step${currentStep}`).classList.add('active');
}

// 点击弹窗外部关闭弹窗
window.onclick = function(event) {
  const modal = document.getElementById("custom-modal");
  if (event.target === modal) {
    closeModal();
  }
}

关键改进说明

  1. CSS样式隔离:使用destination-modal作为弹窗命名空间前缀,所有弹窗样式嵌套在此类下,彻底避免与网站其他CSS冲突。
  2. 修复原有代码问题:
    • 修正原代码中align items: center的语法错误(应为align-items: center)
    • 调整目的地选项的flex属性,避免小屏幕布局错乱
  3. 完善弹窗功能:
    • 添加步骤导航栏与多步骤内容区域,支持自由切换步骤
    • 新增点击弹窗外部关闭的交互逻辑
    • 已选目的地改为列表式展示,视觉更清晰
  4. 增强用户体验:
    • 加入步骤切换的淡入动画
    • 优化按钮与选择项的hover交互效果
    • 统一步骤切换逻辑,代码更易维护

内容的提问来源于stack exchange,提问作者Charles Moses

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 02:59:53