


Building a Modern Interactive Raffle Wheel with HTML, CSS, and JavaScript
Introduction
In today's digital age, engaging your community with interactive tools is essential for fostering participation and excitement. Whether you're hosting a giveaway, conducting a poll, or organizing a competition, having a visually appealing and interactive raffle wheel can significantly enhance user experience. In this article, I'll walk you through the process of creating Modern Raffle 2024, an interactive raffle wheel built with HTML, CSS, and JavaScript. We'll cover everything from setting up the structure to adding animations and integrating social sharing features.
? Technologies Used
To bring this project to life, I leveraged the following technologies:
- HTML5: For structuring the webpage and creating interactive elements.
- CSS3: To style the application with modern design principles, including glassmorphism, animations, and responsive layouts.
- JavaScript: To add interactivity, handle user inputs, and manage the raffle wheel's logic and animations.
- Canvas API: For drawing and animating the raffle wheel.
- Font Awesome: To incorporate vector icons for a polished look.
- Google Fonts: Utilized the Inter font for a clean and modern typography.
- Buy Me a Coffee: Integrated a donation button to support the project.
?️ Project Structure
The project is organized into three main files:
- index.html: Contains the HTML structure of the application.
- styles.css: Holds all the CSS styles for layout and design.
- script.js: Includes the JavaScript code that powers the interactivity and animations.
Additionally, a footer section is incorporated to promote my website, LinkedIn, Twitter, and include a Buy Me a Coffee button for support.
? HTML (index.html)
The HTML structure sets up the main components of the raffle application, including input sections for participants and prizes, the raffle wheel, a modal for announcing winners, and a footer for promotions.
html
Modern Raffle 2024
? Modern Raffle 2024 ?
<div class="input-section"> <h2>Add Participants</h2> <div class="input-group"> <input type="text"> <pre class="brush:php;toolbar:false"> ? CSS (styles.css) The CSS file is meticulously crafted to ensure a modern and premium look, incorporating glassmorphism, smooth animations, responsive design, and accessibility features. Below is the complete CSS with detailed explanations of enhancements and fixes.
/* Reset and Base Styles */
- { box-sizing: border-box; margin: 0; padding: 0; font-family: 'Inter', sans-serif; }
body {
background: linear-gradient(135deg, #1e3c72, #2a5298);
color: #ffffff;
display: flex;
flex-direction: column; /* Stack children vertically /
justify-content: flex-start; / Start from the top /
align-items: center;
min-height: 100vh;
/ Remove overflow hidden to allow footer visibility */
overflow-x: hidden;
}
/* Container Styles /
.container {
background: rgba(255, 255, 255, 0.05);
backdrop-filter: blur(10px);
padding: 40px;
border-radius: 20px;
text-align: center;
width: 90%;
max-width: 900px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.37);
border: 1px solid rgba(255, 255, 255, 0.18);
animation: fadeIn 1s ease-in-out;
flex: 1; / Allow container to grow and push footer down */
display: flex;
flex-direction: column;
align-items: center;
}
/* Fade-in Animation */
@keyframes fadeIn {
from { opacity: 0; transform: translateY(-20px); }
to { opacity: 1; transform: translateY(0); }
}
/* Heading Styles */
h1 {
margin-bottom: 30px;
font-size: 3rem;
font-weight: 700;
text-shadow: 3px 3px 6px rgba(0,0,0,0.3);
}
/* Input Sections */
.input-section {
margin-bottom: 40px;
width: 100%;
}
.input-section h2 {
margin-bottom: 15px;
font-size: 1.75rem;
font-weight: 600;
}
/* Input Groups */
.input-group {
display: flex;
justify-content: center;
align-items: center;
gap: 10px;
margin-bottom: 15px;
}
.input-group input {
padding: 12px 20px;
width: 60%;
border: none;
border-radius: 30px;
background: rgba(255, 255, 255, 0.1);
color: #ffffff;
font-size: 1rem;
outline: none;
transition: background 0.3s ease, box-shadow 0.3s ease;
}
.input-group input::placeholder {
color: #dddddd;
}
.input-group input:focus {
background: rgba(255, 255, 255, 0.2);
box-shadow: 0 0 10px rgba(255, 127, 80, 0.5);
}
.input-group button {
padding: 12px 25px;
border: none;
border-radius: 30px;
background-color: #ff7f50;
color: #fff;
font-size: 1rem;
font-weight: 600;
cursor: pointer;
display: flex;
align-items: center;
gap: 8px;
transition: background-color 0.3s ease, transform 0.2s ease, box-shadow 0.3s ease;
}
.input-group button:hover {
background-color: #ff5722;
transform: translateY(-2px);
box-shadow: 0 4px 10px rgba(0,0,0,0.3);
}
/* User List */
userList {
}
userList li {
<div class="input-section"> <h2>Add Participants</h2> <div class="input-group"> <input type="text"> <pre class="brush:php;toolbar:false"> ? CSS (styles.css) The CSS file is meticulously crafted to ensure a modern and premium look, incorporating glassmorphism, smooth animations, responsive design, and accessibility features. Below is the complete CSS with detailed explanations of enhancements and fixes.
}
/* Selected Prize */
selectedPrize {
list-style: none; max-height: 120px; overflow-y: auto; text-align: left; padding: 0 20%; width: 100%;
}
/* Wheel Container */
.wheel-container {
position: relative;
margin-bottom: 40px;
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
}
.wheel-wrapper {
position: relative;
width: 100%;
max-width: 500px;
margin: 0 auto 20px;
}
/* Canvas Styles */
canvas {
width: 100%;
height: auto;
border-radius: 50%;
box-shadow: 0 0 20px rgba(0,0,0,0.5);
background: #000;
transition: transform 4s cubic-bezier(0.33, 1, 0.68, 1);
}
/* Pointer Styles */
.pointer {
position: absolute;
top: -20px;
left: 50%;
transform: translateX(-50%);
font-size: 2rem;
color: #ffeb3b;
animation: bounce 2s infinite;
}
@keyframes bounce {
0%, 100% { transform: translateX(-50%) translateY(0); }
50% { transform: translateX(-50%) translateY(-10px); }
}
/* Spin Button */
spinBtn {
padding: 8px 0; border-bottom: 1px solid rgba(255, 255, 255, 0.2); font-size: 1rem;
}
spinBtn:hover {
font-size: 1.2rem; font-weight: 500; margin-top: 10px;
}
spinBtn:active {
padding: 15px 35px; border: none; border-radius: 50px; background-color: #32cd32; color: #fff; font-size: 1.25rem; font-weight: 600; cursor: pointer; box-shadow: 0 6px 20px rgba(0,0,0,0.3); transition: background-color 0.3s ease, transform 0.2s ease, box-shadow 0.3s ease; display: flex; align-items: center; gap: 10px; margin: 0 auto;
}
/* Modal Styles */
.modal {
display: none;
position: fixed;
z-index: 100;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0,0,0,0.8);
animation: fadeInModal 0.5s ease;
}
@keyframes fadeInModal {
from { opacity: 0; }
to { opacity: 1; }
}
.modal-content {
background-color: rgba(30, 30, 30, 0.95);
margin: 10% auto;
padding: 30px;
border-radius: 15px;
width: 90%;
max-width: 600px;
text-align: center;
box-shadow: 0 8px 25px rgba(0,0,0,0.5);
position: relative;
animation: slideDown 0.5s ease;
}
@keyframes slideDown {
from { transform: translateY(-50px); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}
.close-button {
color: #bbb;
position: absolute;
top: 15px;
right: 20px;
font-size: 28px;
font-weight: bold;
cursor: pointer;
transition: color 0.3s ease;
}
.close-button:hover,
.close-button:focus {
color: #fff;
}
.modal-content h2 {
margin-bottom: 20px;
font-size: 2rem;
font-weight: 700;
}
.modal-content p {
font-size: 1.25rem;
margin-bottom: 25px;
}
shareBtn {
background-color: #28a428; transform: translateY(-3px); box-shadow: 0 8px 25px rgba(0,0,0,0.4);
}
shareBtn:hover {
transform: translateY(0); box-shadow: 0 4px 15px rgba(0,0,0,0.2);
}
/* Footer Styles /
.footer {
background: rgba(255, 255, 255, 0.05);
backdrop-filter: blur(10px);
padding: 20px 0;
border-top: 1px solid rgba(255, 255, 255, 0.2);
width: 100%;
/ Ensure footer stays below content */
flex-shrink: 0;
}
.footer-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
max-width: 900px;
margin: 0 auto;
padding: 0 20px;
}
.footer-links {
display: flex;
gap: 20px;
margin-bottom: 15px;
}
.footer-links a {
color: #ffffff;
font-size: 1rem;
text-decoration: none;
display: flex;
align-items: center;
gap: 8px;
transition: color 0.3s ease, transform 0.2s ease;
}
.footer-links a:hover {
color: #ff7f50;
transform: translateY(-2px);
}
.footer-links a i {
font-size: 1.2rem;
}
.footer-donate {
margin-top: 10px;
}
/* Responsive Design for Footer */
@media (min-width: 600px) {
.footer-container {
flex-direction: row;
justify-content: space-between;
}
}
/* Scrollbar Styles for User List */
userList::-webkit-scrollbar {
<div class="input-section"> <h2>Add Participants</h2> <div class="input-group"> <input type="text"> <pre class="brush:php;toolbar:false"> ? CSS (styles.css) The CSS file is meticulously crafted to ensure a modern and premium look, incorporating glassmorphism, smooth animations, responsive design, and accessibility features. Below is the complete CSS with detailed explanations of enhancements and fixes.
}
userList::-webkit-scrollbar-track {
list-style: none; max-height: 120px; overflow-y: auto; text-align: left; padding: 0 20%; width: 100%;
}
userList::-webkit-scrollbar-thumb {
padding: 8px 0; border-bottom: 1px solid rgba(255, 255, 255, 0.2); font-size: 1rem;
}
userList::-webkit-scrollbar-thumb:hover {
font-size: 1.2rem; font-weight: 500; margin-top: 10px;
}
/* Button Focus States for Accessibility */
.input-group button:focus,
spinBtn:focus,
shareBtn:focus {
padding: 15px 35px; border: none; border-radius: 50px; background-color: #32cd32; color: #fff; font-size: 1.25rem; font-weight: 600; cursor: pointer; box-shadow: 0 6px 20px rgba(0,0,0,0.3); transition: background-color 0.3s ease, transform 0.2s ease, box-shadow 0.3s ease; display: flex; align-items: center; gap: 10px; margin: 0 auto;
}
background-color: #28a428; transform: translateY(-3px); box-shadow: 0 8px 25px rgba(0,0,0,0.4);
// Selecting DOM Elements
const addUserBtn = document.getElementById('addUserBtn');
const usernameInput = document.getElementById('username');
const userList = document.getElementById('userList');
const setPrizeBtn = document.getElementById('setPrizeBtn');
const prizeInput = document.getElementById('prize');
const selectedPrize = document.getElementById('selectedPrize');
const spinBtn = document.getElementById('spinBtn');
const winnerModal = document.getElementById('winnerModal');
const closeBtn = document.querySelector('.close-button');
const winnerText = document.getElementById('winnerText');
const shareBtn = document.getElementById('shareBtn');
// State Variables
let users = [];
let prize = "None";
let isSpinning = false;
// Wheel Configuration
const canvas = document.getElementById('raffleWheel');
const ctx = canvas.getContext('2d');
const wheelRadius = canvas.width / 2;
const colors = ['#FF5733', '#33FF57', '#3357FF', '#F333FF', '#FF33A8', '#33FFF6', '#FFC300', '#DAF7A6'];
let startAngle = 0;
let arc = 0;
// Initialize Wheel
function initializeWheel() {
if (users.length === 0) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
return;
}
arc = (2 * Math.PI) / users.length;
drawWheel();
}
// Draw the Raffle Wheel
function drawWheel() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (let i = 0; i < users.length; i ) {
const angle = startAngle i * arc;
ctx.fillStyle = colors[i % colors.length];
ctx.beginPath();
ctx.moveTo(wheelRadius, wheelRadius);
ctx.arc(wheelRadius, wheelRadius, wheelRadius, angle, angle arc, false);
ctx.closePath();
ctx.fill();
}
// Draw the Pointer Arrow
function drawPointer() {
const pointerSize = 20;
ctx.fillStyle = '#FFEB3B';
ctx.beginPath();
ctx.moveTo(wheelRadius - pointerSize, 0);
ctx.lineTo(wheelRadius pointerSize, 0);
ctx.lineTo(wheelRadius, -pointerSize * 1.5);
ctx.closePath();
ctx.fill();
}
// Add User Event
addUserBtn.addEventListener('click', addUser);
usernameInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') addUser();
});
// Function to Add a User
function addUser() {
const username = usernameInput.value.trim();
if (username === "") {
showAlert("Please enter a valid username.");
return;
}
if (users.includes(username)) {
showAlert("This username is already added.");
return;
}
users.push(username);
updateUserList();
usernameInput.value = '';
initializeWheel();
}
// Update the User List UI
function updateUserList() {
userList.innerHTML = '';
users.forEach(user => {
const li = document.createElement('li');
li.textContent = user;
userList.appendChild(li);
});
}
// Set Prize Event
setPrizeBtn.addEventListener('click', setPrize);
prizeInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') setPrize();
});
// Function to Set the Prize
function setPrize() {
const prizeInputValue = prizeInput.value.trim();
if (prizeInputValue === "") {
showAlert("Please enter a valid prize.");
return;
}
prize = prizeInputValue;
selectedPrize.textContent = Selected Prize: ${prize};
prizeInput.value = '';
}
// Spin Button Event
spinBtn.addEventListener('click', spinWheel);
// Function to Spin the Wheel
function spinWheel() {
if (isSpinning) return;
if (users.length === 0) {
showAlert("Please add at least one user.");
return;
}
if (prize === "None") {
showAlert("Please set a prize.");
return;
}
}
// Function to Stop the Wheel and Announce Winner
function stopRotateWheel() {
const degrees = startAngle * 180 / Math.PI 90;
const arcd = arc * 180 / Math.PI;
const index = Math.floor((360 - (degrees % 360)) / arcd) % users.length;
const winner = users[index];
showWinner(winner);
isSpinning = false;
spinBtn.disabled = false;
}
// Easing Function for Smooth Animation
function easeOut(t, b, c, d) {
t /= d;
t--;
return c * (t * t * t 1) b;
}
// Function to Display Alerts
function showAlert(message) {
alert(message);
}
// Function to Show Winner in Modal
function showWinner(winner) {
winnerText.textContent = ${winner} has won ${prize}! ?;
winnerModal.style.display = "block";
}
// Close Modal Events
closeBtn.addEventListener('click', () => {
winnerModal.style.display = "none";
});
window.addEventListener('click', (event) => {
if (event.target === winnerModal) {
winnerModal.style.display = "none";
}
});
// Share on Twitter
shareBtn.addEventListener('click', shareOnTwitter);
// Function to Share Winner on Twitter
function shareOnTwitter() {
const text = encodeURIComponent(? Congratulations to ${winnerText.textContent}! They have won ${prize}! ? #Giveaway #Community);
const url = encodeURIComponent('https://gladiatorsbattle.com');
const twitterUrl = https://twitter.com/intent/tweet?text=${text}&url=${url};
window.open(twitterUrl, '_blank');
}
// Initial Wheel Setup
initializeWheel();
<div class="input-section"> <h2>Add Participants</h2> <div class="input-group"> <input type="text"> <pre class="brush:php;toolbar:false"> ? CSS (styles.css) The CSS file is meticulously crafted to ensure a modern and premium look, incorporating glassmorphism, smooth animations, responsive design, and accessibility features. Below is the complete CSS with detailed explanations of enhancements and fixes.
The above is the detailed content of Building a Modern Interactive Raffle Wheel with HTML, CSS, and JavaScript. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics











Let’s attempt to coin a term here: "Static Form Provider." You bring your HTML

At the start of a new project, Sass compilation happens in the blink of an eye. This feels great, especially when it’s paired with Browsersync, which reloads

In this week's roundup of platform news, Chrome introduces a new attribute for loading, accessibility specifications for web developers, and the BBC moves

This is me looking at the HTML element for the first time. I've been aware of it for a while, but haven't taken it for a spin yet. It has some pretty cool and

Buy or build is a classic debate in technology. Building things yourself might feel less expensive because there is no line item on your credit card bill, but

In this week's roundup, a handy bookmarklet for inspecting typography, using await to tinker with how JavaScript modules import one another, plus Facebook's

For a while, iTunes was the big dog in podcasting, so if you linked "Subscribe to Podcast" to like:

There are loads of analytics platforms to help you track visitor and usage data on your sites. Perhaps most notably Google Analytics, which is widely used
