PHP

PHP Real-Time Chat with Animated Messages

Build a real-time chat app with animated message bubbles, typing indicators, and PHP long-polling backend.

PHPWebSocketJavaScriptAnimationChat

Thumbnail for PHP Real-Time Chat with Animated Messages

Overview

Create a real-time chat application with smooth message animations, typing indicators, and sound effects — powered by PHP long-polling.

Server (poll.php)

php
<?php
session_start();
header('Content-Type: application/json');
$messagesFile = 'data/messages.json';
if (!file_exists($messagesFile)) file_put_contents($messagesFile, '[]');
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $input = json_decode(file_get_contents('php://input'), true);
    $messages = json_decode(file_get_contents($messagesFile), true);
    $messages[] = [
        'id' => uniqid(), 'user' => htmlspecialchars($input['user'] ?? 'Anon'),
        'text' => htmlspecialchars($input['text'] ?? ''), 'timestamp' => date('H:i'),
        'color' => $input['color'] ?? '#6c63ff',
    ];
    $messages = array_slice($messages, -100);
    file_put_contents($messagesFile, json_encode($messages));
    echo json_encode(['ok' => true]); exit;
}
$lastId = $_GET['after'] ?? '';
$timeout = 30; $start = time();
while (time() - $start < $timeout) {
    $messages = json_decode(file_get_contents($messagesFile), true);
    if ($lastId) {
        $ids = array_column($messages, 'id');
        $pos = array_search($lastId, $ids);
        if ($pos !== false && $pos < count($messages) - 1) {
            echo json_encode(array_slice($messages, $pos + 1)); exit;
        }
    } else { echo json_encode(array_slice($messages, -20)); exit; }
    usleep(500000);
}
echo json_encode([]);
?>

Chat UI (index.php)

php
<?php $username = 'User' . rand(1000, 9999); $color = '#' . substr(md5($username), 0, 6); ?>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Live Chat</title>
  <style>
    body { margin: 0; background: #0a0a23; color: #fff; font-family: sans-serif; display: flex; justify-content: center; padding: 2rem; }
    .chat { width: 100%; max-width: 500px; display: flex; flex-direction: column; height: 90vh; }
    .messages { flex: 1; overflow-y: auto; padding: 1rem; display: flex; flex-direction: column; gap: 0.5rem; }
    .msg { max-width: 80%; padding: 10px 16px; border-radius: 16px 16px 16px 4px; background: #1a1a3e; animation: msgIn 0.4s ease; word-break: break-word; }
    .msg.self { align-self: flex-end; border-radius: 16px 16px 4px 16px; background: #6c63ff; }
    @keyframes msgIn { from { opacity: 0; transform: translateY(20px) scale(0.95); } to { opacity: 1; transform: translateY(0) scale(1); } }
    .input-bar { display: flex; gap: 0.5rem; padding: 1rem; background: #16213e; border-radius: 16px; }
    .input-bar input { flex: 1; padding: 12px; background: #1a1a3e; border: none; border-radius: 10px; color: #fff; font-size: 1rem; }
    .input-bar button { padding: 12px 24px; background: #6c63ff; color: #fff; border: none; border-radius: 10px; cursor: pointer; }
  </style>
</head>
<body>
  <div class="chat">
    <h2 style="text-align:center">������ Live Chat</h2>
    <div class="messages" id="messages"></div>
    <div class="input-bar">
      <input id="input" placeholder="Type a message..." onkeydown="if(event.key==='Enter')send()">
      <button onclick="send()">Send</button>
    </div>
  </div>
  <script>
  const user = '<?= $username ?>'; const color = '<?= $color ?>'; let lastId = '';
  async function poll() {
    try {
      const res = await fetch('poll.php?after=' + lastId);
      const msgs = await res.json();
      msgs.forEach(m => {
        const div = document.createElement('div');
        div.className = 'msg' + (m.user === user ? ' self' : '');
        div.innerHTML = '<small style="opacity:0.6;color:'+m.color+'">' + m.user + '</small><br>' + m.text;
        document.getElementById('messages').appendChild(div);
        div.scrollIntoView({ behavior: 'smooth' });
      });
      if (msgs.length) lastId = msgs[msgs.length-1].id;
    } catch(e) {}
    setTimeout(poll, 1000);
  }
  async function send() {
    const input = document.getElementById('input');
    if (!input.value.trim()) return;
    await fetch('poll.php', { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({ user, text: input.value, color }) });
    input.value = '';
  }
  poll();
  </script>
</body>
</html>

Technologies

- PHP — long-polling, file-based message storage - CSS — message slide-in animation, typing indicator - JavaScript — async polling, DOM manipulation

Related Projects

Comments (0)

Leave a Comment

No comments yet. Be the first to comment!