Making a virtual magic 8 ball with Javascript and CSS Clip-Path

George and I had the idea to make a virtual magic 8 ball but with only sarcastic responses. We are using are Javascript, for the randomization function. The styling is handled by CSS, and the elements are HTML DIV elements. This will be a multi-part project.

To begin the project, I set out to lay out the basic framework for a functional virtual magic 8 ball coded with Javascript using an array containing the possible responses and a randomization function.

For the construction of the shapes I decided to shape the HTML DIV elements with the CSS Clip-path property. The only shapes are going to be the outer circle, and the inner triangle with the response text in it.

My philosophy is that using only HTML elements simplifies things as well. While adding images can improve the ‘pretty’ factor, that’ll be a later stage addition if anything.

Generating the clip path is made easier by this handy tool made by Bennet Feely named Clippy which you can access here:

The clip code looks like this:

clip-path: circle(50% at 50% 50%);

clip-path: polygon(50% 0%, 0% 100%, 100% 100%);

Once I had the shapes defined, I had some fiddling around to do in order to get the layout not to look ugly, and for the text to fit in the triangle.

.tritext {
        width: 50%;
        margin: auto;
        color: red;
        text-align: center;
        padding-top: 50%;
        padding-bottom: 20%;
        margin-bottom: auto;
        word-wrap: break-word;
        opacity: 90%;
        text-shadow: 1px 1px 8px maroon;
        z-index: 60;

I went with a fixed size for the ball and triangle, because early experiments with percentages for the size resulted in some funky behavior.

Auto-sizing of the elements would be possible with some more fiddling. However, I plan on working with different fixed sizes based on browser width with @media tags.

The Javascript code was fairly simple.

I reused my getRndInteger function from the night sky generator:

function getRndInteger(min, max) {
    return Math.floor(Math.random() * (max - min + 1) ) + min;

For the business end, I had to make a function to define the array of possible responses.

We call the getRndInteger function with possible values within the array. I used four possible responses, and a possible value between 1 and 4. This can be adjusted to match your array length. You can even set it up to automatically adjust based on the array length. I won’t be going that in depth with this example.

Since arrays start at 0, I subtracted one from the returned random integer to use all four of the possible responses in the array.

Finally, I used the innerHTML method to replace the “tritext” element (by ID) with the value after the subtraction.

function askBall() {
    var responses = ["Who Knows?", "Probably", "What the heck", "Definitely"];
    value = (getRndInteger(1, 4) - 1);
    document.getElementById("tritext").innerHTML = responses[value];

The result looks like this:

You can try out the live demo on our server here:

Or, for ease of experimentation, check it out on CodePen:

If you have any questions or suggestions please feel free to share in the comments below. Thanks for reading!

Leave a Reply

Your email address will not be published. Required fields are marked *