Open In App

Create Magic Eight Ball Game in HTML CSS & JavaScript

Last Updated : 19 Feb, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

We are to assume that the person will give us a question as input and once the input question comes in, The Magic Eight ball generates a random answer to the question. We will add a feature where in case of no input the ball says, “Sorry but I can’t work with that”.

Preview Image:

8BallOP

How the game will work?

  • Firstly, We will take a question input that input will get processed by JavaScript. If no input is provided then the result will be “Sorry but I can’t work with that”.
  • If there is an input the user clicks on the ball, we will record it.
  • The ball will be shaken and make the number 8 on the ball disappear.
  • Once the shaking stops the answer appears and changes the color of the inner circle to green.
  • We will finally record the answer in our table and our job will be done.

Approach:

  • Make the basic structure of the page using HTML, with <div>, <p>, <input>, and other following tags that might be needed for the structure.
  • Add styling using CSS , basically adding margins and paddings to align the stuff perfectly, also properly sizing the objects, and making sure that the ball stays to a fixed size at max and a fixed size for minimum.
  • Then we need to make 4 animations as follows –
    • Fade out animation ( To Fade out the text inside the ball before displaying answer ).
    • Fade in animation ( To Fade in the text inside the ball for displaying the answer ).
    • Shake animation ( To shake the ball when the person clicks it )
    • Color changing animation ( To change the color of the center of the ball from white to green ).
  • Finally, for the JavaScript part we will store all the answers in an array and 1st answer will be stored 2 times to make that outcome twice as probable as compared to others.
  • We will be using Math.random() to select a random element from the answers array and send it in as an answer.
  • Finally we will be using setTimeout() function to control the flow of the app and control the timings for the animations. And to trigger the event when the ball is clicked we will be using addEventListener().

Example: The below code can be used to create the Eight ball game using HTML, CSS, and JavaScript.

HTML




<!DOCTYPE html>
<html lang="en">
  
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, 
                                   initial-scale=1.0" />
    <!-- Link to custom css -->
    <link rel="stylesheet" href="style.css" />
    <title>GFG - Magic 8 Ball</title>
</head>
  
<body>
    <header>
        <h1>GeeksforGeeks</h1>
        <h2>Magic 8 Ball Game</h2>
    </header>
  
    <main class="main">
        <div class="questionBox">
            <h3>Enter What you have in your mind!!!</h3>
            <input type="text" name="fortuneQuestion" 
                id="fortuneQuestion"
                placeholder="Enter a question here" />
        </div>
        <div id="ball">
            <div id="answer">
                <p class="answerText">8</p>
            </div>
        </div>
    </main>
    <footer class="footer">
        <table id="questionAnswerTable">
            <thead>
                <tr>
                    <th>Question</th>
                    <th>Answer</th>
                </tr>
            </thead>
            <tbody class="tableBody"></tbody>
        </table>
    </footer>
    <script src="script.js"></script>
</body>
  
</html>


CSS




/* Universal selector to set some styles for all elements */
* {
    margin: 0;
    padding: 0;
    font-family: "Gill Sans", "Gill Sans MT", Calibri, 
      "Trebuchet MS", sans-serif;
}
  
/* Our Heading section */
header {
    margin: 6px;
    padding: 6px;
    text-align: center;
}
  
/* Main section box where the ball and the question is */
main {
    margin: 1svh;
    padding: 1svh;
    text-align: center;
    border-radius: 12px;
    box-shadow: 0px 0px 4px 0px gray;
}
  
/* Heading inside the main section */
main h2 {
    margin: 1svh;
}
  
/* Question input box styling */
#fortuneQuestion {
    width: 50%;
    padding: 16px;
    margin: 2svh 1svw;
    border-radius: 12px;
    border: 1px solid #000;
    background-color: #e9e7e7;
    font-size: large;
    color: black;
}
  
#fortuneQuestion::placeholder {
    font-size: large;
}
  
/* Magic eight ball black part */
#ball {
    width: 50vw;
    height: 50vw;
    max-width: 500px;
    max-height: 500px;
    background: radial-gradient(circle
      rgb(78, 78, 78) 0%, black 100%);
    border-radius: 50%;
    margin: 5vw auto;
}
  
/* The white circle inside the Magic eight ball */
#answer {
    width: 20vw;
    height: 20vw;
    max-width: 200px;
    max-height: 200px;
    background-color: white;
    border-radius: 50%;
    position: relative;
    top: calc(50% - min(10vw, 100px));
    margin: auto;
    /* line-height: min(20vw, 200px); */
    display: flex;
    cursor: pointer;
}
  
/* The big 8 Text inside magic eight ball */
#answer>.answerText {
    color: black;
    font-size: min(15vw, 120px);
    margin: auto;
    padding: 1vw;
}
  
/* A small rotating animation whenever we hover on it */
#answer:hover {
    transform: rotate(360deg);
    transition: transform 0.3s;
}
  
/* Styles to be used once the answer is displayed */
#answer.answerDisplayed {
    background-color: lightgreen;
    box-shadow: inset 0px 0px 4px 0px green;
}
  
#answer.answerDisplayed>.answerText {
    font-size: medium;
    display: block;
    white-space: normal;
}
  
/* All the styling for the table that will log question ans answers */
#questionAnswerTable th {
    padding: 3svh 10vw;
    width: 100svw;
    background-color: lightgreen;
    border-radius: 10px 10px 0px 0px;
    border: 1px solid green;
    font-size: large;
    text-align: center;
    color: black;
    box-shadow: 0px 0px 4px 0px gray;
}
  
#questionAnswerTable {
    border-collapse: separate;
    margin: 3vh;
    display: none;
}
  
#questionAnswerTable td {
    border: 1px solid green;
    padding: 1svh 10vw;
    width: 100svw;
    background-color: rgb(162, 249, 162);
    text-align: center;
    box-shadow: 0px 0px 4px 0px gray;
    white-space: normal;
}
  
.tableBody :nth-last-child(1)>td {
    border-radius: 0px 0px 10px 10px;
}
  
/* Shake animation */
@keyframes shake {
    0% {
        transform: translate(1px, 1px) rotate(0deg);
    }
  
    10% {
        transform: translate(-1px, -2px) rotate(-1deg);
    }
  
    20% {
        transform: translate(-3px, 0px) rotate(1deg);
    }
  
    30% {
        transform: translate(3px, 2px) rotate(0deg);
    }
  
    40% {
        transform: translate(1px, -1px) rotate(1deg);
    }
  
    50% {
        transform: translate(-1px, 2px) rotate(-1deg);
    }
  
    60% {
        transform: translate(-3px, 1px) rotate(0deg);
    }
  
    70% {
        transform: translate(3px, 1px) rotate(-1deg);
    }
  
    80% {
        transform: translate(-1px, -1px) rotate(1deg);
    }
  
    90% {
        transform: translate(1px, 2px) rotate(0deg);
    }
  
    100% {
        transform: translate(1px, -2px) rotate(-1deg);
    }
}
  
.shake {
    animation: shake 1.5s;
    animation-iteration-count: infinite;
}
  
/* Fade out animation frames */
@keyframes fadeOut {
    from {
        opacity: 1;
    }
  
    to {
        opacity: 0;
    }
}
  
/* Fade in animation frames */
@keyframes fadeIn {
    0% {
        opacity: 0;
    }
  
    100% {
        opacity: 1;
    }
}
  
/* Color change animation frames */
@keyframes colorChange {
    0% {
        background-color: white;
        box-shadow: none;
    }
  
    100% {
        background-color: lightgreen;
        box-shadow: inset 0px 0px 4px 0px green;
    }
}


Javascript




const eightBall =
    document.querySelector("main #ball");
const answerText =
    document.querySelector("#ball #answer .answerText");
const answerDiv =
    document.querySelector("#ball #answer");
const questionInput =
    document.querySelector("main .questionBox input");
  
const answers = [
    "Yes, definitely.",
    "Yes, definitely.",
    "It is certain.",
    "It is decidedly so.",
    "Without a doubt.",
    "You may rely on it.",
    "As I see it, yes.",
    "Most likely.",
    "Outlook good.",
    "Signs point to yes.",
    "Yes.",
    "Reply hazy, try again.",
    "Ask again later",
    "Better not tell you now.",
    "Cannot predict now.",
    "Concentrate and ask again.",
    "Don't bet on it.",
    "My reply is no.",
    "My sources say no.",
    "Outlook not so good.",
    "Very doubtful.",
];
  
const questionTable = 
    document.querySelector("footer #questionAnswerTable");
const tableBody = 
    document.querySelector("footer #questionAnswerTable tbody");
  
eightBall.addEventListener("click", () => {
    const question = questionInput.value.trim();
    let answer;
    if (question === "") {
        answer = "I can't tell with that information.";
    } else {
        const randomIndex = 
            Math.floor(Math.random() * answers.length);
        answer = answers[randomIndex];
    }
    eightBall.classList.add("shake");
    answerDiv.style.animation = "colorChange 1s";
    answerText.style.animation = "fadeOut 1s";
    setTimeout(() => {
        answerText.innerText = "";
        answerDiv.classList.add("answerDisplayed");
    }, 700);
  
  
    setTimeout(() => {
        eightBall.classList.remove("shake");
        answerText.innerText = answer;
        answerText.style.animation = "fadeIn 1s";
        setTimeout(() => {
            answerText.style.animation = "";
        }, 700);
        if (question !== "") {
            const row = document.createElement("tr");
            const questionCell = document.createElement("td");
            const answerCell = document.createElement("td");
            questionCell.textContent = question;
            answerCell.textContent = answer;
            row.appendChild(questionCell);
            row.appendChild(answerCell);
            tableBody.appendChild(row);
            questionTable.style.display = "block";
        }
    }, 1500);
});


Output:

8BallGIF



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads