Build an HTML5 Spreadsheet-Like Graph Plotter with JavaScript

Build a Graph Plotter in HTML5!
Build a Graph Plotter in HTML5!

Live stream set for 2025-08-10 at 14:00:00 Eastern

Ask questions in the live chat about any programming or lifestyle topic.

This livestream will be on YouTube or you can watch below.

Have you ever wanted to create a simple graphing tool using just HTML5 and JavaScript? In this tutorial, I’ll show you how to build a spreadsheet-style data input table that plots dynamic bar and line graphs using the <canvas> element — no external libraries required.

This project is perfect for JavaScript beginners, especially if you enjoy learning through hands-on examples.

🎯 What You’ll Learn

  • How to use <input type="number"> in a spreadsheet-style table
  • Automatically add new rows when inputs are filled
  • Draw bar and line graphs using the HTML5 <canvas>
  • Add interactivity with JavaScript
  • Toggle between graph types using a dropdown

📑 Project Code Overview

We’ll create:

  1. A simple table with two columns for X and Y values
  2. Auto-expanding rows when both X and Y are filled
  3. A dropdown to choose between Line or Bar graph
  4. Canvas rendering logic to draw and update the graph

💻 Technologies Used

  • HTML5 for structure and canvas
  • CSS3 for minimal styling
  • Vanilla JavaScript for dynamic interaction
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <title>Line/Bar Graph Plotter</title>
  <style>
    body {
      font-family: sans-serif;
      padding: 20px;
      background: #f0f0f0;
    }

    table {
      width: 300px;
      margin-bottom: 10px;
      border-collapse: collapse;
    }

    th, td {
      padding: 6px;
      border: 1px solid #ccc;
      text-align: center;
    }

    input[type="number"] {
      width: 80px;
      padding: 4px;
      text-align: right;
    }

    select, button {
      padding: 8px 12px;
      margin: 10px 0;
      font-size: 14px;
    }

    canvas {
      border: 1px solid #333;
      background: #fff;
      display: block;
      margin-top: 20px;
    }
  </style>
</head>
<body>

  <h2>Spreadsheet Graph Plotter</h2>

  <label>Choose Graph Type:</label>
  <select id="graphType">
    <option value="line">Line Graph</option>
    <option value="bar">Bar Graph</option>
  </select>

  <table id="dataTable">
    <thead>
      <tr><th>X</th><th>Y</th></tr>
    </thead>
    <tbody>
      <tr>
        <td><input type="number" step="any" /></td>
        <td><input type="number" step="any" /></td>
      </tr>
    </tbody>
  </table>

  <button onclick="plotGraph()">Plot Graph</button>

  <canvas id="graphCanvas" width="600" height="400"></canvas>

  <script>
    const table = document.getElementById('dataTable').getElementsByTagName('tbody')[0];

    // Add new row if last one is filled
    table.addEventListener('input', () => {
      const rows = table.rows;
      const lastRow = rows[rows.length - 1];
      const xInput = lastRow.cells[0].querySelector('input');
      const yInput = lastRow.cells[1].querySelector('input');

      if (xInput.value && yInput.value) {
        addRow();
      }
    });

    function addRow() {
      const newRow = table.insertRow();
      const xCell = newRow.insertCell(0);
      const yCell = newRow.insertCell(1);

      const xInput = document.createElement('input');
      xInput.type = 'number';
      xInput.step = 'any';

      const yInput = document.createElement('input');
      yInput.type = 'number';
      yInput.step = 'any';

      xCell.appendChild(xInput);
      yCell.appendChild(yInput);
    }

function plotGraph() {
  const graphType = document.getElementById("graphType").value;
  const canvas = document.getElementById("graphCanvas");
  const ctx = canvas.getContext("2d");
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  let points = [];

  const rows = table.rows;
  for (let i = 0; i < rows.length; i++) {
    const x = parseFloat(rows[i].cells[0].querySelector('input').value);
    const y = parseFloat(rows[i].cells[1].querySelector('input').value);
    if (!isNaN(x) && !isNaN(y)) {
      points.push({ x, y });
    }
  }

  if (points.length < 2) {
    alert("Please enter at least two valid data points.");
    return;
  }

  if (graphType === 'line') {
    points.sort((a, b) => a.x - b.x);
  }

  const padding = 40;
  const graphWidth = canvas.width - 2 * padding;
  const graphHeight = canvas.height - 2 * padding;
  const xVals = points.map(p => p.x);
  const yVals = points.map(p => p.y);

  const xMin = Math.min(...xVals);
  const xMax = Math.max(...xVals);
  const yMin = Math.min(0, ...yVals);
  const yMax = Math.max(...yVals);

  const xScale = graphWidth / (xMax - xMin || 1);
  const yScale = graphHeight / (yMax - yMin || 1);

  // Axes
  ctx.strokeStyle = "#999";
  ctx.lineWidth = 1;
  ctx.beginPath();
  ctx.moveTo(padding, canvas.height - padding);
  ctx.lineTo(canvas.width - padding, canvas.height - padding); // X-axis
  ctx.moveTo(padding, padding);
  ctx.lineTo(padding, canvas.height - padding); // Y-axis
  ctx.stroke();

  if (graphType === 'line') {
    // ✅ Draw a single path through all sorted points
    ctx.strokeStyle = "#007acc";
    ctx.lineWidth = 2;
    ctx.beginPath();

    points.forEach((point, i) => {
      const xCoord = padding + (point.x - xMin) * xScale;
      const yCoord = canvas.height - padding - (point.y - yMin) * yScale;

      if (i === 0) {
        ctx.moveTo(xCoord, yCoord);
      } else {
        ctx.lineTo(xCoord, yCoord);
      }
    });

    ctx.stroke(); // ⬅️ Only stroke once, after path is fully defined

    // ✅ Draw data points on top
    points.forEach(point => {
      const xCoord = padding + (point.x - xMin) * xScale;
      const yCoord = canvas.height - padding - (point.y - yMin) * yScale;
      ctx.fillStyle = "#ff3333";
      ctx.beginPath();
      ctx.arc(xCoord, yCoord, 4, 0, 2 * Math.PI);
      ctx.fill();
    });
  }

  if (graphType === 'bar') {
    // Draw bars centered on each x
    const barWidth = Math.min(40, graphWidth / xVals.length - 10);

    points.forEach((point) => {
      const xCoord = padding + (point.x - xMin) * xScale - barWidth / 2;
      const yCoord = canvas.height - padding - (point.y - yMin) * yScale;
      const barHeight = (point.y - yMin) * yScale;

      ctx.fillStyle = "#28a745";
      ctx.fillRect(xCoord, yCoord, barWidth, barHeight);
    });
  }
}

</script>

</body>
</html>

Interactive Demo

Here’s a live example of the Spreadsheet Graph in action:

HTML5 Spreadsheet Graph Demo
HTML5 Line Graph
Web Browser Displaying HTML5 Spreadsheet Line Graph

HTML5 Bar Graph
Web Browser Displaying HTML5 Spreadsheet Bar Graph

HTML5 Spreadsheet Graph Video

📚 Want to Learn JavaScript More Deeply?

Check out my beginner-friendly book:
📖 Learning JavaScript – A Beginner’s Guide

Whether you’re starting fresh or revisiting JavaScript, this book is a solid companion.

Also, explore my full course here:
🎓 Learning JavaScript – Online Course

👨‍🎓 Need Help or 1-on-1 Tutoring?

I’m available for personalized programming tutorials — including HTML5, CSS, JavaScript, and more.
📧 Contact me here to book a session.

🔁 What’s Next?

In future tutorials, I’ll cover:

  • Adding axis labels and gridlines
  • Exporting graphs as images
  • Saving input data to local storage or files

💬 Questions?

Have any questions or feedback? Leave a comment below or reach out through the contact form.

Happy coding!

About Edward

Edward is a software engineer, web developer, and author dedicated to helping people achieve their personal and professional goals through actionable advice and real-world tools.

As the author of impactful books including Learning JavaScript, Learning Python, Learning PHP, Mastering Blender Python API, and fiction The Algorithmic Serpent, Edward writes with a focus on personal growth, entrepreneurship, and practical success strategies. His work is designed to guide, motivate, and empower.

In addition to writing, Edward offers professional "full-stack development," "database design," "1-on-1 tutoring," "consulting sessions,", tailored to help you take the next step. Whether you are launching a business, developing a brand, or leveling up your mindset, Edward will be there to support you.

Edward also offers online courses designed to deepen your learning and accelerate your progress. Explore the programming on languages like JavaScript, Python and PHP to find the perfect fit for your journey.

📚 Explore His Books – Visit the Book Shop to grab your copies today.
💼 Need Support? – Learn more about Services and the ways to benefit from his expertise.
🎓 Ready to Learn? – Check out his Online Courses to turn your ideas into results.

Leave a Reply

Your email address will not be published. Required fields are marked *