1. 移动优先设计:专为手机屏幕优化,使用响应式布局。
  2. 现代化UI:采用类似主流App(如微信、WhatsApp)的设计风格,简洁美观。
  3. 功能完整:包含消息发送、接收、时间戳、输入框、表情按钮、模拟“正在输入”状态等。
  4. 代码清晰:HTML、CSS(使用Tailwind CSS)和JavaScript分离,易于理解和修改。
  5. 可扩展性强:你可以轻松地添加更多功能,如文件发送、语音消息、视频通话等。

最终效果预览

这是一个静态图片,展示了模板在不同状态下的样子,实际代码是可交互的。

手机web聊天html模板
(图片来源网络,侵删)

第一步:准备工作

我们将使用 Tailwind CSS 来快速构建现代化的UI,你不需要下载任何东西,只需在HTML文件中引入其CDN链接即可。


第二步:完整代码

将以下所有代码复制到一个 .html 文件中,然后用浏览器打开即可看到效果,建议在手机浏览器或浏览器的“设备模拟器”模式下查看,体验更佳。

<!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">手机Web聊天</title>
    <!-- Tailwind CSS CDN -->
    <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;
        }
        /* 消息气泡动画 */
        @keyframes slideIn {
            from {
                opacity: 0;
                transform: translateY(10px);
            }
            to {
                opacity: 1;
                transform: translateY(0);
            }
        }
        .message-bubble {
            animation: slideIn 0.2s ease-out;
        }
    </style>
</head>
<body class="bg-gray-100 h-screen flex flex-col overflow-hidden">
    <!-- 1. 聊天头部 -->
    <header class="bg-indigo-600 text-white p-4 flex items-center justify-between shadow-md">
        <div class="flex items-center">
            <button class="mr-3">
                <i class="fas fa-chevron-left text-xl"></i>
            </button>
            <img src="https://i.pravatar.cc/150?img=1" alt="Avatar" class="w-10 h-10 rounded-full mr-3">
            <div>
                <h1 class="font-semibold text-lg">张三</h1>
                <p class="text-xs opacity-80">在线</p>
            </div>
        </div>
        <div class="flex space-x-4">
            <button>
                <i class="fas fa-phone text-xl"></i>
            </button>
            <button>
                <i class="fas fa-ellipsis-v text-xl"></i>
            </button>
        </div>
    </header>
    <!-- 2. 聊天内容区域 -->
    <main id="chat-container" class="flex-grow overflow-y-auto p-4 space-y-4 custom-scrollbar bg-gray-50">
        <!-- 系统消息/日期分隔符 -->
        <div class="flex justify-center my-4">
            <span class="bg-gray-300 text-gray-600 text-xs px-3 py-1 rounded-full">lt;/span>
        </div>
        <!-- 接收到的消息 -->
        <div class="flex items-start">
            <img src="https://i.pravatar.cc/150?img=1" alt="Avatar" class="w-8 h-8 rounded-full mr-2">
            <div class="max-w-xs lg:max-w-md">
                <div class="bg-white p-3 rounded-2xl rounded-tl-none shadow-sm message-bubble">
                    <p class="text-gray-800">你好,最近怎么样?</p>
                </div>
                <p class="text-xs text-gray-500 mt-1 ml-2">10:30</p>
            </div>
        </div>
        <!-- 发送的消息 -->
        <div class="flex items-start justify-end">
            <div class="max-w-xs lg:max-w-md">
                <div class="bg-indigo-600 text-white p-3 rounded-2xl rounded-tr-none shadow-sm message-bubble">
                    <p>挺好的,你呢?项目进展顺利吗?</p>
                </div>
                <p class="text-xs text-gray-500 mt-1 mr-2 text-right">10:32</p>
            </div>
        </div>
        <!-- 接收到的长文本消息 -->
        <div class="flex items-start">
            <img src="https://i.pravatar.cc/150?img=1" alt="Avatar" class="w-8 h-8 rounded-full mr-2">
            <div class="max-w-xs lg:max-w-md">
                <div class="bg-white p-3 rounded-2xl rounded-tl-none shadow-sm message-bubble">
                    <p class="text-gray-800">还不错,已经完成了80%了,遇到了一些技术难题,不过正在解决中,你那边有什么新的想法吗?</p>
                </div>
                <p class="text-xs text-gray-500 mt-1 ml-2">10:35</p>
            </div>
        </div>
        <!-- 发送的消息(带表情) -->
        <div class="flex items-start justify-end">
            <div class="max-w-xs lg:max-w-md">
                <div class="bg-indigo-600 text-white p-3 rounded-2xl rounded-tr-none shadow-sm message-bubble">
                    <p>太棒了!加油!🚀</p>
                </div>
                <p class="text-xs text-gray-500 mt-1 mr-2 text-right">10:36</p>
            </div>
        </div>
        <!-- 模拟“正在输入”状态 -->
        <div id="typing-indicator" class="flex items-start hidden">
            <img src="https://i.pravatar.cc/150?img=1" alt="Avatar" class="w-8 h-8 rounded-full mr-2">
            <div class="bg-white p-3 rounded-2xl rounded-tl-none shadow-sm">
                <div class="flex space-x-1">
                    <div class="w-2 h-2 bg-gray-400 rounded-full animate-bounce" style="animation-delay: 0ms;"></div>
                    <div class="w-2 h-2 bg-gray-400 rounded-full animate-bounce" style="animation-delay: 150ms;"></div>
                    <div class="w-2 h-2 bg-gray-400 rounded-full animate-bounce" style="animation-delay: 300ms;"></div>
                </div>
            </div>
        </div>
    </main>
    <!-- 3. 输入区域 -->
    <footer class="bg-white border-t border-gray-200 p-3">
        <div class="flex items-center">
            <button class="text-gray-500 mr-3 p-2">
                <i class="fas fa-plus-circle text-2xl"></i>
            </button>
            <div class="flex-grow relative">
                <input 
                    type="text" 
                    id="message-input"
                    placeholder="输入消息..." 
                    class="w-full bg-gray-100 rounded-full py-2 px-4 pr-10 focus:outline-none focus:ring-2 focus:ring-indigo-500"
                >
                <button class="absolute right-2 top-1/2 transform -translate-y-1/2 text-gray-500">
                    <i class="far fa-smile text-xl"></i>
                </button>
            </div>
            <button id="send-button" class="ml-3 bg-indigo-600 text-white rounded-full w-10 h-10 flex items-center justify-center focus:outline-none focus:ring-2 focus:ring-indigo-500">
                <i class="fas fa-paper-plane"></i>
            </button>
        </div>
    </footer>
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const chatContainer = document.getElementById('chat-container');
            const messageInput = document.getElementById('message-input');
            const sendButton = document.getElementById('send-button');
            const typingIndicator = document.getElementById('typing-indicator');
            // 自动滚动到底部
            function scrollToBottom() {
                chatContainer.scrollTop = chatContainer.scrollHeight;
            }
            // 模拟对方正在输入
            function simulateTyping() {
                typingIndicator.classList.remove('hidden');
                scrollToBottom();
                setTimeout(() => {
                    typingIndicator.classList.add('hidden');
                    // 模拟对方回复
                    receiveMessage();
                }, 2000); // 2秒后停止输入并发送消息
            }
            // 发送消息
            function sendMessage() {
                const message = messageInput.value.trim();
                if (message) {
                    addMessageToChat(message, 'sent');
                    messageInput.value = '';
                    scrollToBottom();
                    // 模拟对方回复
                    setTimeout(simulateTyping, 1000);
                }
            }
            // 接收消息
            function receiveMessage() {
                const replies = [
                    "收到!",
                    "明白了,谢谢!",
                    "这个想法不错,我们讨论一下。",
                    "哈哈,有道理。",
                    "稍后我看看,有情况再联系你。"
                ];
                const randomReply = replies[Math.floor(Math.random() * replies.length)];
                addMessageToChat(randomReply, 'received');
                scrollToBottom();
            }
            // 将消息添加到聊天界面
            function addMessageToChat(message, type) {
                const messageDiv = document.createElement('div');
                const now = new Date();
                const timeString = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}`;
                if (type === 'sent') {
                    messageDiv.className = 'flex items-start justify-end';
                    messageDiv.innerHTML = `
                        <div class="max-w-xs lg:max-w-md">
                            <div class="bg-indigo-600 text-white p-3 rounded-2xl rounded-tr-none shadow-sm message-bubble">
                                <p>${message}</p>
                            </div>
                            <p class="text-xs text-gray-500 mt-1 mr-2 text-right">${timeString}</p>
                        </div>
                    `;
                } else {
                    messageDiv.className = 'flex items-start';
                    messageDiv.innerHTML = `
                        <img src="https://i.pravatar.cc/150?img=1" alt="Avatar" class="w-8 h-8 rounded-full mr-2">
                        <div class="max-w-xs lg:max-w-md">
                            <div class="bg-white p-3 rounded-2xl rounded-tl-none shadow-sm message-bubble">
                                <p class="text-gray-800">${message}</p>
                            </div>
                            <p class="text-xs text-gray-500 mt-1 ml-2">${timeString}</p>
                        </div>
                    `;
                }
                // 在“正在输入”提示之前插入消息
                const typingIndicatorIndex = Array.from(chatContainer.children).indexOf(typingIndicator);
                if (typingIndicatorIndex !== -1) {
                    chatContainer.insertBefore(messageDiv, typingIndicator);
                } else {
                    chatContainer.appendChild(messageDiv);
                }
            }
            // 事件监听
            sendButton.addEventListener('click', sendMessage);
            messageInput.addEventListener('keypress', (e) => {
                if (e.key === 'Enter') {
                    sendMessage();
                }
            });
        });
    </script>
</body>
</html>

第三步:代码解析

HTML 结构

  • <header>: 聊天顶部,包含返回按钮、头像、联系人名称和在线状态,以及通话和更多选项按钮。
  • `
    : 聊天记录显示区域。
    • flex-grow: 让这个区域占据所有剩余空间。
    • overflow-y-auto: 允许内容垂直滚动。
    • space-y-4: 为每条消息之间添加垂直间距。
    • 消息使用 flex 布局,通过 justify-start (接收) 和 justify-end (发送) 来控制左右对齐。
    • 消息气泡 rounded-2xlrounded-tl-none/rounded-tr-none 实现了尖角效果。
  • <footer>: 底部输入区域,包含加号按钮(扩展功能)、输入框、表情按钮和发送按钮。

CSS (内嵌在 <style> 标签中)

  • Tailwind CSS: 通过CDN引入,提供了大量的实用类,如 bg-indigo-600, text-white, p-4, rounded-full 等,极大简化了样式编写。
  • 自定义滚动条: .custom-scrollbar 类定义了更美观的滚动条样式。
  • 消息动画: @keyframes slideIn.message-bubble 类让新消息出现时有一个平滑的滑入效果。
  • “正在输入”动画: 使用了 animate-bounce 和不同的 animation-delay 实现了三个小圆点的跳动效果。

JavaScript (内嵌在 <script> 标签中)

这是实现交互功能的核心部分。

  • scrollToBottom(): 一个辅助函数,用于在消息更新后自动将聊天窗口滚动到底部。
  • simulateTyping(): 模拟对方正在输入,它显示“正在输入”动画,2秒后自动隐藏,并调用 receiveMessage() 来模拟一条自动回复。
  • sendMessage():
    1. 获取输入框的值。
    2. 检查值是否为空。
    3. 调用 addMessageToChat() 将消息添加到界面(类型为 sent)。
    4. 清空输入框。
    5. 设置一个1秒的延迟,然后调用 simulateTyping() 来模拟对方回复。
  • receiveMessage(): 从一个预设的回复数组中随机选择一条消息,然后调用 addMessageToChat() 将其添加到界面(类型为 received)。
  • addMessageToChat(message, type):
    1. 创建一个新的 div 元素来包裹整条消息(包括头像、气泡和时间戳)。
    2. 根据消息类型(sentreceived)生成不同的HTML结构,实现左右对齐和不同的气泡颜色。
    3. 获取当前时间并格式化。
    4. 使用 innerHTML 将生成的HTML插入到 chat-container 中,它会智能地处理“正在输入”提示的位置。
  • 事件监听:
    • 为发送按钮和输入框绑定 clickkeypress 事件,实现点击按钮或按回车键都能发送消息。

如何扩展和修改?

  1. 更换头像: 修改 <img src="..."> 中的 src 属性,可以链接到任何图片URL或本地图片路径。
  2. 修改颜色主题: 修改 headerbg-indigo-600 和发送消息气泡的 bg-indigo-600 为你喜欢的颜色代码(如 bg-blue-500, bg-green-500)。
  3. 添加新功能:
    • 文件发送: 在加号按钮的弹出菜单中添加一个文件输入 <input type="file">,然后通过JavaScript读取文件并显示文件名或预览图。
    • 语音消息: 可以添加一个录音按钮,使用 MediaRecorder API 来录制并发送语音片段。
    • 更多联系人: 你可以为每个联系人创建一个聊天窗口,通过JavaScript来切换显示。
  4. 连接后端: 目前所有消息都是模拟的,要实现真实聊天,你需要将 sendMessagereceiveMessage 中的逻辑替换为使用 fetchaxios 等库与你的后端API进行通信(发送消息到服务器,并从服务器接收新消息)。
手机web聊天html模板
(图片来源网络,侵删)