Design a modern chat interface with message bubbles and real-time features.
This project will guide you through creating a modern chat interface using CSS. You'll learn to design message bubbles, user avatars, and responsive layouts.
Intermediate: 2-3 hours | Advanced: 1-2 hours
Difficulty Level: Intermediate
<div class="chat-container">
<div class="chat-header">
<div class="user-info">
<img src="avatar.jpg" alt="User Avatar" class="avatar">
<div>
<h3>John Doe</h3>
<span class="status">Online</span>
</div>
</div>
</div>
<div class="chat-messages">
<div class="message received">
<img src="user1.jpg" alt="User 1" class="message-avatar">
<div class="message-content">
<p>Hey! How are you doing?</p>
<span class="timestamp">10:30 AM</span>
</div>
</div>
<div class="message sent">
<div class="message-content">
<p>I'm doing great! Thanks for asking.</p>
<span class="timestamp">10:32 AM</span>
</div>
</div>
</div>
<div class="chat-input">
<input type="text" placeholder="Type a message...">
<button class="send-btn"><i class="fas fa-paper-plane"></i></button>
</div>
</div>
.chat-container {
max-width: 400px;
height: 600px;
margin: 2rem auto;
background: white;
border-radius: 20px;
box-shadow: 0 10px 30px rgba(0,0,0,0.1);
display: flex;
flex-direction: column;
overflow: hidden;
}
.chat-header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 1rem;
}
.user-info {
display: flex;
align-items: center;
gap: 1rem;
}
.avatar {
width: 40px;
height: 40px;
border-radius: 50%;
object-fit: cover;
}
.status {
font-size: 0.8rem;
opacity: 0.8;
}
.chat-messages {
flex: 1;
padding: 1rem;
overflow-y: auto;
background: #f8f9fa;
}
.message {
display: flex;
margin-bottom: 1rem;
gap: 0.5rem;
}
.message.sent {
flex-direction: row-reverse;
}
.message-avatar {
width: 32px;
height: 32px;
border-radius: 50%;
object-fit: cover;
}
.message-content {
max-width: 70%;
}
.message-content p {
margin: 0;
padding: 0.75rem 1rem;
border-radius: 18px;
font-size: 0.9rem;
line-height: 1.4;
}
.message.received .message-content p {
background: white;
color: #333;
border-bottom-left-radius: 4px;
}
.message.sent .message-content p {
background: #667eea;
color: white;
border-bottom-right-radius: 4px;
}
.timestamp {
font-size: 0.7rem;
color: #999;
margin-top: 0.25rem;
display: block;
}
.message.sent .timestamp {
text-align: right;
}
.chat-input {
display: flex;
gap: 0.5rem;
padding: 1rem;
background: white;
border-top: 1px solid #e9ecef;
}
.chat-input input {
flex: 1;
padding: 0.75rem 1rem;
border: 1px solid #e9ecef;
border-radius: 25px;
outline: none;
font-size: 0.9rem;
}
.chat-input input:focus {
border-color: #667eea;
}
.send-btn {
background: #667eea;
color: white;
border: none;
width: 40px;
height: 40px;
border-radius: 50%;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: background 0.2s;
}
.send-btn:hover {
background: #5a6fd8;
}
@media (max-width: 480px) {
.chat-container {
margin: 0;
height: 100vh;
border-radius: 0;
}
.message-content {
max-width: 85%;
}
}
class ChatApp {
constructor() {
this.messages = [];
this.init();
}
init() {
this.bindEvents();
this.scrollToBottom();
}
bindEvents() {
const input = document.querySelector('.chat-input input');
const sendBtn = document.querySelector('.send-btn');
sendBtn.addEventListener('click', () => this.sendMessage());
input.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
this.sendMessage();
}
});
}
sendMessage() {
const input = document.querySelector('.chat-input input');
const message = input.value.trim();
if (message) {
this.addMessage(message, 'sent');
input.value = '';
this.scrollToBottom();
// Simulate reply after 1 second
setTimeout(() => {
this.addMessage('Thanks for your message!', 'received');
this.scrollToBottom();
}, 1000);
}
}
addMessage(text, type) {
const messagesContainer = document.querySelector('.chat-messages');
const timestamp = new Date().toLocaleTimeString([], {
hour: '2-digit',
minute: '2-digit'
});
const messageHTML = `
<div class="message ${type}">
${type === 'received' ? '<img src="user1.jpg" alt="User 1" class="message-avatar">' : ''}
<div class="message-content">
<p>${text}</p>
<span class="timestamp">${timestamp}</span>
</div>
</div>
`;
messagesContainer.insertAdjacentHTML('beforeend', messageHTML);
}
scrollToBottom() {
const messagesContainer = document.querySelector('.chat-messages');
messagesContainer.scrollTop = messagesContainer.scrollHeight;
}
}
new ChatApp();