Design a Stock Market Dashboard using HTML CSS & JavaScript
We will walk through the step-by-step process of designing a Stock Market Dashboard template using HTML, CSS, and JavaScript. This application will provide users with a dashboard interface where they can view a watchlist of stocks, search for specific stocks, and see detailed information about each stock.
Prerequisites:
Approach to Design a Stock Market Dashboard
- Create an HTML file (index.html) and define the basic structure of the dashboard.
- Include sections for the header, main content area, watchlist, stock details, search functionality, etc.
- Link necessary external CSS and JavaScript files.
- Use CSS to create a visually appealing layout, including fonts, colors, spacing, and responsiveness for different screen sizes.
- Create a JavaScript file (script.js) to handle dynamic content and user interactions.
- Use JavaScript to fetch stock data from an API or mock data and display it in the dashboard.
- Implement functionalities like adding/removing stocks from the watchlist, searching for stocks, and displaying stock details.
- Display stock information in the dashboard, including stock name, symbol, price, change percentage, etc.
- Implement features to highlight positive and negative changes using colors (green for positive, red for negative).
- Allow users to create a watchlist of their favorite stocks.
- Implement functionalities to add/remove stocks from the watchlist.
- Display the watchlist dynamically and update it as users interact with the dashboard.
- Implement a search input field to allow users to search for specific stocks by name or symbol.
- Filter and display search results dynamically as users type in the search field.
Project Structure:
Example: To demonstrate creating a stock market dashboard using HTML, CSS and JavaScript.
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, initial-scale=1.0">
<title>Stock Market Dashboard</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="dashboard">
<header>
<h1>Stock Market Dashboard</h1>
</header>
<main>
<div class="watchlist">
<h2>Watchlist</h2>
<ul id="watchlist">
<!-- Watchlist items will be dynamically added here -->
</ul>
</div>
<div class="stock-details">
<h2>Stock Details</h2>
<div id="stock-info">
<!-- Stock details will be displayed here -->
</div>
</div>
</main>
<section class="search-section">
<input type="text" id="search"
placeholder="Search for stocks...">
<table id="stock-table">
<thead>
<tr>
<th>Stock Name</th>
<th>Price</th>
<th>Change</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<!-- Stock list will be dynamically added here -->
</tbody>
</table>
</section>
</div>
<script src="script.js"></script>
</body>
</html>
/* styles.css */
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #f0f2f5;
}
.dashboard {
max-width: 1200px;
margin: auto;
padding: 20px;
}
header {
background-color: #333;
color: white;
padding: 10px 0;
text-align: center;
}
main {
display: flex;
justify-content: space-between;
margin-top: 20px;
}
.watchlist, .stock-details {
background-color: white;
padding: 20px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
width: 48%;
}
.search-section {
margin-top: 20px;
background-color: white;
padding: 20px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
h2 {
margin-top: 0;
}
ul {
list-style: none;
padding: 0;
}
li {
padding: 10px;
border-bottom: 1px solid #ddd;
cursor: pointer;
position: relative;
}
li:hover {
background-color: #f0f2f5;
}
li button {
display: none;
position: absolute;
right: 10px;
top: 10px;
}
li:hover button {
display: inline-block;
}
#stock-info {
font-size: 1.2em;
}
#search {
width: 100%;
padding: 10px;
margin-bottom: 20px;
border: 1px solid #ddd;
border-radius: 4px;
}
#stock-table {
width: 100%;
border-collapse: collapse;
}
#stock-table th, #stock-table td {
border: 1px solid #ddd;
padding: 10px;
text-align: left;
}
#stock-table tr:hover{
background-color: #f0f2f5;
}
#stock-table th {
background-color: #f4f4f4;
}
.positive {
color: green;
}
.negative {
color: red;
}
.actions {
display: flex;
gap: 5px;
}
button {
padding: 5px 10px;
border: none;
border-radius: 4px;
cursor: pointer;
}
button.add {
background-color: green;
color: white;
}
button.remove {
background-color: red;
color: white;
}ding: 0;
}
li {
padding: 10px;
border-bottom: 1px solid #ddd;
cursor: pointer;
position: relative;
}
li:hover {
background-color: #f0f2f5;
}
li button {
display: none;
position: absolute;
right: 10px;
top: 10px;
}
li:hover button {
display: inline-block;
}
#stock-info {
font-size: 1.2em;
}
#search {
width: 100%;
padding: 10px;
margin-bottom: 20px;
border: 1px solid #ddd;
border-radius: 4px;
}
#stock-table {
width: 100%;
border-collapse: collapse;
}
#stock-table th, #stock-table td {
border: 1px solid #ddd;
padding: 10px;
text-align: left;
}
#stock-table tr:hover{
background-color: #f0f2f5;
}
#stock-table th {
background-color: #f4f4f4;
}
.positive {
color: green;
}
.negative {
color: red;
}
.actions {
display: flex;
gap: 5px;
}
button {
padding: 5px 10px;
border: none;
border-radius: 4px;
cursor: pointer;
}
button.add {
background-color: green;
color: white;
}
button.remove {
background-color: red;
color: white;
}
// script.js
document.addEventListener('DOMContentLoaded', () => {
const watchlist = document.getElementById('watchlist');
const stockInfo = document.getElementById('stock-info');
const searchInput = document.getElementById('search');
const stockTableBody = document.querySelector('#stock-table tbody');
let watchlistStocks = [
{ symbol: 'AAPL', name: 'Apple Inc.',
price: 150.54, change: 0.5 },
{ symbol: 'GOOGL', name: 'Alphabet Inc.',
price: 2800.66, change: -1.2 },
{ symbol: 'AMZN', name: 'Amazon.com Inc.',
price: 3401.46, change: 2.1 },
{ symbol: 'MSFT', name: 'Microsoft Corporation',
price: 299.35, change: -0.3 }
];
const allStocks = [
{ symbol: 'AAPL', name: 'Apple Inc.',
price: 150.54, change: 0.5 },
{ symbol: 'GOOGL', name: 'Alphabet Inc.',
price: 2800.66, change: -1.2 },
{ symbol: 'AMZN', name: 'Amazon.com Inc.',
price: 3401.46, change: 2.1 },
{ symbol: 'MSFT', name: 'Microsoft Corporation',
price: 299.35, change: -0.3 },
{ symbol: 'FB', name: 'Meta Platforms Inc.',
price: 355.23, change: 1.4 },
{ symbol: 'TSLA', name: 'Tesla Inc.',
price: 720.25, change: 0.8 },
{ symbol: 'NFLX', name: 'Netflix Inc.',
price: 510.89, change: -0.6 },
{ symbol: 'NVDA', name: 'NVIDIA Corporation',
price: 198.67, change: 1.2 },
{ symbol: 'PYPL', name: 'PayPal Holdings Inc.',
price: 245.12, change: -0.4 },
{ symbol: 'INTC', name: 'Intel Corporation',
price: 54.22, change: 0.3 },
{ symbol: 'CSCO', name: 'Cisco Systems Inc.',
price: 53.45, change: -0.2 },
{ symbol: 'PEP', name: 'PepsiCo Inc.',
price: 148.87, change: 0.7 },
{ symbol: 'KO', name: 'The Coca-Cola Company',
price: 54.95, change: 0.6 },
{ symbol: 'PFE', name: 'Pfizer Inc.',
price: 41.21, change: -0.1 },
{ symbol: 'JNJ', name: 'Johnson & Johnson',
price: 163.45, change: 0.2 },
{ symbol: 'V', name: 'Visa Inc.',
price: 222.34, change: -0.5 },
{ symbol: 'MA', name: 'Mastercard Incorporated',
price: 349.56, change: 0.4 },
{ symbol: 'DIS', name: 'The Walt Disney Company',
price: 179.32, change: -0.8 },
{ symbol: 'ADBE', name: 'Adobe Inc.',
price: 590.67, change: 1.1 },
{ symbol: 'CRM', name: 'Salesforce.com Inc.',
price: 252.44, change: -0.7 },
{ symbol: 'ORCL', name: 'Oracle Corporation',
price: 87.32, change: 0.3 },
{ symbol: 'IBM', name: 'International Business Machines Corporation',
price: 142.31, change: 0.2 },
{ symbol: 'UBER', name: 'Uber Technologies Inc.',
price: 51.23, change: 1.0 },
{ symbol: 'LYFT', name: 'Lyft Inc.',
price: 47.56, change: -1.1 },
{ symbol: 'TWTR', name: 'Twitter Inc.',
price: 64.98, change: 0.9 },
{ symbol: 'SNAP', name: 'Snap Inc.',
price: 70.55, change: -0.5 },
{ symbol: 'SQ', name: 'Block Inc.',
price: 245.67, change: 1.3 },
{ symbol: 'SPOT', name: 'Spotify Technology S.A.',
price: 265.78, change: -0.4 },
{ symbol: 'ZM', name: 'Zoom Video Communications Inc.',
price: 355.67, change: -1.0 },
{ symbol: 'DOCU', name: 'DocuSign Inc.',
price: 285.34, change: 0.6 },
{ symbol: 'BABA', name: 'Alibaba Group Holding Limited',
price: 230.45, change: -0.8 },
{ symbol: 'JD', name: 'JD.com Inc.',
price: 81.23, change: 0.7 },
{ symbol: 'SHOP', name: 'Shopify Inc.',
price: 1220.78, change: 1.4 },
{ symbol: 'WMT', name: 'Walmart Inc.',
price: 139.54, change: -0.2 },
{ symbol: 'TGT', name: 'Target Corporation',
price: 230.56, change: 0.5 },
{ symbol: 'MCD', name: 'McDonald\'s Corporation',
price: 232.67, change: -0.3 },
{ symbol: 'SBUX', name: 'Starbucks Corporation',
price: 114.23, change: 0.2 },
{ symbol: 'NKE', name: 'NIKE Inc.',
price: 147.56, change: 0.8 },
{ symbol: 'LULU', name: 'Lululemon Athletica Inc.',
price: 372.45, change: -0.5 },
{ symbol: 'BA', name: 'The Boeing Company',
price: 241.78, change: 1.0 },
{ symbol: 'GE', name: 'General Electric Company',
price: 106.23, change: -0.1 },
{ symbol: 'F', name: 'Ford Motor Company',
price: 14.56, change: 0.4 },
{ symbol: 'GM', name: 'General Motors Company',
price: 56.78, change: -0.7 },
{ symbol: 'TM', name: 'Toyota Motor Corporation',
price: 151.23, change: 0.3 },
{ symbol: 'HMC', name: 'Honda Motor Co. Ltd.',
price: 31.45, change: -0.2 },
{ symbol: 'UBS', name: 'UBS Group AG',
price: 16.23, change: 0.6 },
{ symbol: 'DB', name: 'Deutsche Bank AG'
, price: 12.45, change: -0.1 },
{ symbol: 'HSBC', name: 'HSBC Holdings plc',
price: 30.67, change: 0.5 }
];
function fetchStockData(symbol) {
// Mock data for all stocks
const mockData = {
AAPL: { price: 150.54, change: 0.5 },
GOOGL: { price: 2800.66, change: -1.2 },
AMZN: { price: 3401.46, change: 2.1 },
MSFT: { price: 299.35, change: -0.3 },
FB: { price: 355.23, change: 1.4 },
TSLA: { price: 720.25, change: 0.8 },
NFLX: { price: 510.89, change: -0.6 },
NVDA: { price: 198.67, change: 1.2 },
PYPL: { price: 245.12, change: -0.4 },
INTC: { price: 54.22, change: 0.3 },
CSCO: { price: 53.45, change: -0.2 },
PEP: { price: 148.87, change: 0.7 },
KO: { price: 54.95, change: 0.6 },
PFE: { price: 41.21, change: -0.1 },
JNJ: { price: 163.45, change: 0.2 },
V: { price: 222.34, change: -0.5 },
MA: { price: 349.56, change: 0.4 },
DIS: { price: 179.32, change: -0.8 },
ADBE: { price: 590.67, change: 1.1 },
CRM: { price: 252.44, change: -0.7 },
ORCL: { price: 87.32, change: 0.3 },
IBM: { price: 142.31, change: 0.2 },
UBER: { price: 51.23, change: 1.0 },
LYFT: { price: 47.56, change: -1.1 },
TWTR: { price: 64.98, change: 0.9 },
SNAP: { price: 70.55, change: -0.5 },
SQ: { price: 245.67, change: 1.3 },
SPOT: { price: 265.78, change: -0.4 },
ZM: { price: 355.67, change: -1.0 },
DOCU: { price: 285.34, change: 0.6 },
BABA: { price: 230.45, change: -0.8 },
JD: { price: 81.23, change: 0.7 },
SHOP: { price: 1220.78, change: 1.4 },
WMT: { price: 139.54, change: -0.2 },
TGT: { price: 230.56, change: 0.5 },
MCD: { price: 232.67, change: -0.3 },
SBUX: { price: 114.23, change: 0.2 },
NKE: { price: 147.56, change: 0.8 },
LULU: { price: 372.45, change: -0.5 },
BA: { price: 241.78, change: 1.0 },
GE: { price: 106.23, change: -0.1 },
F: { price: 14.56, change: 0.4 },
GM: { price: 56.78, change: -0.7 },
TM: { price: 151.23, change: 0.3 },
HMC: { price: 31.45, change: -0.2 },
UBS: { price: 16.23, change: 0.6 },
DB: { price: 12.45, change: -0.1 },
HSBC: { price: 30.67, change: 0.5 }
};
return new Promise((resolve) => {
setTimeout(() => resolve(mockData[symbol]), 50);
});
}
function displayStockInfo(stock) {
fetchStockData(stock.symbol)
.then((data) => {
const changeClass = data
.change >= 0 ? 'positive' : 'negative';
stockInfo.innerHTML = `
<h3>${stock.name} (${stock.symbol})</h3>
<p>Price: $${data.price.toFixed(2)}</p>
<p class="${changeClass}">Change: ${data.change}%</p>
`;
});
}
function updateWatchlist()
{
watchlist
.innerHTML = '';
// Clear previous items
watchlistStocks
.forEach((stock) => {
const li = document
.createElement('li');
li
.textContent = `${stock.name} (${stock.symbol}) `;
const removeButton = document
.createElement('button');
removeButton
.textContent = 'Remove';
removeButton
.classList.add('remove');
removeButton
.addEventListener('click', () =>
{
watchlistStocks = watchlistStocks
.filter(item => item
.symbol !== stock
.symbol);
updateWatchlist();
displayStockTable(allStocks);
// Refresh the table to update
// the "Add/Remove" buttons
});
li.appendChild(removeButton);
// Add event listener to display
// stock details when clicked
li.addEventListener('click', () =>
{
displayStockInfo(stock);
});
watchlist.appendChild(li);
});
}
function displayStockTable(stocks)
{
stockTableBody.innerHTML = '';
// Clear previous data
stocks
.forEach((stock) =>
{
const changeClass = stock
.change >= 0 ? 'positive' : 'negative';
const tr = document
.createElement('tr');
tr.innerHTML = `
<td>${stock
.name}</td>
<td>$${stock
.price
.toFixed(1)}</td>
<td class="${changeClass}">${stock
.change}%</td>
<td class="actions"></td>
`;
const actionsTd = tr
.querySelector('.actions');
if (!watchlistStocks
.some(item => item
.symbol === stock
.symbol))
{
const addButton = document
.createElement('button');
addButton
.textContent = 'Add';
addButton
.classList
.add('add');
addButton
.addEventListener('click', () =>
{
watchlistStocks
.push(stock);
updateWatchlist();
displayStockTable(allStocks);
// Refresh the table to
// update the "Add/Remove" buttons
});
actionsTd.appendChild(addButton);
} else
{
const removeButton = document
.createElement('button');
removeButton
.textContent = 'Remove';
removeButton
.classList
.add('remove');
removeButton
.addEventListener('click', () =>
{
watchlistStocks = watchlistStocks
.filter(item => item
.symbol !== stock
.symbol
);
updateWatchlist();
displayStockTable(allStocks);
// Refresh the table
// to reflect the removal
});
actionsTd.appendChild(removeButton);
}
// Add event listener to display
// stock details when clicked
tr
.addEventListener('click', () =>
{
displayStockInfo(stock);
});
stockTableBody
.appendChild(tr);
});
}
searchInput
.addEventListener('input', (event) => {
const searchTerm = event
.target
.value
.toLowerCase();
const filteredStocks = allStocks
.filter(stock =>
stock
.name
.toLowerCase()
.includes(searchTerm) ||
stock
.symbol
.toLowerCase()
.includes(searchTerm)
);
displayStockTable(filteredStocks);
});
// Initial display of all stocks
displayStockTable(allStocks);
updateWatchlist();
});
Output: