Skip to content

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.