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=Samshows “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.
<!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.15inrunAway().2.5is 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:
<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:
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
- Create a free account at github.com and click New repository. Make it public.
- Click Add file → Upload files, upload your
index.htmland commit. - Open Settings → Pages. Under “Build and deployment”, choose Deploy from a branch, pick
mainand/ (root), then save. - After a minute or two your page is live at
https://your-username.github.io/your-repo-name/.
Netlify Drop
- Put
index.htmlin its own folder. - Go to app.netlify.com/drop and drag the folder onto the page.
- 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.