• 完全响应式: 专为手机端优化,在平板和桌面浏览器上也能良好显示。
  • 现代设计: 使用简洁的卡片式布局,清晰的视觉层次。
  • 功能齐全: 包含商品选择、数量增减、价格实时计算、删除商品、优惠券输入、结算等功能。
  • 使用原生技术: 只用 HTML, CSS (Tailwind CSS), 和原生 JavaScript,易于理解和集成。
  • 用户体验良好: 包含加载动画、空购物车状态、价格格式化等细节。

最终预览效果


第一步:准备 HTML 结构

这是整个购物车页面的骨架,我们使用语义化的 HTML5 标签,并用 Tailwind CSS 的类名来快速构建样式。

html5 手机站购物车模板
(图片来源网络,侵删)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">购物车 - 手机商城</title>
    <!-- Tailwind CSS -->
    <script src="https://cdn.tailwindcss.com"></script>
    <!-- Font Awesome for icons -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <style>
        /* 自定义滚动条样式,使其更美观 */
        .custom-scrollbar::-webkit-scrollbar {
            width: 4px;
        }
        .custom-scrollbar::-webkit-scrollbar-track {
            background: #f1f1f1;
        }
        .custom-scrollbar::-webkit-scrollbar-thumb {
            background: #888;
            border-radius: 2px;
        }
        .custom-scrollbar::-webkit-scrollbar-thumb:hover {
            background: #555;
        }
        /* 防止 iOS 上橡皮筋效果 */
        body, html {
            overscroll-behavior-y: contain;
        }
    </style>
</head>
<body class="bg-gray-50">
    <!-- 顶部导航栏 -->
    <header class="bg-white shadow-sm sticky top-0 z-50">
        <div class="flex items-center justify-between p-4">
            <a href="#" class="text-gray-600">
                <i class="fas fa-arrow-left text-xl"></i>
            </a>
            <h1 class="text-lg font-semibold">购物车(3)</h1>
            <a href="#" class="text-gray-600">
                <i class="fas fa-ellipsis-v text-xl"></i>
            </a>
        </div>
    </header>
    <main class="pb-24">
        <!-- 购物车列表 -->
        <section class="p-4">
            <div id="cart-items" class="space-y-4 custom-scrollbar" style="max-height: calc(100vh - 180px); overflow-y: auto;">
                <!-- 购物车项模板 1 -->
                <div class="bg-white rounded-lg shadow-sm p-4 cart-item" data-price="299" data-id="1">
                    <div class="flex items-start">
                        <input type="checkbox" class="item-checkbox mt-1 w-5 h-5 text-blue-600 rounded" checked>
                        <img src="https://via.placeholder.com/80x80" alt="商品图片" class="w-20 h-20 object-cover rounded ml-3">
                        <div class="flex-1 ml-3">
                            <h3 class="font-medium text-gray-800 line-clamp-2">Apple AirPods Pro (第2代) 主动降噪无线蓝牙耳机</h3>
                            <p class="text-sm text-gray-500 mt-1">颜色: 白色</p>
                            <div class="flex items-center justify-between mt-3">
                                <p class="text-red-500 font-bold">
                                    <span class="symbol">¥</span><span class="item-price">299</span>
                                </p>
                                <div class="flex items-center border border-gray-300 rounded">
                                    <button class="quantity-btn minus px-3 py-1 text-gray-600 hover:bg-gray-100">
                                        <i class="fas fa-minus"></i>
                                    </button>
                                    <span class="quantity px-3 py-1 border-x border-gray-300">1</span>
                                    <button class="quantity-btn plus px-3 py-1 text-gray-600 hover:bg-gray-100">
                                        <i class="fas fa-plus"></i>
                                    </button>
                                </div>
                            </div>
                        </div>
                        <button class="delete-btn ml-2 text-gray-400 hover:text-red-500">
                            <i class="fas fa-trash-alt"></i>
                        </button>
                    </div>
                </div>
                <!-- 购物车项模板 2 -->
                <div class="bg-white rounded-lg shadow-sm p-4 cart-item" data-price="158" data-id="2">
                    <div class="flex items-start">
                        <input type="checkbox" class="item-checkbox mt-1 w-5 h-5 text-blue-600 rounded" checked>
                        <img src="https://via.placeholder.com/80x80" alt="商品图片" class="w-20 h-20 object-cover rounded ml-3">
                        <div class="flex-1 ml-3">
                            <h3 class="font-medium text-gray-800 line-clamp-2">小米手环 8 NFC版 智能运动手环 心率血氧睡眠监测</h3>
                            <p class="text-sm text-gray-500 mt-1">颜色: 黑色</p>
                            <div class="flex items-center justify-between mt-3">
                                <p class="text-red-500 font-bold">
                                    <span class="symbol">¥</span><span class="item-price">158</span>
                                </p>
                                <div class="flex items-center border border-gray-300 rounded">
                                    <button class="quantity-btn minus px-3 py-1 text-gray-600 hover:bg-gray-100">
                                        <i class="fas fa-minus"></i>
                                    </button>
                                    <span class="quantity px-3 py-1 border-x border-gray-300">2</span>
                                    <button class="quantity-btn plus px-3 py-1 text-gray-600 hover:bg-gray-100">
                                        <i class="fas fa-plus"></i>
                                    </button>
                                </div>
                            </div>
                        </div>
                        <button class="delete-btn ml-2 text-gray-400 hover:text-red-500">
                            <i class="fas fa-trash-alt"></i>
                        </button>
                    </div>
                </div>
                <!-- 购物车项模板 3 -->
                <div class="bg-white rounded-lg shadow-sm p-4 cart-item" data-price="45" data-id="3">
                    <div class="flex items-start">
                        <input type="checkbox" class="item-checkbox mt-1 w-5 h-5 text-blue-600 rounded">
                        <img src="https://via.placeholder.com/80x80" alt="商品图片" class="w-20 h-20 object-cover rounded ml-3">
                        <div class="flex-1 ml-3">
                            <h3 class="font-medium text-gray-800 line-clamp-2">Anker 安克 20W 氮化镓充电器 GaNPrime 轻薄快充</h3>
                            <p class="text-sm text-gray-500 mt-1">颜色: 白色</p>
                            <div class="flex items-center justify-between mt-3">
                                <p class="text-red-500 font-bold">
                                    <span class="symbol">¥</span><span class="item-price">45</span>
                                </p>
                                <div class="flex items-center border border-gray-300 rounded">
                                    <button class="quantity-btn minus px-3 py-1 text-gray-600 hover:bg-gray-100">
                                        <i class="fas fa-minus"></i>
                                    </button>
                                    <span class="quantity px-3 py-1 border-x border-gray-300">1</span>
                                    <button class="quantity-btn plus px-3 py-1 text-gray-600 hover:bg-gray-100">
                                        <i class="fas fa-plus"></i>
                                    </button>
                                </div>
                            </div>
                        </div>
                        <button class="delete-btn ml-2 text-gray-400 hover:text-red-500">
                            <i class="fas fa-trash-alt"></i>
                        </button>
                    </div>
                </div>
            </div>
        </section>
        <!-- 空购物车提示 (默认隐藏) -->
        <div id="empty-cart" class="hidden flex flex-col items-center justify-center p-8 text-center">
            <i class="fas fa-shopping-cart text-6xl text-gray-300 mb-4"></i>
            <p class="text-gray-500 text-lg">购物车还是空的</p>
            <a href="#" class="mt-4 bg-blue-500 text-white px-6 py-2 rounded-full">去逛逛</a>
        </div>
    </main>
    <!-- 底部结算栏 -->
    <footer class="fixed bottom-0 left-0 right-0 bg-white border-t border-gray-200">
        <div class="flex items-center justify-between p-4">
            <div class="flex items-center">
                <input type="checkbox" id="select-all" class="w-5 h-5 text-blue-600 rounded mr-2">
                <label for="select-all" class="text-gray-700">全选</label>
            </div>
            <div class="flex items-center">
                <div class="text-right mr-4">
                    <p class="text-sm text-gray-500">合计:</p>
                    <p class="text-red-500 font-bold text-lg">
                        <span class="symbol">¥</span><span id="total-price">756</span>
                    </p>
                </div>
                <button id="checkout-btn" class="bg-red-500 text-white px-6 py-2 rounded-full font-medium">
                    结算(2)
                </button>
            </div>
        </div>
    </footer>
    <!-- 删除确认弹窗 (默认隐藏) -->
    <div id="delete-modal" class="hidden fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
        <div class="bg-white rounded-lg p-6 w-80 mx-4">
            <h3 class="text-lg font-semibold mb-2">确认删除</h3>
            <p class="text-gray-600 mb-6">您确定要从购物车中删除该商品吗?</p>
            <div class="flex justify-end space-x-3">
                <button id="cancel-delete" class="px-4 py-2 border border-gray-300 rounded text-gray-700">取消</button>
                <button id="confirm-delete" class="px-4 py-2 bg-red-500 text-white rounded">确定</button>
            </div>
        </div>
    </div>
    <script src="cart.js"></script>
</body>
</html>

第二步:编写 JavaScript 逻辑 (cart.js)

这是让购物车“活”起来的核心部分,我们把它放在一个单独的 cart.js 文件中,并在 HTML 的末尾引入。

document.addEventListener('DOMContentLoaded', () => {
    // --- DOM 元素 ---
    const cartItemsContainer = document.getElementById('cart-items');
    const emptyCartMsg = document.getElementById('empty-cart');
    const selectAllCheckbox = document.getElementById('select-all');
    const totalPriceElement = document.getElementById('total-price');
    const checkoutBtn = document.getElementById('checkout-btn');
    const deleteModal = document.getElementById('delete-modal');
    const cancelDeleteBtn = document.getElementById('cancel-delete');
    const confirmDeleteBtn = document.getElementById('confirm-delete');
    const cartCountTitle = document.querySelector('h1');
    let itemToDelete = null;
    // --- 工具函数 ---
    function formatPrice(price) {
        return price.toFixed(2);
    }
    function updateCartCount() {
        const checkedItems = document.querySelectorAll('.item-checkbox:checked');
        const count = checkedItems.length;
        cartCountTitle.textContent = `购物车(${count})`;
        checkoutBtn.textContent = `结算(${count})`;
    }
    function updateTotalPrice() {
        let total = 0;
        const checkedItems = document.querySelectorAll('.item-checkbox:checked');
        checkedItems.forEach(item => {
            const cartItem = item.closest('.cart-item');
            const price = parseFloat(cartItem.dataset.price);
            const quantity = parseInt(cartItem.querySelector('.quantity').textContent);
            total += price * quantity;
        });
        totalPriceElement.textContent = formatPrice(total);
    }
    function toggleEmptyCart() {
        const totalItems = document.querySelectorAll('.cart-item').length;
        if (totalItems === 0) {
            cartItemsContainer.classList.add('hidden');
            emptyCartMsg.classList.remove('hidden');
        } else {
            cartItemsContainer.classList.remove('hidden');
            emptyCartMsg.classList.add('hidden');
        }
    }
    // --- 事件监听器 ---
    // 1. 单个商品选择
    cartItemsContainer.addEventListener('change', (e) => {
        if (e.target.classList.contains('item-checkbox')) {
            updateTotalPrice();
            updateCartCount();
            // 检查是否需要更新“全选”框的状态
            const allCheckboxes = document.querySelectorAll('.item-checkbox');
            const checkedCheckboxes = document.querySelectorAll('.item-checkbox:checked');
            selectAllCheckbox.checked = allCheckboxes.length === checkedCheckboxes.length;
        }
    });
    // 2. 全选/取消全选
    selectAllCheckbox.addEventListener('change', () => {
        const itemCheckboxes = document.querySelectorAll('.item-checkbox');
        itemCheckboxes.forEach(checkbox => {
            checkbox.checked = selectAllCheckbox.checked;
        });
        updateTotalPrice();
        updateCartCount();
    });
    // 3. 数量增减
    cartItemsContainer.addEventListener('click', (e) => {
        const btn = e.target.closest('.quantity-btn');
        if (!btn) return;
        const quantitySpan = btn.parentElement.querySelector('.quantity');
        let quantity = parseInt(quantitySpan.textContent);
        if (btn.classList.contains('plus')) {
            quantity++;
        } else if (btn.classList.contains('minus') && quantity > 1) {
            quantity--;
        }
        quantitySpan.textContent = quantity;
        updateTotalPrice(); // 数量改变,总价重新计算
    });
    // 4. 删除商品
    cartItemsContainer.addEventListener('click', (e) => {
        const deleteBtn = e.target.closest('.delete-btn');
        if (!deleteBtn) return;
        itemToDelete = deleteBtn.closest('.cart-item');
        deleteModal.classList.remove('hidden');
    });
    // 5. 确认删除
    confirmDeleteBtn.addEventListener('click', () => {
        if (itemToDelete) {
            itemToDelete.remove();
            itemToDelete = null;
            deleteModal.classList.add('hidden');
            // 更新UI
            updateTotalPrice();
            updateCartCount();
            toggleEmptyCart();
            // 重新绑定全选逻辑
            const allCheckboxes = document.querySelectorAll('.item-checkbox');
            const checkedCheckboxes = document.querySelectorAll('.item-checkbox:checked');
            selectAllCheckbox.checked = allCheckboxes.length > 0 && allCheckboxes.length === checkedCheckboxes.length;
        }
    });
    // 6. 取消删除
    cancelDeleteBtn.addEventListener('click', () => {
        itemToDelete = null;
        deleteModal.classList.add('hidden');
    });
    // 7. 结算按钮
    checkoutBtn.addEventListener('click', () => {
        const checkedCount = document.querySelectorAll('.item-checkbox:checked').length;
        if (checkedCount === 0) {
            alert('请至少选择一件商品');
            return;
        }
        // 这里跳转到结算页面
        alert(`正在结算 ${checkedCount} 件商品...`);
    });
    // --- 初始化 ---
    updateTotalPrice();
    updateCartCount();
    toggleEmptyCart();
});

如何使用这个模板

  1. 创建文件: 创建三个文件:index.htmlcart.js 和一个空的 styles.css(如果不需要,可以省略)。
  2. 复制代码: 将上面的 HTML 代码粘贴到 index.html 中,将 JavaScript 代码粘贴到 cart.js 中。
  3. 引入依赖: 确保你的 HTML 文件中通过 CDN 引入了 Tailwind CSS 和 Font Awesome。
  4. 运行: 直接在浏览器中打开 index.html 文件即可看到效果,由于是静态页面,无需服务器。

扩展和自定义建议

  • 数据源: 目前数据是硬编码的,在实际项目中,你需要通过 JavaScript 从服务器 API 获取购物车数据,然后动态渲染到页面上。
  • 优惠券: 可以添加一个输入框和验证逻辑,在计算总价时减去优惠券金额。
  • 运费: 可以添加一个运费计算逻辑,根据总价或商品数量来决定是否收取运费。
  • 图片懒加载: 对于商品列表,可以使用 loading="lazy" 属性来优化图片加载性能。
  • 动画: 可以使用 CSS transitions 或 JavaScript 动画库(如 AOS)来添加删除、数量变化等微交互,提升用户体验。

这个模板为您提供了一个坚实的起点,您可以根据自己的业务需求进行快速修改和扩展。

html5 手机站购物车模板
(图片来源网络,侵删)