Nanni Archive

DAILY FORTUNE BOX

Learn how to create an interactive box that reveals a random fortune message

LIVE DEMO

This is how the final result will look on your webpage. Click the box to see your fortune!

DAILY
FORTUNE

Fortune mailbox
What does destiny have in store for you today?

STEP 1: HTML STRUCTURE

The whole thing is one card: a title on top, the mailbox image in the middle (this is the clickable part), and a pink question/answer box at the bottom. We need four pieces: the fortune-card (the outer frame), the fortune-title, the fortune-box holding the mailbox image, and the fortune-result where the text is shown.

  • fortune-card: The outer bordered frame that holds everything.
  • fortune-title: The "★ DAILY FORTUNE ★" heading, in the site's pixel font.
  • fortune-box: The clickable area wrapping the mailbox image.
  • fortune-result: The pink box with the question (before clicking) or the fortune (after clicking).
HTML
<div class="fortune-card">
  <h3 class="fortune-title">
    <span class="pixel-star">★</span> DAILY<br>
    FORTUNE <span class="pixel-star">★</span>
  </h3>

  <div class="fortune-box" id="fortuneBox" onclick="revealFortune()">
    <img src="img/cute-mail.gif" alt="Fortune mailbox" class="fortune-icon">
  </div>

  <div class="fortune-result" id="fortuneResult">
    What does destiny have in store for you today?
  </div>
</div>

Swap img/cute-mail.gif for whatever image or gif you're using for the mailbox/box art on your own site.

STEP 2: CSS STYLES

The fortune-card is a white rounded card with a thick pink border — the frame that holds everything and gives it that "postcard" feel. The title uses the pixel font in dark pink. The mailbox image sits centered with a little hover/click feedback so it reads as clickable even without a button around it. The result box keeps the filled pink background with a dashed border from before, so the phrase always sits inside its own little card instead of floating as plain text.

CSS
/* Outer card / frame */
.fortune-card {
  background: #ffffff;
  border: 4px solid #e55c8a;
  border-radius: 28px;
  padding: 30px 24px;
  max-width: 300px;
  margin: 0 auto;
  text-align: center;
}

/* "★ DAILY FORTUNE ★" title */
.fortune-title {
  font-family: 'Silkscreen', cursive;
  color: #e55c8a;
  font-size: 20px;
  line-height: 1.5;
  letter-spacing: 1px;
  margin: 0 0 20px;
}

/* Clickable area around the mailbox image */
.fortune-box {
  width: 140px;
  margin: 0 auto 24px;
  cursor: pointer;
  transition: transform .2s ease;
}

.fortune-box:hover {
  transform: scale(1.05);
}

.fortune-box:active {
  transform: scale(0.95);
}

/* The mailbox image itself */
.fortune-icon {
  width: 100%;
  height: auto;
  image-rendering: pixelated; /* Keeps pixel art crisp */
  display: block;
}

/* Pink box with the question / the fortune */
.fortune-result {
  background: #ffcfe1;
  border: 2px dashed #e55c8a;
  border-radius: 18px;
  padding: 18px 16px;
  color: #6d2f44;
  font-size: 14px;
  line-height: 1.5;
}

STEP 3: JAVASCRIPT

We store all the phrases in an array and, on click, pick a random position with Math.random(). If you want the phrase to change only once per day (instead of every click), use today's date as a "seed" and save it in localStorage, so the visitor always sees the same message even if they reload the page.

JS
// List of fortune phrases
const fortunes = [
  "✦ Today is a good day to start something new ✦",
  "✦ An unexpected smile will brighten your afternoon ✦",
  "✦ The patience you have today will be tomorrow's victory ✦",
  "✦ Someone is thinking of you fondly ✦",
  "✦ Trust your instinct, it won't fail you ✦",
  "✦ Today is a perfect day to rest without guilt ✦",
  "✦ A small surprise is on its way ✦"
];

function revealFortune() {
  const resultBox = document.getElementById("fortuneResult");

  // Different phrase every click:
  const random = Math.floor(Math.random() * fortunes.length);
  resultBox.innerText = fortunes[random];
}

// --- "ONE PHRASE PER DAY" VERSION ---
function revealDailyFortune() {
  const resultBox = document.getElementById("fortuneResult");
  const today = new Date().toISOString().slice(0, 10); // e.g. "2026-08-08"

  const savedDate = localStorage.getItem("fortuneDate");
  let savedFortune = localStorage.getItem("fortuneText");

  if (savedDate !== today || !savedFortune) {
    // If it's a new day, pick a new phrase and save it
    const random = Math.floor(Math.random() * fortunes.length);
    savedFortune = fortunes[random];
    localStorage.setItem("fortuneDate", today);
    localStorage.setItem("fortuneText", savedFortune);
  }

  resultBox.innerText = savedFortune;
}

CUSTOMIZATION AND TIPS

  • Use the daily version: replace onclick="revealFortune()" with onclick="revealDailyFortune()" in the HTML, and also call revealDailyFortune() as soon as the page loads with window.onload so it shows up without needing a click.
  • Add a "reveal" animation: add this class when the message is revealed:
    .fortune-result.show {
      animation: pop .3s ease;
    }
    @keyframes pop {
      0% { transform: scale(0.8); opacity: 0; }
      100% { transform: scale(1); opacity: 1; }
    }
    and in JS add resultBox.classList.add("show") inside the function.
  • Change the mailbox art: swap img/cute-mail.gif for any other pixel art or gif — an envelope, a fortune cookie, a red packet — as long as it's roughly square it'll fit the frame.