Create Loan Calculator using HTML, CSS, and JavaScript

Faraz

By Faraz -

Learn how to create a loan calculator using HTML, CSS, and JavaScript with graphical representation using Chart.js. Follow this simple step-by-step guide.


create-loan-calculator-using-html-css-and-javascript.webp

Table of Contents

  1. Project Introduction
  2. HTML Code
  3. CSS Code
  4. JavaScript Code
  5. Conclusion
  6. Preview

Creating a loan calculator with a graphical representation is an excellent project to learn web development. This tutorial will walk you through creating a loan calculator using HTML, CSS, and JavaScript, with a graphical representation of the principal and interest using Chart.js.

Features

  1. User-Friendly Interface: The calculator will have an easy-to-use interface for users to input loan details.
  2. Real-Time Calculations: Instant calculation of monthly payments, total payment, and total interest.
  3. Graphical Representation: A pie chart that visually displays the principal and interest portions of the loan using Chart.js.
  4. Dark Mode: A toggle switch for a dark mode to enhance the user experience.
  5. Responsive Design: The calculator will be responsive, ensuring a great look on both desktop and mobile devices.

Let’s start building your loan calculator.

Source Code

Step 1 (HTML Code):

Begin by setting up the basic HTML structure. This includes input fields for the loan amount, interest rate, and loan term, as well as a canvas for the Chart.js graph.

Here's a breakdown of the HTML code:

<!DOCTYPE html>

  • Declaration: Specifies the document type and version of HTML (HTML5 in this case).

<html lang="en">

  • <html> Tag: The root element that wraps all the content on the page.
  • lang="en": Indicates that the language of the page content is English.

<head>

  • Head Section: Contains metadata and links to resources like stylesheets and scripts.

<meta charset="UTF-8">

  • Character Encoding: Specifies that the document uses UTF-8 character encoding.

<meta name="viewport" content="width=device-width, initial-scale=1.0">

  • Viewport Settings: Ensures the page is responsive on different devices by setting the viewport width to the device width.

<title>Loan Calculator</title>

  • Title: Defines the title of the webpage, which appears in the browser tab.

<link rel="stylesheet" href="styles.css">

  • Stylesheet Link: Links to an external CSS file named styles.css for styling the webpage.

<body>

  • Body Section: Contains the content that will be displayed on the webpage.

Dark Mode Toggle

<div class="dark-mode-toggle">
    <label class="switch">
        <input type="checkbox" id="dark-mode-switch">
        <span class="slider"></span>
    </label>
</div>
  • Dark Mode Toggle: This section creates a toggle switch that users can click to switch between light and dark modes.

Main Container

<div class="container">
    <h1>Loan Calculator</h1>
  • Container: A wrapper for the main content of the page, including the title and calculator.

Calculator Form

<div class="calculator">
    <div class="input-group">
        <label for="amount">Loan Amount ($)</label>
        <input type="number" id="amount" placeholder="Enter amount" />
    </div>
    <div class="input-group">
        <label for="rate">Interest Rate (%)</label>
        <input type="number" id="rate" placeholder="Enter rate" />
    </div>
    <div class="input-group">
        <label for="years">Loan Term (Years)</label>
        <input type="number" id="years" placeholder="Enter years" />
        <input type="range" id="year-slider" min="1" max="30" value="15">
    </div>
    <button id="calculate">Calculate</button>
</div>
  • Calculator: Contains input fields where users can enter the loan amount, interest rate, and loan term.
    • <input type="number">: Inputs for entering numerical values for the loan amount, interest rate, and loan term.
    • <input type="range">: A slider that allows users to adjust the loan term within a range of 1 to 30 years.
    • <button id="calculate">Calculate</button>: A button that users click to perform the loan calculation.

Results Display

<div class="results">
    <div id="monthly-payment" class="result-box">Monthly Payment: $0.00</div>
    <div id="total-payment" class="result-box">Total Payment: $0.00</div>
    <div id="total-interest" class="result-box">Total Interest: $0.00</div>
</div>
  • Results: This section displays the calculated monthly payment, total payment, and total interest.

Chart Container

<div id="chart-container">
    <canvas id="payment-chart"></canvas>
</div>
  • Chart: Provides a container for a chart that will visualize the payment details. The <canvas> element is used for rendering the chart.

Scripts

<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="script.js"></script>
  • Scripts:
    • Chart.js: A JavaScript library linked via CDN, used for rendering the payment chart.
    • script.js: Links to an external JavaScript file (script.js) that contains the logic for calculating the loan and updating the page with the results.

Closing Tags

  • </body> and </html>: Close the body and HTML tags, completing the document structure.

Step 2 (CSS Code):

Use CSS to style the calculator and make it look modern and responsive.

Here’s a breakdown of what each part of the CSS does:

General Styles for the Body

body {
  font-family: 'Poppins', sans-serif;
  margin: 0;
  padding: 0;
  background: linear-gradient(135deg, #ff7e5f, #feb47b);
  color: #333;
  transition: background-color 0.3s, color 0.3s;
  overflow-x: hidden;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}
  • Font and Layout:
    • Uses the 'Poppins' font for a modern, clean look.
    • Removes default margin and padding to ensure consistent spacing across browsers.
    • Sets the background to a gradient that transitions from #ff7e5f to #feb47b.
    • Ensures the content is centered both horizontally and vertically with flexbox.
    • The page is designed to cover the entire viewport height (min-height: 100vh), and overflow-x: hidden prevents horizontal scrolling.
  • Transitions:
    • Smoothly transitions the background color and text color when switching between light and dark modes.

Dark Mode Toggle Switch

.dark-mode-toggle {
  position: fixed;
  top: 20px;
  right: 20px;
}

.switch {
  position: relative;
  display: inline-block;
  width: 60px;
  height: 34px;
}

.switch input {
  opacity: 0;
  width: 0;
  height: 0;
}

.slider {
  position: absolute;
  cursor: pointer;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: #ccc;
  transition: .4s;
  border-radius: 34px;
}

.slider:before {
  position: absolute;
  content: "";
  height: 26px;
  width: 26px;
  border-radius: 50%;
  left: 4px;
  bottom: 4px;
  background-color: white;
  transition: .4s;
}

input:checked + .slider {
  background-color: #ff7e5f;
}

input:checked + .slider:before {
  transform: translateX(26px);
}
  • Positioning: The toggle is positioned at the top-right corner of the screen.
  • Switch Style:
    • The switch is styled to look like a slider.
    • The slider background changes color when toggled, indicating the dark mode activation.
    • The circle inside the slider (slider:before) moves to the right when the switch is toggled.

Container and Form Elements

.container {
  width: 100%;
  max-width: 450px;
  background: #fff;
  padding: 20px;
  border-radius: 20px;
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.2);
  text-align: center;
  margin: 20px;
  transform: scale(0.95);
  transition: transform 0.3s ease-in-out;
  overflow: hidden; 
}

h1 {
  margin-bottom: 20px;
  font-size: 2em;
  color: #333;
  letter-spacing: 1px;
}
  • Container Styling:
    • The container has a white background, rounded corners, and a subtle shadow to make it stand out.
    • The container scales slightly down (transform: scale(0.95)) and has a smooth scaling transition.
  • Heading (h1):
    • Styled to be large and centered, with letter-spacing for readability.

Input Groups

.input-group {
  margin-bottom: 15px;
  position: relative;
}

.input-group label {
  display: block;
  margin-bottom: 5px;
  font-weight: bold;
}

.input-group input[type="number"],
.input-group input[type="range"] {
  width: 100%;
  padding: 12px;
  border-radius: 30px;
  border: 1px solid #ddd;
  font-size: 1em;
  background-color: #f9f9f9;
  box-sizing: border-box;
  overflow: hidden;
}

.input-group input[type="number"]:focus {
    box-shadow: inset 0 4px 12px rgba(0, 0, 0, 0.2);
    outline: none;
}

.input-group input[type="number"]::-webkit-inner-spin-button,
.input-group input[type="number"]::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
  • Input Group:
    • Each input group (label + input) has margin for spacing and is relatively positioned for further customization.
    • Labels are bold and have a small margin at the bottom.
  • Inputs:
    • The input elements (for numbers and sliders) have a rounded shape, padding, and a light background color.
    • On focus, the input shows an inset shadow, making it visually distinct.
    • The spin buttons in the number input fields are removed for a cleaner look.

Button

button {
  width: 100%;
  padding: 15px;
  border-radius: 30px;
  border: none;
  background-color: #ff7e5f;
  color: #fff;
  font-size: 1.2em;
  cursor: pointer;
  transition: background-color 0.3s ease, transform 0.3s ease;
}

button:hover {
  background-color: #feb47b;
  transform: translateY(-3px);
}
  • Button Styling:
    • The button is wide, with ample padding, a bright background color, and rounded corners.
    • On hover, the background color changes, and the button slightly raises (transform: translateY(-3px)), providing feedback to the user.

Results and Animation

.results {
  margin-bottom: 20px;
}

.result-box {
  margin-bottom: 10px;
  padding: 10px;
  background-color: #f1f1f1;
  border-radius: 30px;
  font-size: 1.1em;
  color: #495057;
  animation: fadeIn 0.5s ease-in-out;
}

@keyframes fadeIn {
  from { opacity: 0; transform: translateY(20px); }
  to { opacity: 1; transform: translateY(0); }
}

#chart-container {
  width: 100%;
  height: 250px;
  animation: fadeIn 0.5s ease-in-out;
}
  • Results Section:
    • Each result box is styled with padding, a light background, and rounded corners.
    • The fadeIn animation makes the result boxes slide up and fade in when they appear.
  • Chart Container:
    • The chart container takes the full width and has a height of 250px. It also has the fadeIn animation for a smooth appearance.

Dark Mode Styles

.dark-mode {
  background-color: #333;
  color: #f4f4f4;
}

.dark-mode .container {
  background-color: #444;
  box-shadow: none;
}

.dark-mode h1 {
  color: #f4f4f4;
}

.dark-mode input[type="number"],
.dark-mode input[type="range"],
.dark-mode button {
  background-color: #555;
  color: #f4f4f4;
  border: 1px solid #666;
}

.dark-mode button:hover {
  background-color: #feb47b;
}
  • Dark Mode Styling:
    • Changes the background and text colors to darker tones.
    • The container’s background and input fields are darkened to match the dark mode theme.
    • Removes the box shadow in dark mode for a flatter look.
body {
  font-family: 'Poppins', sans-serif;
  margin: 0;
  padding: 0;
  background: linear-gradient(135deg, #ff7e5f, #feb47b);
  color: #333;
  transition: background-color 0.3s, color 0.3s;
  overflow-x: hidden;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.dark-mode-toggle {
  position: fixed;
  top: 20px;
  right: 20px;
}

.switch {
  position: relative;
  display: inline-block;
  width: 60px;
  height: 34px;
}

.switch input {
  opacity: 0;
  width: 0;
  height: 0;
}

.slider {
  position: absolute;
  cursor: pointer;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: #ccc;
  transition: .4s;
  border-radius: 34px;
}

.slider:before {
  position: absolute;
  content: "";
  height: 26px;
  width: 26px;
  border-radius: 50%;
  left: 4px;
  bottom: 4px;
  background-color: white;
  transition: .4s;
}

input:checked + .slider {
  background-color: #ff7e5f;
}

input:checked + .slider:before {
  transform: translateX(26px);
}

.container {
  width: 100%;
  max-width: 450px;
  background: #fff;
  padding: 20px;
  border-radius: 20px;
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.2);
  text-align: center;
  margin: 20px;
  transform: scale(0.95);
  transition: transform 0.3s ease-in-out;
  overflow: hidden; 
}

h1 {
  margin-bottom: 20px;
  font-size: 2em;
  color: #333;
  letter-spacing: 1px;
}

.calculator {
  margin-bottom: 20px;
}

.input-group {
  margin-bottom: 15px;
  position: relative;
}

.input-group label {
  display: block;
  margin-bottom: 5px;
  font-weight: bold;
}

.input-group input[type="number"],
.input-group input[type="range"] {
  width: 100%;
  padding: 12px;
  border-radius: 30px;
  border: 1px solid #ddd;
  font-size: 1em;
  background-color: #f9f9f9;
  box-sizing: border-box;
  overflow: hidden;
}

.input-group input[type="number"]:focus {
    box-shadow: inset 0 4px 12px rgba(0, 0, 0, 0.2);
    outline: none;
}

.input-group input[type="number"]::-webkit-inner-spin-button,
.input-group input[type="number"]::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

button {
  width: 100%;
  padding: 15px;
  border-radius: 30px;
  border: none;
  background-color: #ff7e5f;
  color: #fff;
  font-size: 1.2em;
  cursor: pointer;
  transition: background-color 0.3s ease, transform 0.3s ease;
}

button:hover {
  background-color: #feb47b;
  transform: translateY(-3px);
}

.results {
  margin-bottom: 20px;
}

.result-box {
  margin-bottom: 10px;
  padding: 10px;
  background-color: #f1f1f1;
  border-radius: 30px;
  font-size: 1.1em;
  color: #495057;
  animation: fadeIn 0.5s ease-in-out;
}

@keyframes fadeIn {
  from { opacity: 0; transform: translateY(20px); }
  to { opacity: 1; transform: translateY(0); }
}

#chart-container {
  width: 100%;
  height: 250px;
  animation: fadeIn 0.5s ease-in-out;
}

.dark-mode {
  background-color: #333;
  color: #f4f4f4;
}

.dark-mode .container {
  background-color: #444;
  box-shadow: none;
}

.dark-mode h1 {
  color: #f4f4f4;
}

.dark-mode input[type="number"],
.dark-mode input[type="range"],
.dark-mode button {
  background-color: #555;
  color: #f4f4f4;
  border: 1px solid #666;
}

.dark-mode button:hover {
  background-color: #feb47b;
} 

Step 3 (JavaScript Code):

Now, add JavaScript to handle the calculations and generate the graphical representation using Chart.js.

Here's an explanation of the JavaScript code:

1. Dark Mode Toggle:

document.getElementById('dark-mode-switch').addEventListener('change', function() {
  document.body.classList.toggle('dark-mode', this.checked);
});
  • This block listens for a change event on the dark-mode-switch checkbox.
  • When the checkbox is toggled, it either adds or removes the dark-mode class on the <body> element, depending on whether the checkbox is checked. This class changes the color scheme of the page.

2. Calculate Monthly Payment:

document.getElementById('calculate').addEventListener('click', function() {
    const amount = document.getElementById('amount').value;
    const rate = document.getElementById('rate').value;
    const years = document.getElementById('years').value;

    const principal = parseFloat(amount);
    const calculatedInterest = parseFloat(rate) / 100 / 12;
    const calculatedPayments = parseFloat(years) * 12;

    const x = Math.pow(1 + calculatedInterest, calculatedPayments);
    const monthly = (principal * x * calculatedInterest) / (x - 1);

    if (isFinite(monthly)) {
        const totalPayment = (monthly * calculatedPayments).toFixed(2);
        const totalInterest = (totalPayment - principal).toFixed(2);

        document.getElementById('monthly-payment').textContent = `Monthly Payment: $${monthly.toFixed(2)}`;
        document.getElementById('total-payment').textContent = `Total Payment: $${totalPayment}`;
        document.getElementById('total-interest').textContent = `Total Interest: $${totalInterest}`;

        updateChart(principal, totalInterest);
    } else {
        alert('Please check your numbers');
    }
});
  • When the calculate button is clicked, it retrieves the values for the amount, rate, and years from the respective input fields.
  • It converts these values to numbers and calculates the monthly payment using the formula for an amortizing loan.
  • If the result is a finite number, it calculates the total payment and total interest over the loan period.
  • The results are then displayed on the page in the appropriate HTML elements.
  • Finally, it calls the updateChart function to update the chart with the principal and interest values.

3. Synchronizing the Slider and Input:

document.getElementById('year-slider').addEventListener('input', function() {
    document.getElementById('years').value = this.value;
});
  • This block listens for input events on a slider (year-slider).
  • As the slider is moved, it updates the value of the years input field to match the slider's current value.

4. Update Chart Function:

function updateChart(principal, interest) {
    if (paymentChart) {
        paymentChart.destroy();
    }

    const ctx = document.getElementById('payment-chart').getContext('2d');
    paymentChart = new Chart(ctx, {
        type: 'doughnut',
        data: {
            labels: ['Principal', 'Interest'],
            datasets: [{
                data: [principal, interest],
                backgroundColor: ['#28a745', '#007bff']
            }]
        },
        options: {
            responsive: true,
            maintainAspectRatio: false,
            legend: {
                position: 'bottom'
            }
        }
    });
}
  • This function updates a doughnut chart that visualizes the breakdown of the principal and interest.
  • If a chart already exists (paymentChart), it is destroyed to avoid creating multiple instances.
  • It then creates a new Chart object, setting it up as a doughnut chart with the principal and interest data.
  • The chart displays these two values with different colors and is responsive to ensure it fits well on various screen sizes.
let paymentChart;

document.getElementById('dark-mode-switch').addEventListener('change', function() {
  document.body.classList.toggle('dark-mode', this.checked);
});

document.getElementById('calculate').addEventListener('click', function() {
    const amount = document.getElementById('amount').value;
    const rate = document.getElementById('rate').value;
    const years = document.getElementById('years').value;

    const principal = parseFloat(amount);
    const calculatedInterest = parseFloat(rate) / 100 / 12;
    const calculatedPayments = parseFloat(years) * 12;

    const x = Math.pow(1 + calculatedInterest, calculatedPayments);
    const monthly = (principal * x * calculatedInterest) / (x - 1);

    if (isFinite(monthly)) {
        const totalPayment = (monthly * calculatedPayments).toFixed(2);
        const totalInterest = (totalPayment - principal).toFixed(2);

        document.getElementById('monthly-payment').textContent = `Monthly Payment: $${monthly.toFixed(2)}`;
        document.getElementById('total-payment').textContent = `Total Payment: $${totalPayment}`;
        document.getElementById('total-interest').textContent = `Total Interest: $${totalInterest}`;

        updateChart(principal, totalInterest);
    } else {
        alert('Please check your numbers');
    }
});

document.getElementById('year-slider').addEventListener('input', function() {
    document.getElementById('years').value = this.value;
});

function updateChart(principal, interest) {
    if (paymentChart) {
        paymentChart.destroy(); 
    }

    const ctx = document.getElementById('payment-chart').getContext('2d');
    paymentChart = new Chart(ctx, {
        type: 'doughnut',
        data: {
            labels: ['Principal', 'Interest'],
            datasets: [{
                data: [principal, interest],
                backgroundColor: ['#28a745', '#007bff']
            }]
        },
        options: {
            responsive: true,
            maintainAspectRatio: false,
            legend: {
                position: 'bottom'
            }
        }
    });
}

Final Output:

create-loan-calculator-using-html-css-and-javascript.gif

Conclusion:

Congratulations! You’ve successfully built a loan calculator with HTML, CSS, JavaScript, and Chart.js. This project is a fantastic way to improve your web development skills while creating a practical tool. The graphical representation enhances the user experience, making the calculator more interactive and visually appealing.

Feel free to expand the functionality or refine the design further to match your preferences.

That’s a wrap!

I hope you enjoyed this post. Now, with these examples, you can create your own amazing page.

Did you like it? Let me know in the comments below 🔥 and you can support me by buying me a coffee

And don’t forget to sign up to our email newsletter so you can get useful content like this sent right to your inbox!

Thanks!
Faraz 😊

End of the article

Subscribe to my Newsletter

Get the latest posts delivered right to your inbox


Latest Post

Please allow ads on our site🥺