Duckmath Sites Today
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<title>DuckMath • Quack & Calculate | Printable Math Fun</title>
<style>
*
margin: 0;
padding: 0;
box-sizing: border-box;
body
background: #eef4c3; /* soft marsh grass */
font-family: 'Segoe UI', 'Comic Neue', 'Comic Neue', 'Comic Sans MS', 'Chalkboard SE', cursive, sans-serif;
padding: 2rem 1rem;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
/* paper style – looks like a printable worksheet */
.paper
max-width: 1100px;
width: 100%;
background: #fffef7;
background-image: radial-gradient(circle at 10% 30%, rgba(255,245,200,0.3) 2%, transparent 2.5%);
background-size: 28px 28px;
border-radius: 32px;
box-shadow: 0 20px 35px rgba(0,0,0,0.1), 0 0 0 12px #f9e7b3, 0 0 0 14px #c7a55b;
padding: 2rem 2rem 2.5rem;
transition: all 0.2s;
/* for print — make borders crisp and no shadows */
@media print
body
background: white;
padding: 0;
margin: 0;
.paper
box-shadow: none;
border: 2px solid #ccb27c;
padding: 0.8in;
max-width: 100%;
border-radius: 0;
background: white;
background-image: none;
.duck-print-hide
display: none;
button, .action-buttons
display: none;
.math-grid
break-inside: avoid;
h2
break-after: avoid;
.worksheet-header
break-inside: avoid;
/* duck themed header */
.duck-banner
display: flex;
align-items: baseline;
justify-content: space-between;
flex-wrap: wrap;
border-bottom: 5px dotted #fbcb6e;
margin-bottom: 1.5rem;
padding-bottom: 0.75rem;
.title-area
display: flex;
align-items: center;
gap: 12px;
flex-wrap: wrap;
h1
font-size: 3rem;
background: linear-gradient(135deg, #f3a712, #e07c1f);
background-clip: text;
-webkit-background-clip: text;
color: transparent;
text-shadow: 2px 2px 0 #fff3cf;
letter-spacing: -0.5px;
.duck-icon
font-size: 3rem;
transform: rotate(2deg);
display: inline-block;
filter: drop-shadow(2px 2px 0 rgba(0,0,0,0.1));
.sub
color: #bc8f4b;
font-weight: bold;
font-size: 1.2rem;
background: #fef1cf;
padding: 0.3rem 0.9rem;
border-radius: 40px;
.date-name
display: flex;
gap: 2rem;
margin: 1rem 0 1.8rem;
font-size: 1rem;
border-top: 2px dashed #ffe1a0;
padding-top: 1rem;
justify-content: space-between;
flex-wrap: wrap;
.date-name span
background: #fff2df;
padding: 0.3rem 1rem;
border-radius: 28px;
color: #b45f2b;
/* worksheet grid */
.math-grid
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 1.8rem;
margin: 1.8rem 0;
.problem-card
background: #fefbe6;
border-radius: 42px;
padding: 1rem 1rem 1rem 1.5rem;
box-shadow: 0 8px 0 #e2c48b;
border: 2px solid #f7dfa5;
transition: transform 0.1s ease;
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
.problem-card:hover
transform: translateY(-3px);
background: #fffff2;
.equation
font-size: 2rem;
font-weight: bold;
font-family: 'Courier New', 'Segoe UI', monospace;
background: white;
padding: 0.3rem 1rem;
border-radius: 60px;
box-shadow: inset 0 1px 3px #0001, 0 2px 3px #ffefb0;
color: #3a2c1b;
letter-spacing: 2px;
.answer-line
display: flex;
align-items: center;
gap: 8px;
background: #fff3dc;
padding: 0.3rem 1rem 0.3rem 1.5rem;
border-radius: 60px;
.answer-line label
font-weight: bold;
color: #c55a1a;
font-size: 1rem;
.answer-input
width: 80px;
font-size: 1.3rem;
font-family: monospace;
text-align: center;
border: 2px solid #fbcb6e;
border-radius: 30px;
padding: 0.4rem 0;
background: white;
font-weight: bold;
outline: none;
transition: 0.1s;
.answer-input:focus
border-color: #f39c12;
box-shadow: 0 0 0 2px #ffda99;
.feedback
font-size: 1.2rem;
margin-left: 8px;
min-width: 36px;
text-align: center;
.duck-fact
background: #fffaec;
margin: 2rem 0 1rem;
padding: 0.8rem 1.5rem;
border-radius: 80px;
display: inline-block;
font-size: 0.95rem;
border-left: 12px solid #f7bc45;
/* score panel & buttons */
.score-panel
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
margin-top: 2rem;
padding-top: 1rem;
border-top: 3px wavy #fbd26a;
.score-box
background: #f7d98c;
padding: 0.4rem 1.2rem;
border-radius: 60px;
font-weight: bold;
font-size: 1.3rem;
color: #543a1a;
.action-buttons
display: flex;
gap: 1rem;
button
background: #f2c94c;
border: none;
font-family: inherit;
font-weight: bold;
font-size: 1rem;
padding: 0.5rem 1.2rem;
border-radius: 50px;
cursor: pointer;
box-shadow: 0 3px 0 #b97f2e;
transition: 0.07s linear;
color: #2d2b1f;
button:active
transform: translateY(2px);
box-shadow: 0 1px 0 #b97f2e;
.reset-btn
background: #fed287;
.check-btn
background: #ffe0a3;
.print-btn
background: #cbe6b0;
box-shadow: 0 3px 0 #8ba35c;
/* decorative duck */
.rubber-duck
text-align: right;
font-size: 2rem;
opacity: 0.6;
margin-top: -0.8rem;
user-select: none;
@media (max-width: 700px)
.paper
padding: 1.2rem;
.equation
font-size: 1.4rem;
.problem-card
flex-direction: column;
align-items: stretch;
gap: 12px;
.answer-line
justify-content: space-between;
.correct-feedback
color: #2a7221;
font-weight: bold;
.wrong-feedback
color: #c7362b;
font-weight: bold;
hr
border: 1px solid #ffdfa5;
margin: 0.5rem 0;
.footnote
font-size: 0.7rem;
text-align: center;
margin-top: 1rem;
color: #b4935a;
</style>
</head>
<body>
<div class="paper" id="duckMathPaper">
<div class="duck-banner">
<div class="title-area">
<span class="duck-icon">🐤📐</span>
<h1>DuckMath</h1>
<span class="duck-icon">🧮🦆</span>
</div>
<div class="sub">quack & calculate</div>
</div>
<div class="date-name">
<span>📅 Date: __________________</span>
<span>✏️ Name: __________________</span>
<span>⭐ Duck level: mathematician</span>
</div>
<!-- dynamic math problems container -->
<div id="problemsContainer" class="math-grid"></div>
<div class="duck-fact">
🦆 Did you know? A duck's quack doesn't echo (that's a myth!) but math always adds up! Try your best.
</div>
<div class="score-panel">
<div class="score-box" id="scoreDisplay">🦆 Score: 0 / 0</div>
<div class="action-buttons">
<button class="check-btn" id="checkAnswersBtn">✅ Check answers</button>
<button class="reset-btn" id="resetBtn">🔄 New problems</button>
<button class="print-btn duck-print-hide" id="printPaperBtn">🖨️ Print / Paper mode</button>
</div>
</div>
<div class="rubber-duck duck-print-hide">🐥🐤🦆</div>
<div class="footnote">✏️ Write your answers in the boxes, then click "Check answers". For printing, use the print button → perfect worksheet!</div>
</div>
<script>
// ------------------- DUCKMATH ENGINE --------------------
// Generate random arithmetic problems (addition & subtraction within 0-20, no negatives)
// Also some multiplication for 3rd grade style? To keep fun but elementary: mix of + and - and simple × (0..5)
// We'll create 12 problems with nice duck theme. Operations: +, -, × (× only with small numbers)
const CONFIG =
NUM_PROBLEMS: 12,
MAX_ADD_SUB: 20,
MAX_MULTIPLICAND: 5,
MAX_MULTIPLIER: 5
;
let currentProblems = []; // store text, answer, userAnswer, id
let userAnswers = []; // parallel array for reactivity (store as string or null)
let problemNodes = []; // store references to input fields & feedback spans
// Helper: random integer [min,max]
function rand(min, max)
return Math.floor(Math.random() * (max - min + 1)) + min;
// generate a single problem with random operation
function generateProblem()
const opType = rand(1, 3); // 1:add, 2:sub, 3:mult (gentle)
if (opType === 1) // addition
let a = rand(0, CONFIG.MAX_ADD_SUB);
let b = rand(0, CONFIG.MAX_ADD_SUB);
let sum = a + b;
if (sum > CONFIG.MAX_ADD_SUB + 5) // rebalance not too big, keep under 30
a = rand(0, 12);
b = rand(0, 12);
sum = a + b;
return text: `$a + $b = ?`, answer: sum, operation: '+' ;
else if (opType === 2) // subtraction, ensure non-negative
let a = rand(0, CONFIG.MAX_ADD_SUB);
let b = rand(0, a);
return text: `$a - $b = ?`, answer: a - b, operation: '-' ;
else // multiplication (easy)
let a = rand(0, CONFIG.MAX_MULTIPLICAND);
let b = rand(0, CONFIG.MAX_MULTIPLIER);
return text: `$a × $b = ?`, answer: a * b, operation: '×' ;
// generate full problem set
function generateProblemSet()
const problems = [];
for (let i = 0; i < CONFIG.NUM_PROBLEMS; i++)
problems.push(generateProblem());
return problems;
// rebuild UI from currentProblems array
function renderProblems()
const container = document.getElementById('problemsContainer');
if (!container) return;
container.innerHTML = '';
problemNodes = [];
currentProblems.forEach((prob, idx) =>
const card = document.createElement('div');
card.className = 'problem-card';
const equationSpan = document.createElement('div');
equationSpan.className = 'equation';
equationSpan.innerText = prob.text;
const answerDiv = document.createElement('div');
answerDiv.className = 'answer-line';
const labelSpan = document.createElement('label');
labelSpan.innerText = '➤ answer:';
const inputField = document.createElement('input');
inputField.type = 'number';
inputField.placeholder = '?';
inputField.className = 'answer-input';
inputField.value = (prob.userAnswer !== undefined && prob.userAnswer !== null) ? prob.userAnswer : '';
inputField.addEventListener('input', (e) =>
const raw = e.target.value.trim();
if (raw === '')
currentProblems[idx].userAnswer = null;
else
const num = Number(raw);
if (!isNaN(num))
currentProblems[idx].userAnswer = num;
else
currentProblems[idx].userAnswer = null;
// update feedback realtime? we can clear feedback on edit
const fbSpan = answerDiv.querySelector('.feedback');
if (fbSpan)
fbSpan.innerHTML = '';
fbSpan.className = 'feedback';
);
const feedbackSpan = document.createElement('span');
feedbackSpan.className = 'feedback';
answerDiv.appendChild(labelSpan);
answerDiv.appendChild(inputField);
answerDiv.appendChild(feedbackSpan);
card.appendChild(equationSpan);
card.appendChild(answerDiv);
container.appendChild(card);
problemNodes.push(
input: inputField,
feedback: feedbackSpan,
idx: idx
);
);
updateScoreDisplayOnly(); // reset score display
// update score display (no auto check)
function updateScoreDisplayOnly()
const total = currentProblems.length;
let correctCount = 0;
for (let p of currentProblems)
if (p.userAnswer !== undefined && p.userAnswer !== null && p.userAnswer === p.answer)
correctCount++;
const scoreDiv = document.getElementById('scoreDisplay');
if (scoreDiv)
scoreDiv.innerHTML = `🦆 Score: $correctCount / $total $getDuckMood(correctCount,total)`;
function getDuckMood(correct, total)
if (total === 0) return '🐣';
const ratio = correct / total;
if (ratio === 1) return '🏆🦆✨';
if (ratio >= 0.75) return '👍🦆';
if (ratio >= 0.5) return '🤔🦆';
return '📖🦆 keep trying!';
// check all answers and update feedback spans
function checkAllAnswers()
let correctCount = 0;
// iterate through problems and sync from inputs? but we already store in currentProblems via input events.
// However to be safe, re-sync from input fields values
for (let node of problemNodes)
const inp = node.input;
const idx = node.idx;
let rawValue = inp.value.trim();
let numericAnswer = null;
if (rawValue !== '')
numericAnswer = Number(rawValue);
if (isNaN(numericAnswer)) numericAnswer = null;
currentProblems[idx].userAnswer = numericAnswer;
// evaluate each
for (let i = 0; i < currentProblems.length; i++)
const prob = currentProblems[i];
const fbSpan = problemNodes.find(n => n.idx === i)?.feedback;
if (!fbSpan) continue;
const isCorrect = (prob.userAnswer !== null && prob.userAnswer !== undefined && prob.userAnswer === prob.answer);
if (isCorrect)
fbSpan.innerHTML = '✅✔️';
fbSpan.className = 'feedback correct-feedback';
correctCount++;
else prob.userAnswer === undefined
const total = currentProblems.length;
const scoreDiv = document.getElementById('scoreDisplay');
if (scoreDiv)
scoreDiv.innerHTML = `🦆 Score: $correctCount / $total $getDuckMood(correctCount,total)`;
// add a little quack celebration if perfect
if (correctCount === total && total > 0)
const duckFactDiv = document.querySelector('.duck-fact');
const originalText = duckFactDiv.innerHTML;
duckFactDiv.innerHTML = '🎉✨ PERFECT QUACK! ✨🎉 You’re a math duck champion! 🦆🏅';
setTimeout(() =>
if (duckFactDiv) duckFactDiv.innerHTML = originalText;
, 2500);
// reset all problems: generate new set and clear answers & UI
function resetAllProblems()
currentProblems = generateProblemSet();
// initialize userAnswer fields as null
for (let p of currentProblems)
p.userAnswer = null;
renderProblems(); // fresh DOM, rebind events
// also reset score display after render
updateScoreDisplayOnly();
// extra: also clear any global feedback fields because renderProblems rebuilds everything
// on window load, initialise
function init()
currentProblems = generateProblemSet();
for (let p of currentProblems)
p.userAnswer = null;
renderProblems();
const checkBtn = document.getElementById('checkAnswersBtn');
const resetBtn = document.getElementById('resetBtn');
const printBtn = document.getElementById('printPaperBtn');
if (checkBtn) checkBtn.addEventListener('click', checkAllAnswers);
if (resetBtn) resetBtn.addEventListener('click', resetAllProblems);
if (printBtn)
printBtn.addEventListener('click', () =>
window.print();
);
// optional: add Enter key support for check? not needed but nice
document.addEventListener('keypress', (e) => );
// start everything
init();
</script>
</body>
</html>
Top 5 DuckMath Sites You Need to Bookmark
Here are the most effective platforms currently available. Note that the landscape changes frequently, so these represent both active sites and the types of sites you should search for.
1. Narrative-Driven Quests
Children help a duck character solve problems to cross a pond, find lost eggs, or prepare for winter. For example: “Quackers needs to gather 12 lily pads. He has 5. How many more does he need?” duckmath sites
Key Features of DuckMath Sites
While each site is unique, most DuckMath platforms share these core components: Top 5 DuckMath Sites You Need to Bookmark
3. Visual and Auditory Feedback
Correct answers get a cheerful “Quack!” and an animated duck doing a happy waddle. Incorrect answers trigger gentle, non-punitive prompts, like a duck tilting its head curiously. Best for: Visualizing equivalent fractions (e
4. Printable Resources
Most DuckMath sites offer offline worksheets, coloring pages of ducks with numbers, and printable board games for classroom or home use.
2. Quacky Fractions (Part of "Pond Hub")
While not a standalone site, Quacky Fractions is a dedicated module within the larger Pond Hub educational suite. It uses a mother duck dividing bugs among her ducklings to teach denominators.
- Best for: Visualizing equivalent fractions (e.g., 2/4 of the pond is the same as 1/2).
- Unique feature: The "Duck Call" button reads the fraction aloud in a silly voice.
- Teacher tip: Use the printable "Duckling Slips" for offline homework.