Summary

Step-by-step guide to building an interactive dice roller web app with multiple dice types, modifiers, advantage/disadvantage system, and roll history.

Article Body

How to Create a Dice Roller Web App with HTML, CSS & JavaScript
How to Create a Dice Roller Web App with HTML, CSS & JavaScript

How to Create a Dice Roller Web App with HTML, CSS & JavaScript

Introduction

Dice rollers are essential tools for tabletop gamers, developers, and decision-makers. In this tutorial, we'll build a feature-rich dice roller web application with multiple dice types, quantity selection, modifiers, and roll history.

Step 1: Set Up the HTML Structure

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Dice Roller</title>
</head>
<body>
    <!-- We'll add content here -->
</body>
</html>

Step 2: Add CSS Styling with Tailwind

Include Tailwind CSS for rapid styling:

<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">

Add custom CSS for dice animations:

.dice {
    width: 80px;
    height: 80px;
    position: relative;
    margin: 10px;
}

@keyframes shake {
    0%, 100% { transform: translateX(0); }
    10%, 30%, 50%, 70%, 90% { transform: translateX(-5px); }
    20%, 40%, 60%, 80% { transform: translateX(5px); }
}

.shake {
    animation: shake 0.5s cubic-bezier(.36,.07,.19,.97) both;
}

Step 3: Build the User Interface

Create the main container with two columns:

<div class="container mx-auto px-4 py-8 max-w-4xl">
    <div class="bg-white rounded-xl shadow-md p-6">
        <div class="grid grid-cols-1 md:grid-cols-2 gap-8">
            <!-- Controls Column -->
            <div class="space-y-6">
                <!-- Dice Selection -->
                <!-- Quantity Controls -->
                <!-- Modifiers Section -->
                <!-- Roll Button -->
            </div>
            
            <!-- Results Column -->
            <div>
                <!-- Result Display -->
                <!-- Dice Container -->
                <!-- Roll History -->
            </div>
        </div>
    </div>
</div>

Step 4: Implement JavaScript Functionality

4.1 Initialize Variables

let selectedSides = 6;
let quantity = 1;
let modifier = 0;
let advantage = 'none';
let rollHistory = [];

4.2 Dice Roll Logic

function rollDice() {
    let results = [];
    let total = 0;
    
    for (let i = 0; i < quantity; i++) {
        let roll1 = Math.floor(Math.random() * selectedSides) + 1;
        let roll2 = null;
        
        if (advantage === 'advantage' || advantage === 'disadvantage') {
            roll2 = Math.floor(Math.random() * selectedSides) + 1;
        }
        
        let finalRoll = advantage === 'advantage' ? Math.max(roll1, roll2) :
                       advantage === 'disadvantage' ? Math.min(roll1, roll2) : roll1;
        
        results.push({
            value: finalRoll,
            rolls: roll2 ? [roll1, roll2] : [roll1],
            advantage: advantage
        });
        
        total += finalRoll;
    }
    
    total += modifier;
    displayDice(results);
    totalResult.textContent = total;
    addToHistory(results, total);
}

4.3 Display Results

function displayDice(results) {
    diceContainer.innerHTML = '';
    
    results.forEach((result) => {
        const diceEl = document.createElement('div');
        diceEl.className = 'flex flex-col items-center';
        
        const dice = document.createElement('div');
        dice.className = 'dice-face shake';
        dice.textContent = result.value;
        diceEl.appendChild(dice);
        
        if (result.advantage !== 'none') {
            const details = document.createElement('div');
            details.className = 'text-xs text-gray-500';
            details.textContent = `(${result.rolls.join(', ')})`;
            diceEl.appendChild(details);
        }
        
        diceContainer.appendChild(diceEl);
    });
}

4.4 History Management

function addToHistory(results, total) {
    const historyItem = document.createElement('div');
    historyItem.className = 'history-item bg-gray-50 p-3 rounded-lg flex justify-between items-center';
    
    const diceType = `d${selectedSides}`;
    const modifierText = modifier !== 0 ? ` + ${modifier}` : '';
    
    historyItem.innerHTML = `
        <div class="font-mono">
            <span class="font-bold">${diceType}</span>: ${results.map(r => r.value).join(', ')}${modifierText}
        </div>
        <div class="font-bold text-lg">${total}</div>
    `;
    
    historyContainer.insertBefore(historyItem, historyContainer.firstChild);
}

Step 5: Add Event Listeners

// Dice type selection
diceTypeBtns.forEach(btn => {
    btn.addEventListener('click', function() {
        selectedSides = parseInt(this.getAttribute('data-sides'));
        updateSelectedDiceType();
    });
});

// Roll button
rollBtn.addEventListener('click', function(e) {
    e.preventDefault();
    rollDice();
});

TOPICS MENTIONED IN THIS ARTICLE

About the Author(s)

  • ttimesnow photo

    ttimesnow

    ttimesnow – Author, Curator, and Analyst at [ttimesnow]

    ttimesnow is an experienced journalist with a passion for uncovering the latest trends and breaking news in technology, politics, and culture. ttimesnow combines deep research with a unique perspective to deliver insightful, well-rounded articles that keep readers informed and engaged. At [ttimesnow], ttimesnow curates daily content that brings the world’s most relevant news right to your fingertips.

    View all articles by ttimesnow