Website Design
February 6, 2025
7 min read

How to Create a Chat UI with HTML, CSS, and JavaScript

How to Create a Chat UI with HTML, CSS, and JavaScript

Creating a chat UI with HTML, CSS, and JavaScript is a great way to learn front-end development while building something practical. A chat interface allows users to send and receive messages in a visually appealing and interactive way. Whether you're developing a simple messaging app or integrating chat into a larger project, having a well-designed UI is essential.

In this guide, we will explore how to create a modern chat UI using HTML for structure, CSS for styling, and JavaScript for functionality. By the end of this tutorial, you will have a sleek and fully functional chat interface that can be customized to suit your needs.

Why Build a Chat UI with HTML, CSS, and JavaScript?

A chat UI is an essential part of any messaging platform, and building it with HTML, CSS, and JavaScript offers several benefits:

  • Customization – You can design the chat interface to match your project’s style.
  • No Dependencies – Using pure HTML, CSS, and JavaScript ensures your chat UI remains lightweight.
  • Hands-On Learning – It’s a great project to improve your front-end development skills.
  • Scalability – You can expand the chat UI by integrating APIs, databases, or real-time messaging platforms.

Now, let's break down the process of building a chat UI.

Structuring the Chat UI with HTML

HTML provides the foundation for our chat UI. A typical chat interface consists of the following elements:

  • Chat Container – The main area that holds all the chat messages.
  • User Messages – Separate sections for user and incoming messages.
  • Input Box – A text field where users can type their messages.
  • Send Button – A button to submit messages into the chat.

By structuring your chat interface properly, you ensure a clean and accessible design that works on different screen sizes.

Styling the Chat UI with CSS

CSS helps to enhance the look and feel of the chat UI. A modern chat design includes:

  • Rounded Message Bubbles – To make the conversation visually appealing.
  • Color Differentiation – User messages and received messages should have different background colors.
  • Responsive Design – The chat UI should adjust seamlessly on desktops and mobile devices.
  • Dark Mode Support – A toggle feature for switching between light and dark themes.

Using CSS flexbox and grid layouts, you can create a well-structured chat UI that aligns all elements properly.

Adding Functionality with JavaScript

JavaScript is responsible for making the chat UI interactive. The main features include:

  • Sending Messages – Allow users to type and send messages.
  • Appending Messages to Chat Window – Display messages dynamically in the chat interface.
  • Dark Mode Toggle – A button to switch between light and dark themes.
  • User Interaction Effects – Add small animations or transitions for a smooth user experience.

By implementing these features, your chat UI will be functional and engaging for users.

Enhancing the Chat UI for Better User Experience

To make your chat UI even better, consider adding the following enhancements:

  • Typing Indicator – Show when the other user is typing.
  • Message Timestamps – Display the time when messages are sent.
  • Emojis and Stickers – Allow users to send expressive messages.
  • Message Deletion – A feature to remove messages from the chat.
  • Sound Notifications – Play a sound when a new message arrives.

These improvements make the chat UI more interactive and enjoyable for users.

Source Code

  • Step 1: Setting Up the HTML Structure
  • Step 2: Adding Styling with CSS
  • Step 3: Adding Interactivity with JavaScript
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Modern Dashboard Chat UI</title>
<!-- Font Awesome -->
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"
/>
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<div class="dashboard-container">
<!-- Navigation Menu -->
<div class="nav-menu">
<div class="logo">C</div>
<div class="nav-links">
<div class="nav-link active">
<i class="fas fa-home"></i>
</div>
<div class="nav-link">
<i class="fas fa-comment-dots"></i>
</div>
<div class="nav-link">
<i class="fas fa-th-large"></i>
</div>
<div class="nav-link">
<i class="fas fa-users"></i>
</div>
<div class="nav-link">
<i class="fas fa-server"></i>
</div>
</div>
<div class="user-profile">
<div class="theme-toggle" id="theme-toggle">
<i class="fas fa-sun"></i>
</div>
<div class="profile-img">
<img src="https://i.pravatar.cc/100?img=1" alt="Profile" />
</div>
</div>
</div>
<!-- Left Sidebar - Chat List -->
<div class="left-sidebar">
<div class="sidebar-header">
<h2 class="sidebar-title">Chats</h2>
<div class="action-buttons">
<button class="btn-icon">
<i class="fas fa-star"></i>
</button>
<button class="btn-icon">
<i class="fas fa-plus"></i>
</button>
</div>
</div>
<div class="search-container">
<span class="search-icon">
<i class="fas fa-search"></i>
</span>
<input
type="text"
class="search-box"
placeholder="Search conversations..."
/>
</div>
<div class="chat-filters">
<div class="filter-option active">All</div>
<div class="filter-option">Unread</div>
<div class="filter-option">Groups</div>
</div>
<div class="contact-list">
<div class="contact active">
<div class="avatar online">S</div>
<div class="contact-info">
<div class="contact-name">Sarah Johnson</div>
<div class="contact-preview">I'll check it.</div>
</div>
<div class="contact-time">12:45</div>
</div>
<div class="contact unread">
<div class="avatar">M</div>
<div class="contact-info">
<div class="contact-name">Mike Thompson</div>
<div class="contact-preview">Did you get the files I sent?</div>
</div>
<div class="contact-time">10:20</div>
</div>
<div class="contact">
<div class="avatar online">E</div>
<div class="contact-info">
<div class="contact-name">Emma Davis</div>
<div class="contact-preview">Let's meet.</div>
</div>
<div class="contact-time">2:00</div>
</div>
<div class="contact">
<div class="avatar">J</div>
<div class="contact-info">
<div class="contact-name">James Wilson</div>
<div class="contact-preview">Thanks for your help!</div>
</div>
<div class="contact-time">Yesterday</div>
</div>
<div class="contact">
<div class="avatar online">A</div>
<div class="contact-info">
<div class="contact-name">Alex Robinson</div>
<div class="contact-preview">Are we still on for today?</div>
</div>
<div class="contact-time">Mar 8</div>
</div>
<div class="contact unread">
<div class="avatar">L</div>
<div class="contact-info">
<div class="contact-name">Lisa Miller</div>
<div class="contact-preview">I just sent you the report</div>
</div>
<div class="contact-time">Mar 7</div>
</div>
<div class="contact">
<div class="avatar">D</div>
<div class="contact-info">
<div class="contact-name">Design Team</div>
<div class="contact-preview">John: Final revisions complete</div>
</div>
<div class="contact-time">Mar 6</div>
</div>
<div class="contact">
<div class="avatar">P</div>
<div class="contact-info">
<div class="contact-name">Product Meeting</div>
<div class="contact-preview">Amy: Let's discuss the roadmap</div>
</div>
<div class="contact-time">Mar 5</div>
</div>
</div>
</div>
<!-- Main Chat Area -->
<div class="main-content">
<div class="chat-header">
<button class="mobile-menu-btn" id="mobile-menu-btn">
<i class="fas fa-bars"></i>
</button>
<div class="chat-user-info">
<div class="avatar online">S</div>
<div style="margin-left: 15px">
<h3>Sarah Johnson</h3>
<div class="user-profile-status">
<span class="status-indicator"></span>
<span>Online</span>
</div>
</div>
</div>
<div class="chat-actions">
<button class="btn-icon">
<i class="fas fa-video"></i>
</button>
<button class="btn-icon">
<i class="fas fa-phone"></i>
</button>
<button
class="btn-icon toggle-right-sidebar"
id="toggle-right-sidebar"
>
<i class="fas fa-ellipsis-h"></i>
</button>
</div>
</div>
<div class="messages">
<div class="message-date">
<span>Today, March 10, 2025</span>
</div>
<div class="message received">
<div class="message-content">
Hi! How are you doing today?
<div class="message-meta">
<span class="message-time">11:30</span>
</div>
</div>
</div>
<div class="message sent">
<div class="message-content">
Hey Sarah! I'm doing great, thanks for asking. Just finishing up
some work.
<div class="message-meta">
<span class="message-time">11:32</span>
<span class="message-status">
<i class="fas fa-check"></i>
</span>
</div>
</div>
</div>
<div class="message received">
<div class="message-content">
That's good to hear! I was wondering if you're free this weekend
for the team meetup?
<div class="message-meta">
<span class="message-time">11:34</span>
</div>
</div>
</div>
<div class="message sent">
<div class="message-content">
Yes, I should be available. What time were you thinking?
<div class="message-meta">
<span class="message-time">11:40</span>
<span class="message-status">
<i class="fas fa-check"></i>
</span>
</div>
</div>
</div>
<div class="message received">
<div class="message-content">
<div class="shared-file">
<div class="file-icon">
<i class="fas fa-file-pdf"></i>
</div>
<div class="file-info">
<div class="file-name">Team_Meeting_Agenda.pdf</div>
<div class="file-size">2.4 MB</div>
</div>
<div class="file-actions">
<i class="fas fa-download"></i>
</div>
</div>
Here's the agenda for our meeting. We're planning to meet around 3
PM at Central Park.
<div class="message-meta">
<span class="message-time">12:45</span>
</div>
</div>
</div>
</div>
<div class="input-area">
<div class="input-tools">
<div class="input-tool">
<i class="fas fa-image"></i>
</div>
<div class="input-tool">
<i class="fas fa-map-marker-alt"></i>
</div>
<div class="input-tool">
<i class="fas fa-file-alt"></i>
</div>
</div>
<div class="message-input-container">
<input
type="text"
class="message-input"
placeholder="Type a message..."
/>
<span class="emoji-picker">
<i class="far fa-smile"></i>
</span>
</div>
<button class="send-button">
<i class="fas fa-paper-plane"></i>
</button>
</div>
</div>
<!-- Right Sidebar - User Profile & Files -->
<div class="right-sidebar">
<div class="sidebar-tabs">
<div class="sidebar-tab active">Profile</div>
<div class="sidebar-tab">Files</div>
</div>
<div class="sidebar-content">
<!-- Profile Tab Content -->
<div class="user-profile-card">
<div class="user-profile-pic">
<img src="https://i.pravatar.cc/100?img=2" alt="Profile" />
</div>
<div class="user-profile-name">Sarah Johnson</div>
<div class="user-profile-status">
<span class="status-indicator"></span>
<span>Online</span>
</div>
<div class="user-profile-actions">
<div class="profile-action">
<i class="fas fa-video"></i>
</div>
<div class="profile-action">
<i class="fas fa-phone"></i>
</div>
<div class="profile-action">
<i class="fas fa-ellipsis-h"></i>
</div>
</div>
</div>
<div class="user-info-section">
<h4 class="info-heading">User Information</h4>
<div class="info-item">
<div class="info-icon">
<i class="fas fa-user"></i>
</div>
<div class="info-details">
<div class="info-label">Username</div>
<div class="info-value">@sarah_j</div>
</div>
</div>
<div class="info-item">
<div class="info-icon">
<i class="fas fa-phone"></i>
</div>
<div class="info-details">
<div class="info-label">Phone</div>
<div class="info-value">+1 (555) 123-4567</div>
</div>
</div>
<div class="info-item">
<div class="info-icon">
<i class="fas fa-envelope"></i>
</div>
<div class="info-details">
<div class="info-label">Email</div>
<div class="info-value">sarah.j@example.com</div>
</div>
</div>
<div class="info-item">
<div class="info-icon">
<i class="fas fa-calendar"></i>
</div>
<div class="info-details">
<div class="info-label">Joined</div>
<div class="info-value">March 15, 2022</div>
</div>
</div>
</div>
<!-- Files Tab Content-->
<div class="files-list" style="display: none">
<h4 class="info-heading">Shared Files</h4>
<div class="file-item">
<div class="file-thumbnail">
<i class="fas fa-file-pdf"></i>
</div>
<div class="file-details">
<div class="file-title">Team_Meeting_Agenda.pdf</div>
<div class="file-meta">
<span>2.4 MB</span>
<span class="file-date">Today, 12:45 PM</span>
</div>
</div>
<div class="file-download">
<i class="fas fa-download"></i>
</div>
</div>
<div class="file-item">
<div class="file-thumbnail">
<img src="https://i.pravatar.cc/100?img=3" alt="Profile" />
</div>
<div class="file-details">
<div class="file-title">Project_Screenshot.png</div>
<div class="file-meta">
<span>1.2 MB</span>
<span class="file-date">Yesterday, 4:30 PM</span>
</div>
</div>
<div class="file-download">
<i class="fas fa-download"></i>
</div>
</div>
<div class="file-item">
<div class="file-thumbnail">
<i class="fas fa-file-word"></i>
</div>
<div class="file-details">
<div class="file-title">Quarterly_Report.docx</div>
<div class="file-meta">
<span>3.8 MB</span>
<span class="file-date">Mar 8, 2025</span>
</div>
</div>
<div class="file-download">
<i class="fas fa-download"></i>
</div>
</div>
<div class="file-item">
<div class="file-thumbnail">
<i class="fas fa-file-excel"></i>
</div>
<div class="file-details">
<div class="file-title">Budget_Forecast.xlsx</div>
<div class="file-meta">
<span>1.7 MB</span>
<span class="file-date">Mar 5, 2025</span>
</div>
</div>
<div class="file-download">
<i class="fas fa-download"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
css
:root {
--primary-color: #5b67ca;
--primary-light: #6b77db;
--primary-dark: #4a56b9;
--primary-gradient: linear-gradient(135deg, #5b67ca, #4a56b9);
--secondary-color: #f0f2fd;
--accent-color: #ff6b6b;
--success-color: #20c997;
--text-color: #333;
--light-text: #7a7a7a;
--lighter-text: #a0a0a0;
--sent-message: var(--primary-gradient);
--received-message: #ffffff;
--hover-color: #eaeeff;
--border-radius-sm: 8px;
--border-radius: 15px;
--border-radius-lg: 20px;
--shadow-sm: 0 2px 5px rgba(0, 0, 0, 0.05);
--shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
--shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.12);
--nav-size: 75px;
--sidebar-width: 300px;
--right-sidebar-width: 320px;
--transition: all 0.3s ease;
--font-primary: "Inter", "Segoe UI", -apple-system, BlinkMacSystemFont,
sans-serif;
}
/* Dark mode colors */
.dark-mode {
--primary-color: #6572d7;
--primary-light: #7a85e0;
--primary-dark: #5461c4;
--primary-gradient: linear-gradient(135deg, #6572d7, #5461c4);
--secondary-color: #2c2f3c;
--accent-color: #ff7a7a;
--success-color: #2bd9a7;
--text-color: #f0f0f0;
--light-text: #c0c0c0;
--lighter-text: #a0a0a0;
--sent-message: var(--primary-gradient);
--received-message: #2c2f3c;
--hover-color: #3a3f4e;
--shadow-sm: 0 2px 5px rgba(0, 0, 0, 0.2);
--shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
--shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.3);
background-color: #1c1e29;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: var(--font-primary);
}
body {
display: flex;
height: 100vh;
background-color: #f9faff;
color: var(--text-color);
transition: var(--transition);
}
.dashboard-container {
display: flex;
width: 100%;
height: 100vh;
background: white;
overflow: hidden;
transition: var(--transition);
}
.dark-mode .dashboard-container {
background: #242631;
}
/* Navigation Menu */
.nav-menu {
width: var(--nav-size);
height: 100%;
background: var(--primary-gradient);
display: flex;
flex-direction: column;
align-items: center;
padding: 24px 0;
box-shadow: var(--shadow);
z-index: 10;
transition: var(--transition);
/* position: fixed;
left: 0;
top: 0;
bottom: 0; */
}
.logo {
width: 45px;
height: 45px;
border-radius: var(--border-radius-sm);
background: white;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
color: var(--primary-color);
font-size: 20px;
margin-bottom: 35px;
box-shadow: var(--shadow-sm);
transition: var(--transition);
}
.dark-mode .logo {
color: var(--primary-dark);
background: rgba(255, 255, 255, 0.9);
}
.nav-links {
display: flex;
flex-direction: column;
gap: 18px;
align-items: center;
}
.nav-link {
width: 48px;
height: 48px;
border-radius: var(--border-radius-sm);
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: var(--transition);
color: rgba(255, 255, 255, 0.7);
position: relative;
}
.nav-link.active {
background: white;
color: var(--primary-color);
box-shadow: var(--shadow-sm);
}
.dark-mode .nav-link.active {
background: rgba(255, 255, 255, 0.9);
color: var(--primary-dark);
}
.nav-link:hover {
background: rgba(255, 255, 255, 0.15);
color: white;
transform: translateY(-2px);
}
.nav-link.active:hover {
background: white;
color: var(--primary-color);
transform: translateY(-2px);
}
.dark-mode .nav-link.active:hover {
background: rgba(255, 255, 255, 0.9);
color: var(--primary-dark);
}
.nav-link::after {
content: "";
position: absolute;
left: -20px;
top: 50%;
transform: translateY(-50%) scaleY(0);
width: 4px;
height: 20px;
background: white;
border-radius: 0 4px 4px 0;
transition: var(--transition);
}
.nav-link.active::after {
transform: translateY(-50%) scaleY(1);
}
.nav-icon {
width: 22px;
height: 22px;
}
.user-profile {
margin-top: auto;
position: relative;
}
.profile-img {
width: 48px;
height: 48px;
border-radius: 50%;
background: white;
cursor: pointer;
overflow: hidden;
border: 2px solid rgba(255, 255, 255, 0.5);
transition: var(--transition);
box-shadow: var(--shadow-sm);
}
.profile-img:hover {
transform: scale(1.05);
border-color: white;
}
.profile-img img {
width: 100%;
height: 100%;
object-fit: cover;
}
/* Theme toggle */
.theme-toggle {
position: absolute;
top: -60px;
cursor: pointer;
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
color: rgba(255, 255, 255, 0.8);
transition: var(--transition);
}
.theme-toggle:hover {
color: white;
background: rgba(255, 255, 255, 0.15);
}
/* Left Sidebar - Chat List */
.left-sidebar {
width: var(--sidebar-width);
/* margin-left: var(--nav-size); */
height: 100%;
background: white;
border-right: 1px solid rgba(0, 0, 0, 0.05);
display: flex;
flex-direction: column;
transition: var(--transition);
}
.dark-mode .left-sidebar {
background: #242631;
border-right-color: rgba(255, 255, 255, 0.05);
}
.sidebar-header {
padding: 24px 20px;
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
display: flex;
align-items: center;
justify-content: space-between;
transition: var(--transition);
}
.dark-mode .sidebar-header {
border-bottom-color: rgba(255, 255, 255, 0.05);
}
.sidebar-title {
font-size: 22px;
font-weight: 600;
letter-spacing: -0.5px;
}
.action-buttons {
display: flex;
gap: 12px;
}
.btn-icon {
width: 38px;
height: 38px;
border-radius: var(--border-radius-sm);
background: var(--secondary-color);
border: none;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: var(--transition);
color: var(--text-color);
}
.btn-icon:hover {
background: var(--hover-color);
transform: translateY(-2px);
}
.search-container {
padding: 15px 20px;
position: relative;
}
.search-box {
width: 100%;
padding: 14px 15px 14px 42px;
border: none;
background: var(--secondary-color);
border-radius: var(--border-radius-sm);
outline: none;
font-size: 14px;
transition: var(--transition);
color: var(--text-color);
}
.dark-mode .search-box {
background: rgba(255, 255, 255, 0.1);
color: var(--light-text);
}
.dark-mode .search-box::placeholder {
color: var(--lighter-text);
}
.search-icon {
position: absolute;
left: 35px;
top: 50%;
transform: translateY(-50%);
color: var(--light-text);
}
.search-box:focus {
box-shadow: 0 0 0 2px rgba(91, 103, 202, 0.2);
}
.dark-mode .search-box:focus {
box-shadow: 0 0 0 2px rgba(101, 114, 215, 0.3);
}
.chat-filters {
display: flex;
padding: 0 20px 15px;
gap: 10px;
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
transition: var(--transition);
}
.dark-mode .chat-filters {
border-bottom-color: rgba(255, 255, 255, 0.05);
}
.filter-option {
padding: 8px 15px;
background: var(--secondary-color);
border-radius: 20px;
font-size: 13px;
cursor: pointer;
transition: var(--transition);
font-weight: 500;
}
.dark-mode .filter-option {
background: rgba(255, 255, 255, 0.08);
}
.filter-option.active {
background: var(--primary-color);
color: white;
box-shadow: var(--shadow-sm);
}
.filter-option:hover:not(.active) {
background: var(--hover-color);
transform: translateY(-1px);
}
.dark-mode .filter-option:hover:not(.active) {
background: rgba(255, 255, 255, 0.15);
}
.contact-list {
flex: 1;
overflow-y: auto;
padding: 10px 15px;
scroll-behavior: smooth;
}
.contact-list::-webkit-scrollbar {
width: 6px;
}
.contact-list::-webkit-scrollbar-thumb {
background-color: rgba(0, 0, 0, 0.1);
border-radius: 3px;
}
.dark-mode .contact-list::-webkit-scrollbar-thumb {
background-color: rgba(255, 255, 255, 0.1);
}
.contact {
display: flex;
align-items: center;
padding: 15px;
border-radius: var(--border-radius);
cursor: pointer;
transition: var(--transition);
margin-bottom: 5px;
position: relative;
}
.contact:hover {
background: var(--hover-color);
transform: translateX(2px);
}
.contact.active {
background: var(--hover-color);
box-shadow: var(--shadow-sm);
}
.dark-mode .contact.active {
box-shadow: var(--shadow-sm);
}
.contact.unread::after {
content: "";
position: absolute;
top: 50%;
right: 15px;
transform: translateY(-50%);
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--primary-color);
}
.avatar {
width: 45px;
height: 45px;
border-radius: 50%;
margin-right: 15px;
background: var(--secondary-color);
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
color: var(--primary-color);
position: relative;
font-size: 16px;
box-shadow: var(--shadow-sm);
transition: var(--transition);
}
.dark-mode .avatar {
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
}
.contact:hover .avatar {
transform: scale(1.05);
}
.avatar.online::after {
content: "";
position: absolute;
bottom: 2px;
right: 2px;
width: 10px;
height: 10px;
border-radius: 50%;
background: var(--success-color);
border: 2px solid white;
box-shadow: var(--shadow-sm);
}
.dark-mode .avatar.online::after {
border-color: #242631;
}
.contact-info {
flex: 1;
}
.contact-name {
font-weight: 600;
margin-bottom: 4px;
display: flex;
align-items: center;
justify-content: space-between;
}
.contact-time {
font-size: 12px;
color: var(--light-text);
}
.contact-preview {
font-size: 13px;
color: var(--light-text);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 190px;
}
/* Main Chat Area */
.main-content {
flex: 1;
display: flex;
flex-direction: column;
background: #f9faff;
transition: var(--transition);
}
.dark-mode .main-content {
background: #1c1e29;
}
.chat-header {
padding: 15px 25px;
background: white;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
box-shadow: var(--shadow-sm);
transition: var(--transition);
z-index: 5;
}
.dark-mode .chat-header {
background: #242631;
border-color: rgba(255, 255, 255, 0.05);
}
.chat-user-info {
display: flex;
align-items: center;
}
.chat-actions {
display: flex;
gap: 12px;
}
.messages {
flex: 1;
padding: 25px;
overflow-y: auto;
scroll-behavior: smooth;
}
.messages::-webkit-scrollbar {
width: 6px;
}
.messages::-webkit-scrollbar-thumb {
background-color: rgba(0, 0, 0, 0.1);
border-radius: 3px;
}
.dark-mode .messages::-webkit-scrollbar-thumb {
background-color: rgba(255, 255, 255, 0.1);
}
.message-date {
text-align: center;
margin: 25px 0;
font-size: 12px;
color: var(--light-text);
}
.message-date span {
padding: 6px 15px;
background: white;
border-radius: 20px;
box-shadow: var(--shadow-sm);
transition: var(--transition);
}
.dark-mode .message-date span {
background: #2c2f3c;
}
.message {
display: flex;
margin-bottom: 25px;
max-width: 85%;
animation: fadeInUp 0.3s ease;
}
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.message.received {
justify-content: flex-start;
padding-right: 20%;
}
.message.sent {
justify-content: flex-end;
margin-left: auto;
padding-left: 20%;
}
.message-content {
padding: 16px;
border-radius: var(--border-radius);
box-shadow: var(--shadow-sm);
position: relative;
transition: var(--transition);
}
.message.received .message-content {
background: var(--received-message);
border-bottom-left-radius: 5px;
}
.dark-mode .message.received .message-content {
background: var(--received-message);
color: var(--text-color);
}
.message.sent .message-content {
background: var(--sent-message);
color: white;
border-bottom-right-radius: 5px;
}
.message-meta {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 8px;
}
.message-time {
font-size: 11px;
opacity: 0.8;
}
.message-status {
display: flex;
align-items: center;
}
.message-status svg {
width: 16px;
height: 16px;
}
.message.received .message-time {
color: var(--light-text);
}
.dark-mode .message.received .message-time {
color: var(--lighter-text);
}
.message.sent .message-time {
color: rgba(255, 255, 255, 0.9);
}
.shared-file {
display: flex;
align-items: center;
background: white;
padding: 12px;
border-radius: var(--border-radius-sm);
margin-bottom: 12px;
box-shadow: var(--shadow-sm);
transition: var(--transition);
}
.dark-mode .shared-file {
background: rgba(255, 255, 255, 0.1);
}
.file-icon {
width: 42px;
height: 42px;
background: #f6f6f6;
border-radius: var(--border-radius-sm);
display: flex;
align-items: center;
justify-content: center;
margin-right: 12px;
transition: var(--transition);
}
.dark-mode .file-icon {
background: rgba(255, 255, 255, 0.15);
color: white;
}
.file-info {
flex: 1;
}
.file-name {
font-weight: 500;
font-size: 14px;
}
.file-size {
font-size: 12px;
color: var(--light-text);
}
.file-actions {
display: flex;
gap: 10px;
}
.input-area {
padding: 18px 25px;
background: white;
display: flex;
align-items: center;
border-top: 1px solid rgba(0, 0, 0, 0.05);
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.03);
transition: var(--transition);
position: relative;
}
.dark-mode .input-area {
background: #242631;
border-color: rgba(255, 255, 255, 0.05);
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1);
}
.input-tools {
display: flex;
gap: 16px;
margin-right: 15px;
}
.input-tool {
cursor: pointer;
color: var(--light-text);
transition: var(--transition);
}
.input-tool:hover {
color: var(--primary-color);
transform: translateY(-2px);
}
.message-input-container {
flex: 1;
position: relative;
}
.message-input {
width: 100%;
padding: 15px 45px 15px 20px;
border: none;
background: var(--secondary-color);
border-radius: 25px;
outline: none;
font-size: 14px;
transition: var(--transition);
color: var(--text-color);
}
.dark-mode .message-input {
background: rgba(255, 255, 255, 0.1);
color: var(--light-text);
}
.dark-mode .message-input::placeholder {
color: var(--lighter-text);
}
.message-input:focus {
box-shadow: 0 0 0 2px rgba(91, 103, 202, 0.2);
}
.dark-mode .message-input:focus {
box-shadow: 0 0 0 2px rgba(101, 114, 215, 0.3);
}
.emoji-picker {
position: absolute;
right: 15px;
top: 50%;
transform: translateY(-50%);
cursor: pointer;
color: var(--light-text);
transition: var(--transition);
}
.emoji-picker:hover {
color: var(--primary-color);
transform: translateY(-50%) scale(1.1);
}
.send-button {
width: 50px;
height: 50px;
margin-left: 12px;
background: var(--primary-gradient);
border: none;
border-radius: 50%;
color: white;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: var(--transition);
outline: none;
box-shadow: var(--shadow);
}
.send-button:hover {
transform: scale(1.08);
box-shadow: var(--shadow-lg);
}
.send-icon {
width: 20px;
height: 20px;
}
/* Right Sidebar - User Profile & Files */
.right-sidebar {
width: var(--right-sidebar-width);
height: 100%;
background: white;
border-left: 1px solid rgba(0, 0, 0, 0.05);
display: flex;
flex-direction: column;
transition: var(--transition);
}
.dark-mode .right-sidebar {
background: #242631;
border-left-color: rgba(255, 255, 255, 0.05);
}
.sidebar-tabs {
display: flex;
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
transition: var(--transition);
}
.dark-mode .sidebar-tabs {
border-bottom-color: rgba(255, 255, 255, 0.05);
}
.sidebar-tab {
flex: 1;
padding: 18px 15px;
text-align: center;
cursor: pointer;
font-weight: 500;
transition: var(--transition);
font-size: 14px;
position: relative;
}
.sidebar-tab.active {
color: var(--primary-color);
}
.sidebar-tab.active::after {
content: "";
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 30%;
height: 3px;
background: var(--primary-color);
border-radius: 3px 3px 0 0;
}
.sidebar-content {
flex: 1;
overflow-y: auto;
padding: 25px;
scroll-behavior: smooth;
}
.sidebar-content::-webkit-scrollbar {
width: 6px;
}
.sidebar-content::-webkit-scrollbar-thumb {
background-color: rgba(0, 0, 0, 0.1);
border-radius: 3px;
}
.dark-mode .sidebar-content::-webkit-scrollbar-thumb {
background-color: rgba(255, 255, 255, 0.1);
}
.user-profile-card {
display: flex;
flex-direction: column;
align-items: center;
padding-bottom: 25px;
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
transition: var(--transition);
}
.dark-mode .user-profile-card {
border-bottom-color: rgba(255, 255, 255, 0.05);
}
.user-profile-pic {
width: 120px;
height: 120px;
border-radius: 50%;
margin-bottom: 20px;
background: var(--secondary-color);
overflow: hidden;
box-shadow: var(--shadow);
border: 4px solid white;
transition: var(--transition);
}
.dark-mode .user-profile-pic {
border-color: #242631;
}
.user-profile-pic img {
width: 100%;
height: 100%;
object-fit: cover;
transition: var(--transition);
}
.user-profile-pic:hover img {
transform: scale(1.05);
}
.user-profile-name {
font-size: 20px;
font-weight: 600;
margin-bottom: 5px;
}
.user-profile-status {
display: flex;
align-items: center;
font-size: 13px;
color: var(--light-text);
margin-bottom: 20px;
}
.status-indicator {
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--success-color);
margin-right: 6px;
}
.user-profile-actions {
display: flex;
gap: 15px;
}
.profile-action {
width: 45px;
height: 45px;
border-radius: 50%;
background: var(--secondary-color);
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: var(--transition);
box-shadow: var(--shadow-sm);
}
.dark-mode .profile-action {
background: rgba(255, 255, 255, 0.1);
}
.profile-action:hover {
background: var(--hover-color);
transform: translateY(-3px);
box-shadow: var(--shadow);
}
.dark-mode .profile-action:hover {
background: rgba(255, 255, 255, 0.15);
}
.user-info-section {
margin-top: 25px;
}
.info-heading {
font-size: 15px;
font-weight: 600;
margin-bottom: 15px;
color: var(--text-color);
letter-spacing: -0.3px;
}
.info-item {
display: flex;
align-items: center;
margin-bottom: 18px;
transition: var(--transition);
}
.info-item:hover {
transform: translateX(3px);
}
.info-icon {
width: 38px;
height: 38px;
border-radius: var(--border-radius-sm);
background: var(--secondary-color);
display: flex;
align-items: center;
justify-content: center;
margin-right: 15px;
transition: var(--transition);
}
.dark-mode .info-icon {
background: rgba(255, 255, 255, 0.1);
}
.info-details {
flex: 1;
}
.info-label {
font-size: 12px;
color: var(--light-text);
margin-bottom: 3px;
}
.info-value {
font-size: 14px;
font-weight: 500;
}
.files-list {
display: flex;
flex-direction: column;
gap: 15px;
}
.file-item {
display: flex;
align-items: center;
padding: 14px;
border-radius: var(--border-radius-sm);
background: var(--secondary-color);
transition: var(--transition);
box-shadow: var(--shadow-sm);
}
.dark-mode .file-item {
background: rgba(255, 255, 255, 0.08);
}
.file-item:hover {
background: var(--hover-color);
transform: translateY(-3px);
box-shadow: var(--shadow);
}
.dark-mode .file-item:hover {
background: rgba(255, 255, 255, 0.12);
}
.file-thumbnail {
width: 55px;
height: 55px;
border-radius: var(--border-radius-sm);
background: white;
margin-right: 15px;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
box-shadow: var(--shadow-sm);
transition: var(--transition);
}
.dark-mode .file-thumbnail {
background: rgba(255, 255, 255, 0.15);
}
.file-item:hover .file-thumbnail {
transform: scale(1.05);
}
.file-thumbnail img {
width: 100%;
height: 100%;
object-fit: cover;
transition: var(--transition);
}
.file-details {
flex: 1;
}
.file-title {
font-weight: 500;
margin-bottom: 5px;
font-size: 14px;
}
.file-meta {
display: flex;
align-items: center;
font-size: 12px;
color: var(--light-text);
}
.file-date {
margin-left: 10px;
padding-left: 10px;
border-left: 1px solid rgba(0, 0, 0, 0.1);
}
.dark-mode .file-date {
border-left-color: rgba(255, 255, 255, 0.1);
}
.file-download {
color: var(--primary-color);
cursor: pointer;
transition: var(--transition);
}
.file-download:hover {
transform: scale(1.2);
}
/* Mobile menu button */
.mobile-menu-btn {
display: none;
width: 40px;
height: 40px;
border-radius: var(--border-radius-sm);
background: var(--secondary-color);
border: none;
align-items: center;
justify-content: center;
cursor: pointer;
margin-right: 15px;
transition: var(--transition);
}
.dark-mode .mobile-menu-btn {
background: rgba(255, 255, 255, 0.1);
color: var(--light-text);
}
.mobile-menu-btn:hover {
background: var(--hover-color);
}
/* Responsive styles */
@media (max-width: 1400px) {
.right-sidebar {
width: 280px;
}
}
@media (max-width: 1200px) {
.right-sidebar {
position: absolute;
right: 0;
top: 0;
height: 100%;
transform: translateX(100%);
z-index: 100;
box-shadow: var(--shadow-lg);
}
.right-sidebar.active {
transform: translateX(0);
}
.toggle-right-sidebar {
display: block;
}
}
@media (max-width: 992px) {
.left-sidebar {
width: 260px;
}
.avatar {
width: 40px;
height: 40px;
}
}
@media (max-width: 768px) {
.nav-menu {
width: 60px;
}
.left-sidebar {
width: 240px;
position: absolute;
left: 60px;
top: 0;
height: 100%;
transform: translateX(-100%);
z-index: 100;
box-shadow: var(--shadow-lg);
transition: transform 0.3s ease;
}
.left-sidebar.active {
transform: translateX(0);
}
.logo {
width: 40px;
height: 40px;
font-size: 18px;
margin-bottom: 25px;
}
.nav-link {
width: 42px;
height: 42px;
}
.mobile-menu-btn {
display: flex;
}
.contact-preview {
max-width: 150px;
}
.message {
max-width: 90%;
}
.message.received {
padding-right: 5%;
}
.message.sent {
padding-left: 5%;
}
}
@media (max-width: 576px) {
.nav-menu {
width: 50px;
}
.left-sidebar {
left: 50px;
width: 230px;
}
.logo {
width: 35px;
height: 35px;
font-size: 16px;
}
.nav-link {
width: 35px;
height: 35px;
}
.nav-icon {
width: 18px;
height: 18px;
}
.profile-img {
width: 40px;
height: 40px;
}
.message {
max-width: 100%;
}
.message.received {
padding-right: 0;
}
.message.sent {
padding-left: 0;
}
.send-button {
width: 45px;
height: 45px;
}
.input-area {
padding: 15px;
}
.input-tools {
gap: 12px;
margin-right: 10px;
}
.message-input {
padding: 12px 40px 12px 15px;
}
}
javascript
document.addEventListener("DOMContentLoaded", function () {
const tabs = document.querySelectorAll(".sidebar-tab");
const profileContent = document.querySelector(
".user-profile-card, .user-info-section"
);
const filesContent = document.querySelector(".files-list");
tabs.forEach((tab) => {
tab.addEventListener("click", function () {
tabs.forEach((t) => t.classList.remove("active"));
this.classList.add("active");
if (this.textContent === "Profile") {
profileContent.style.display = "block";
filesContent.style.display = "none";
} else {
profileContent.style.display = "none";
filesContent.style.display = "block";
}
});
});
// Dark mode toggle
const themeToggle = document.getElementById("theme-toggle");
themeToggle.addEventListener("click", function () {
document.body.classList.toggle("dark-mode");
if (document.body.classList.contains("dark-mode")) {
this.innerHTML = `
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
</svg>
`;
} else {
this.innerHTML = `
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
`;
}
});
// Mobile menu toggle
const mobileMenuBtn = document.getElementById("mobile-menu-btn");
const leftSidebar = document.querySelector(".left-sidebar");
mobileMenuBtn.addEventListener("click", function () {
leftSidebar.classList.toggle("active");
});
const toggleRightSidebar = document.getElementById("toggle-right-sidebar");
const rightSidebar = document.querySelector(".right-sidebar");
toggleRightSidebar.addEventListener("click", function () {
rightSidebar.classList.toggle("active");
});
document.addEventListener("click", function (e) {
if (
window.innerWidth <= 768 &&
!e.target.closest(".left-sidebar") &&
!e.target.closest("#mobile-menu-btn") &&
leftSidebar.classList.contains("active")
) {
leftSidebar.classList.remove("active");
}
if (
window.innerWidth <= 1200 &&
!e.target.closest(".right-sidebar") &&
!e.target.closest("#toggle-right-sidebar") &&
rightSidebar.classList.contains("active")
) {
rightSidebar.classList.remove("active");
}
});
const messageInput = document.querySelector(".message-input");
const sendButton = document.querySelector(".send-button");
messageInput.addEventListener("focus", function () {
this.parentElement.style.transform = "scale(1.02)";
this.parentElement.style.transition = "all 0.3s ease";
});
messageInput.addEventListener("blur", function () {
this.parentElement.style.transform = "scale(1)";
});
sendButton.addEventListener("click", function () {
const messageText = messageInput.value.trim();
if (messageText) {
const messagesContainer = document.querySelector(".messages");
const newMessage = document.createElement("div");
newMessage.className = "message sent";
const now = new Date();
const hours = now.getHours().toString().padStart(2, "0");
const minutes = now.getMinutes().toString().padStart(2, "0");
const time = `${hours}:${minutes}`;
newMessage.innerHTML = `
<div class="message-content">
${messageText}
<div class="message-meta">
<span class="message-time">${time}</span>
<span class="message-status">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="20 6 9 17 4 12"></polyline>
</svg>
</span>
</div>
</div>
`;
messagesContainer.appendChild(newMessage);
messageInput.value = "";
messagesContainer.scrollTop = messagesContainer.scrollHeight;
// Animate send button
sendButton.style.transform = "scale(0.8)";
setTimeout(() => {
sendButton.style.transform = "scale(1)";
}, 200);
}
});
messageInput.addEventListener("keyup", function (e) {
if (e.key === "Enter") {
sendButton.click();
}
});
// Contacts interaction
const contacts = document.querySelectorAll(".contact");
contacts.forEach((contact) => {
contact.addEventListener("click", function () {
contacts.forEach((c) => c.classList.remove("active"));
this.classList.add("active");
this.classList.remove("unread");
if (window.innerWidth <= 768) {
leftSidebar.classList.remove("active");
}
});
});
});

Conclusion

Building a chat UI with HTML, CSS, and JavaScript is a rewarding project that helps you develop essential front-end skills. By structuring your UI with HTML, styling it with CSS, and adding functionality with JavaScript, you can create a seamless chat experience. Whether you’re using it for a personal project or integrating it into a larger application, a well-designed chat UI enhances user engagement.

Start building your chat UI today and experiment with different styles and features to make it unique. With continuous improvements, you can create a chat interface that stands out in any web application!

C
CodingVox

Web Developer and Content Creator

chat UIHTML CSS JavaScriptchat interfaceweb chat designJavaScript chat app