Live2024
Built a quick live 2024 Trump vs. Harrison counter. Pulling data from CNN’s live tracker into a simple, clean card. Most live trackers I found were cluttered with unnecessary components and text, so I created a streamlined version in just 5-10 minutes. Feel free to grab the code!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>2024 US Election Counter</title>
<style>
body {
font-family: Arial, sans-serif;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
background-color: #f0f0f0;
}
.card {
background-color: white;
border-radius: 8px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
padding: 20px;
text-align: center;
max-width: 400px;
width: 100%;
}
h1 {
color: #333;
font-size: 24px;
margin-bottom: 10px;
}
p {
color: #666;
font-size: 14px;
margin-bottom: 20px;
}
.counter-container {
display: flex;
justify-content: space-around;
}
.counter {
text-align: center;
}
.counter h2 {
font-size: 18px;
margin-bottom: 10px;
}
.count {
font-size: 36px;
font-weight: bold;
transition: all 0.5s ease;
}
.democrats {
color: #0015bc;
}
.republicans {
color: #ff0000;
}
.loading, .error {
text-align: center;
font-size: 18px;
color: #666;
}
.error {
color: #ff0000;
}
.vote-info {
font-size: 14px;
color: #555;
}
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.05); }
100% { transform: scale(1); }
}
.banner {
position: fixed;
left: 0;
right: 0;
bottom: 0;
background-color: #f8f8f8;
text-align: center;
border-top: 1px solid #ddd;
padding-top:6px;
padding-bottom: 6px;
font-size: x-large;
font-weight: 500;
color: #171717;
}
.banner a {
text-decoration: underline;
}
</style>
</head>
<body>
<div class="card">
<h1>2024 US Election Counter</h1>
<p>Live results updated every 10 seconds</p>
<div id="content">
<div class="loading">Loading...</div>
</div>
</div>
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-W16Z0D8BJ7"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-W16Z0D8BJ7');
</script>
<script>
const content = document.getElementById('content');
function updateCounter(party, count, percentage, votes) {
const countElement = document.getElementById(`${party}-count`);
if (countElement) {
countElement.textContent = count;
document.getElementById(`${party}-percentage`).textContent = `${percentage}%`;
document.getElementById(`${party}-votes`).textContent = `Votes: ${votes}`;
countElement.style.animation = 'pulse 0.5s ease';
setTimeout(() => {
countElement.style.animation = '';
}, 500);
}
}
function renderCounters(democratsCount, republicansCount, demPercentage, repPercentage, demVotes, repVotes) {
content.innerHTML = `
<div class="counter-container">
<div class="counter">
<h2 class="democrats">Democrats</h2>
<div id="democrats-count" class="count democrats">${democratsCount}</div>
<div id="democrats-percentage" class="vote-info">${demPercentage}%</div>
<div id="democrats-votes" class="vote-info">Votes: ${demVotes}</div>
</div>
<div class="counter">
<h2 class="republicans">Republicans</h2>
<div id="republicans-count" class="count republicans">${republicansCount}</div>
<div id="republicans-percentage" class="vote-info">${repPercentage}%</div>
<div id="republicans-votes" class="vote-info">Votes: ${repVotes}</div>
</div>
</div>
`;
}
async function fetchElectionData() {
try {
const response = await fetch('https://politics.api.cnn.io/results/bop/2024-PG-US.json', {
headers: {
'accept': '*/*',
'accept-language': 'en-US,en;q=0.9',
'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36',
'x-api-key': 'TtGlrrOrcdJNvE5U9t4XulVZuwk68Ecru3UIgtnr'
}
});
if (!response.ok) {
throw new Error('Failed to fetch election data');
}
const data = await response.json();
// Extract the relevant counts, percentages, and vote numbers
const democratsData = data.meta.candidates.DEM;
const republicansData = data.meta.candidates.REP;
const democratsCount = democratsData.count;
const republicansCount = republicansData.count;
const democratsPercentage = democratsData.votePercentStr;
const republicansPercentage = republicansData.votePercentStr;
const democratsVotes = democratsData.voteStr;
const republicansVotes = republicansData.voteStr;
// Render the counters or update them if they already exist
if (content.querySelector('.counter-container')) {
updateCounter('democrats', democratsCount, democratsPercentage, democratsVotes);
updateCounter('republicans', republicansCount, republicansPercentage, republicansVotes);
} else {
renderCounters(democratsCount, republicansCount, democratsPercentage, republicansPercentage, democratsVotes, republicansVotes);
}
} catch (error) {
console.error('Error:', error);
content.innerHTML = '<div class="error">Error fetching election data</div>';
}
}
function startPolling() {
fetchElectionData(); // Initial fetch on load
setInterval(fetchElectionData, 10000); // Poll every 10 seconds
}
startPolling();
</script>
<div class="banner">
Sponsored by <a href="https://mylinx.cc/" target="_blank">Mylinx</a>
</div>
</body>
</html>