Code

Will you be my Valentine code: build your own page

A complete "Will you be my Valentine?" page with a runaway No button, in one file of plain HTML, CSS and JavaScript. Copy it, change it, and put it online for free.

How to make a Will You Be My Valentine website

  • One file, no frameworks and no build step.
  • A No button that dodges the mouse on a laptop and jumps away from a finger on a phone.
  • A Yes button that grows every time they try No.
  • The sender’s name from the link: ?from=Sam shows “Sam asks: Will you be my Valentine?”

It’s a simplified version of the idea behind this site, written for this tutorial. Our live link adds question choices, colours, a secret note and a tracker, which need a small server. The code below doesn’t.

Step 1: Copy the code

Create a new file called index.html, paste everything below into it and save it.

index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Will You Be My Valentine?</title>
  <style>
    * { box-sizing: border-box; }
    body {
      margin: 0;
      min-height: 100vh;
      display: flex;
      align-items: center;
      justify-content: center;
      font-family: system-ui, sans-serif;
      text-align: center;
      background: linear-gradient(135deg, #ffe4ec, #f8bbd9);
      overflow: hidden;
    }
    .card { padding: 32px 24px; }
    h1 { color: #c2185b; font-size: clamp(1.8rem, 6vw, 3rem); margin: 0 0 32px; }
    .buttons { display: flex; gap: 16px; justify-content: center; align-items: center; }
    button {
      border: 0;
      border-radius: 999px;
      padding: 14px 32px;
      font-size: 1.1rem;
      font-weight: 700;
      cursor: pointer;
    }
    #yes { background: #c2185b; color: #fff; transition: transform 0.2s; }
    #no { background: #fff; color: #c2185b; transition: left 0.3s, top 0.3s; }
    .hidden { display: none; }
  </style>
</head>
<body>
  <div class="card" id="ask">
    <h1 id="question">Will you be my Valentine? 💕</h1>
    <div class="buttons">
      <button id="yes">Yes</button>
      <button id="no">No</button>
    </div>
  </div>

  <div class="card hidden" id="celebrate">
    <h1>Yay! See you on the 14th! 💖</h1>
  </div>

  <script>
    const yes = document.getElementById('yes');
    const no = document.getElementById('no');
    let scale = 1;

    // Personalise: yoursite.com/?from=Sam shows "Sam asks: ..."
    const from = new URLSearchParams(location.search).get('from');
    if (from) {
      // textContent (not innerHTML) so nobody can inject code via the link
      document.getElementById('question').textContent =
        from.slice(0, 30) + ' asks: Will you be my Valentine? 💕';
    }

    // Move the No button to a random spot and make Yes a bit bigger
    function runAway() {
      const maxX = window.innerWidth - no.offsetWidth - 10;
      const maxY = window.innerHeight - no.offsetHeight - 10;
      no.style.position = 'fixed';
      no.style.left = Math.max(10, Math.random() * maxX) + 'px';
      no.style.top = Math.max(10, Math.random() * maxY) + 'px';
      scale = Math.min(scale + 0.15, 2.5);
      yes.style.transform = 'scale(' + scale + ')';
    }

    no.addEventListener('pointerenter', function (e) {  // mouse: dodge on hover
      if (e.pointerType === 'mouse') runAway();
    });
    no.addEventListener('pointerdown', function (e) {   // phones: dodge on touch
      e.preventDefault();
      runAway();
    });
    no.addEventListener('click', runAway);              // keyboard users

    yes.addEventListener('click', function () {
      document.getElementById('ask').classList.add('hidden');
      document.getElementById('celebrate').classList.remove('hidden');
    });
  </script>
</body>
</html>

Step 2: Try it

Double-click index.html to open it in your browser. Hover over (or tap) No and it jumps somewhere else while Yes grows. Click Yes to see the celebration message.

To test the personalisation, add ?from=YourName to the end of the address, for example index.html?from=Sam. The heading changes to “Sam asks: Will you be my Valentine?”.

Step 3: Make it yours

  • Colours: change #c2185b (rose) and the two colours in the background gradient.
  • Question: edit the text inside <h1 id="question">. “Would you be my Valentine?” and “Will you be mine?” work just as well.
  • Celebration: change the message inside #celebrate, or add a GIF with an <img> tag.
  • How fast Yes grows: change 0.15 in runAway(). 2.5 is the maximum size.

Why textContent? The sender’s name comes from the link, so anyone could type anything into it. Setting it with textContent shows it as plain text, which stops someone from sneaking HTML or scripts into your page. Avoid innerHTML for anything that comes from a URL.

Bonus: the “Are you sure?” version

A popular twist: No doesn’t run away, it just keeps asking, and Yes gets bigger each time until it fills the screen. Replace the three no.addEventListener lines in the script with this:

replace the No listeners
<script>
  // "Are you sure?" version: No stays put, changes its words, and Yes grows
  const lines = ['No', 'Are you sure?', 'Really sure?', 'Think again!',
                 'Last chance!', 'Surely not?', 'You might regret this!',
                 'Have a heart!', 'Is that your final answer?'];
  let tries = 0;

  no.addEventListener('click', function () {
    tries++;
    no.textContent = lines[Math.min(tries, lines.length - 1)];
    yes.style.transform = 'scale(' + (1 + tries * 0.25) + ')';
  });
</script>

Want hearts when they say yes? Swap the yes.addEventListener block for this one:

floating hearts
yes.addEventListener('click', function () {
  document.getElementById('ask').classList.add('hidden');
  document.getElementById('celebrate').classList.remove('hidden');
  // 40 hearts that float up and fade out
  for (let i = 0; i < 40; i++) {
    const h = document.createElement('span');
    h.textContent = '💖';
    h.style.cssText = 'position:fixed;bottom:-40px;font-size:' + (16 + Math.random() * 24) +
      'px;left:' + Math.random() * 100 + 'vw;transition:transform 3s ease-out, opacity 3s;';
    document.body.appendChild(h);
    requestAnimationFrame(function () {
      h.style.transform = 'translateY(-' + (60 + Math.random() * 60) + 'vh)';
      h.style.opacity = '0';
    });
    setTimeout(function () { h.remove(); }, 3200);
  }
});

Step 4: Put it online for free

GitHub Pages

  1. Create a free account at github.com and click New repository. Make it public.
  2. Click Add file → Upload files, upload your index.html and commit.
  3. Open Settings → Pages. Under “Build and deployment”, choose Deploy from a branch, pick main and / (root), then save.
  4. After a minute or two your page is live at https://your-username.github.io/your-repo-name/.

Netlify Drop

  1. Put index.html in its own folder.
  2. Go to app.netlify.com/drop and drag the folder onto the page.
  3. Netlify gives you a live link straight away. Create a free account to keep it.

Then share the link with ?from=YourName on the end.

Frequently asked questions

Is this code free to use?

Yes. You can use, change and share the example code on this page for any purpose under the MIT license. No attribution is needed.

Is this the source code of WillYouBeMyValentine.fun?

No. It’s a small, self-contained example of the same idea. Our live site is not open source; it adds link making, response tracking, themes and e-cards, which rely on a server and a database.

Can I put my Will You Be My Valentine page on GitHub?

Yes. Create a public repository, upload index.html and turn on GitHub Pages (step 4 above). It’s free and gives you a link to share.

Do I need coding experience?

No. You only need to copy, paste and save one file. Knowing a little HTML helps if you want to change the design.

Can I see whether they clicked Yes?

Not with a single static file, because nothing is saved anywhere. You’d need a small backend, such as a serverless function and a database, to record the click. If you don’t want to build that, our free Valentine link includes a private tracker.