Thumbnail

Finance Tracker Using HTML, CSS and JavaScript

Introduction :

This Finance Tracker is a web application designed to help users manage their finances by keeping track of their transactions. It allows users to add both income and expense transactions, dynamically displaying them on the page along with their current balance.

It helps to empower individuals in managing their finances effectively. In an era where financial literacy and management are crucial, this tool serves as a beacon of assistance, providing a simple yet powerful platform for users to monitor their monetary inflows and outflows.

Financial management is not merely about tracking numbers; it’s about gaining control over one’s financial destiny. The Finance Tracker embodies this philosophy by offering a seamless interface that facilitates the recording and analysis of financial transactions. Whether it’s monitoring monthly expenses, tracking income sources, or identifying spending patterns, this tool equips users with the insights needed to make informed financial decisions.

Navigating through the complexities of personal finance can often be daunting. Recognizing this challenge, the Finance Tracker prioritizes user experience, offering an intuitive interface that simplifies the process of recording transactions. From adding income sources to categorizing expenses, every feature is meticulously crafted to ensure a seamless user journey, allowing individuals to focus on what matters most—taking control of their financial future.

Real-Time Insights:

In the fast-paced world of finance, having access to real-time information is paramount. The Finance Tracker empowers users with instant insights into their financial status, displaying their current balance alongside a detailed transaction history. By providing up-to-the-minute updates, users can stay informed about their financial health, enabling proactive decision-making and ensuring financial stability.

Customizable Financial Management:

Recognizing that every individual’s financial journey is unique, the Finance Tracker offers flexibility and customization options to cater to diverse needs. Whether it’s setting personalized budget goals, creating custom transaction categories, or generating tailored reports, users have the freedom to adapt the platform to suit their specific financial objectives, empowering them to chart their own path to financial success.

Commitment to Financial Wellness:

At its core, the Finance Tracker is more than just a tool; it’s a partner in the journey towards financial wellness. By promoting transparency, accountability, and mindfulness in financial management, this platform fosters a culture of empowerment and resilience, guiding users towards a brighter and more secure financial future.

In essence, the Finance Tracker is not just another application—it’s a catalyst for transformation, empowering individuals to take charge of their financial destiny and embark on a journey towards lasting prosperity and peace of mind.

Explanation :

The project consists of HTML, CSS, and JavaScript files. The HTML file defines the structure of the webpage, including sections for displaying the balance, adding transactions, and listing transactions. The CSS file styles the elements to enhance the visual appeal and readability of the webpage. The JavaScript file provides the logic for updating the balance, adding transactions, and validating user inputs.

HTML Structure:

  • The HTML file provides the structural foundation of the Finance Tracker web application.
  • It comprises several sections, each serving a distinct purpose:
  • Balance Section: Displays the current balance.
  • Add Transaction Section: Allows users to input transaction details such as description, amount, and type (income or expense).
  • Transactions Section: Lists the recorded transactions.
  • Each section is semantically defined using appropriate HTML5 tags, enhancing accessibility and SEO-friendliness.

CSS Styling:

  • The CSS file styles the HTML elements to enhance visual appeal and user experience.
  • It employs a combination of layout, typography, color, and animation techniques to create a cohesive and aesthetically pleasing design.
  • Selectors target specific elements, applying styles such as colors, margins, padding, borders, and animations to achieve the desired presentation.
  • CSS animations add dynamic visual effects, such as background color changes and item fade-ins, improving interactivity and engagement.

JavaScript Logic:

  • The JavaScript file provides the functional logic required for the Finance Tracker’s dynamic behavior.
  • It initializes variables to reference important DOM elements such as the balance amount, transaction list, and user input fields.
  • Functions are defined to handle key tasks:
  • updateBalance(): Updates the displayed balance based on recorded transactions.
  • addTransaction(description, amount, type): Adds a new transaction to the list and updates the balance accordingly.
  • Event listeners are set up to respond to user interactions, such as clicking the add transaction button.
  • Input validation ensures that only valid transaction data is processed, enhancing data integrity and user experience.

Purpose of Functions:

  • updateBalance(): Ensures that the balance displayed to the user accurately reflects the total of all recorded transactions. It maintains data consistency and provides users with real-time financial information.
  • addTransaction(description, amount, type): Facilitates the addition of new transactions to the list, updating both the displayed transactions and the overall balance. This function encapsulates the transactional logic, making the addition process modular and reusable.
  • Event listeners: Enable the Finance Tracker to respond to user actions in an interactive manner. They trigger appropriate functions based on user inputs, driving the dynamic behavior of the application.
  • Input validation: Enhances the robustness of the application by ensuring that only valid transaction data is processed. This prevents errors and inconsistencies, maintaining the integrity of the financial records.

In-depth Analysis:

  • The HTML, CSS, and JavaScript files work synergistically to create a cohesive and functional web application.
  • The HTML defines the structure, the CSS styles the presentation, and the JavaScript provides the dynamic behavior.
  • Modularization and encapsulation principles are observed in the JavaScript code, promoting code reusability, maintainability, and scalability.
  • User experience considerations, such as animation effects and input validation, enhance usability and engagement.
  • The application’s architecture reflects best practices in web development, fostering a robust and user-friendly financial management solution.

SOURCE CODE :

HTML (index.html)

				
					<!DOCTYPE html>
<html lang="en">

<head> <script src="index.js" type="module"></script> <link rel="stylesheet" href="style.css" />
  <title>Finance Tracker</title>
</head>

<body>
  <main>
    <section id="balance">
      <h2>Your Balance: <span id="balance-amount">$0.00</span></h2>
    </section>

    <section id="add-transaction">
      <h2>Add Transaction</h2>
      <label for="description">Description:</label>
      <input type="text" id="description" placeholder="Enter description" />
      <label for="amount">Amount:</label>
      <input type="number" id="amount" placeholder="Enter amount" />
      <select id="transaction-type">
        <option value="income">Income</option>
        <option value="expense">Expense</option>
      </select>
      <button id="add-button">Add Transaction</button>
    </section>

    <section id="transactions">
      <h2>Transactions</h2>
      <ul id="transaction-list">
        
      </ul>
    </section>
  </main> <script data-no-optimize="1">!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).LazyLoad=e()}(this,function(){"use strict";function e(){return(e=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n,a=arguments[e];for(n in a)Object.prototype.hasOwnProperty.call(a,n)&&(t[n]=a[n])}return t}).apply(this,arguments)}function i(t){return e({},it,t)}function o(t,e){var n,a="LazyLoad::Initialized",i=new t(e);try{n=new CustomEvent(a,{detail:{instance:i}})}catch(t){(n=document.createEvent("CustomEvent")).initCustomEvent(a,!1,!1,{instance:i})}window.dispatchEvent(n)}function l(t,e){return t.getAttribute(gt+e)}function c(t){return l(t,bt)}function s(t,e){return function(t,e,n){e=gt+e;null!==n?t.setAttribute(e,n):t.removeAttribute(e)}(t,bt,e)}function r(t){return s(t,null),0}function u(t){return null===c(t)}function d(t){return c(t)===vt}function f(t,e,n,a){t&&(void 0===a?void 0===n?t(e):t(e,n):t(e,n,a))}function _(t,e){nt?t.classList.add(e):t.className+=(t.className?" ":"")+e}function v(t,e){nt?t.classList.remove(e):t.className=t.className.replace(new RegExp("(^|\\s+)"+e+"(\\s+|$)")," ").replace(/^\s+/,"").replace(/\s+$/,"")}function g(t){return t.llTempImage}function b(t,e){!e||(e=e._observer)&&e.unobserve(t)}function p(t,e){t&&(t.loadingCount+=e)}function h(t,e){t&&(t.toLoadCount=e)}function n(t){for(var e,n=[],a=0;e=t.children[a];a+=1)"SOURCE"===e.tagName&&n.push(e);return n}function m(t,e){(t=t.parentNode)&&"PICTURE"===t.tagName&&n(t).forEach(e)}function a(t,e){n(t).forEach(e)}function E(t){return!!t[st]}function I(t){return t[st]}function y(t){return delete t[st]}function A(e,t){var n;E(e)||(n={},t.forEach(function(t){n[t]=e.getAttribute(t)}),e[st]=n)}function k(a,t){var i;E(a)&&(i=I(a),t.forEach(function(t){var e,n;e=a,(t=i[n=t])?e.setAttribute(n,t):e.removeAttribute(n)}))}function L(t,e,n){_(t,e.class_loading),s(t,ut),n&&(p(n,1),f(e.callback_loading,t,n))}function w(t,e,n){n&&t.setAttribute(e,n)}function x(t,e){w(t,ct,l(t,e.data_sizes)),w(t,rt,l(t,e.data_srcset)),w(t,ot,l(t,e.data_src))}function O(t,e,n){var a=l(t,e.data_bg_multi),i=l(t,e.data_bg_multi_hidpi);(a=at&&i?i:a)&&(t.style.backgroundImage=a,n=n,_(t=t,(e=e).class_applied),s(t,ft),n&&(e.unobserve_completed&&b(t,e),f(e.callback_applied,t,n)))}function N(t,e){!e||0<e.loadingCount||0<e.toLoadCount||f(t.callback_finish,e)}function C(t,e,n){t.addEventListener(e,n),t.llEvLisnrs[e]=n}function M(t){return!!t.llEvLisnrs}function z(t){if(M(t)){var e,n,a=t.llEvLisnrs;for(e in a){var i=a[e];n=e,i=i,t.removeEventListener(n,i)}delete t.llEvLisnrs}}function R(t,e,n){var a;delete t.llTempImage,p(n,-1),(a=n)&&--a.toLoadCount,v(t,e.class_loading),e.unobserve_completed&&b(t,n)}function T(o,r,c){var l=g(o)||o;M(l)||function(t,e,n){M(t)||(t.llEvLisnrs={});var a="VIDEO"===t.tagName?"loadeddata":"load";C(t,a,e),C(t,"error",n)}(l,function(t){var e,n,a,i;n=r,a=c,i=d(e=o),R(e,n,a),_(e,n.class_loaded),s(e,dt),f(n.callback_loaded,e,a),i||N(n,a),z(l)},function(t){var e,n,a,i;n=r,a=c,i=d(e=o),R(e,n,a),_(e,n.class_error),s(e,_t),f(n.callback_error,e,a),i||N(n,a),z(l)})}function G(t,e,n){var a,i,o,r,c;t.llTempImage=document.createElement("IMG"),T(t,e,n),E(c=t)||(c[st]={backgroundImage:c.style.backgroundImage}),o=n,r=l(a=t,(i=e).data_bg),c=l(a,i.data_bg_hidpi),(r=at&&c?c:r)&&(a.style.backgroundImage='url("'.concat(r,'")'),g(a).setAttribute(ot,r),L(a,i,o)),O(t,e,n)}function D(t,e,n){var a;T(t,e,n),a=e,e=n,(t=It[(n=t).tagName])&&(t(n,a),L(n,a,e))}function V(t,e,n){var a;a=t,(-1<yt.indexOf(a.tagName)?D:G)(t,e,n)}function F(t,e,n){var a;t.setAttribute("loading","lazy"),T(t,e,n),a=e,(e=It[(n=t).tagName])&&e(n,a),s(t,vt)}function j(t){t.removeAttribute(ot),t.removeAttribute(rt),t.removeAttribute(ct)}function P(t){m(t,function(t){k(t,Et)}),k(t,Et)}function S(t){var e;(e=At[t.tagName])?e(t):E(e=t)&&(t=I(e),e.style.backgroundImage=t.backgroundImage)}function U(t,e){var n;S(t),n=e,u(e=t)||d(e)||(v(e,n.class_entered),v(e,n.class_exited),v(e,n.class_applied),v(e,n.class_loading),v(e,n.class_loaded),v(e,n.class_error)),r(t),y(t)}function $(t,e,n,a){var i;n.cancel_on_exit&&(c(t)!==ut||"IMG"===t.tagName&&(z(t),m(i=t,function(t){j(t)}),j(i),P(t),v(t,n.class_loading),p(a,-1),r(t),f(n.callback_cancel,t,e,a)))}function q(t,e,n,a){var i,o,r=(o=t,0<=pt.indexOf(c(o)));s(t,"entered"),_(t,n.class_entered),v(t,n.class_exited),i=t,o=a,n.unobserve_entered&&b(i,o),f(n.callback_enter,t,e,a),r||V(t,n,a)}function H(t){return t.use_native&&"loading"in HTMLImageElement.prototype}function B(t,i,o){t.forEach(function(t){return(a=t).isIntersecting||0<a.intersectionRatio?q(t.target,t,i,o):(e=t.target,n=t,a=i,t=o,void(u(e)||(_(e,a.class_exited),$(e,n,a,t),f(a.callback_exit,e,n,t))));var e,n,a})}function J(e,n){var t;et&&!H(e)&&(n._observer=new IntersectionObserver(function(t){B(t,e,n)},{root:(t=e).container===document?null:t.container,rootMargin:t.thresholds||t.threshold+"px"}))}function K(t){return Array.prototype.slice.call(t)}function Q(t){return t.container.querySelectorAll(t.elements_selector)}function W(t){return c(t)===_t}function X(t,e){return e=t||Q(e),K(e).filter(u)}function Y(e,t){var n;(n=Q(e),K(n).filter(W)).forEach(function(t){v(t,e.class_error),r(t)}),t.update()}function t(t,e){var n,a,t=i(t);this._settings=t,this.loadingCount=0,J(t,this),n=t,a=this,Z&&window.addEventListener("online",function(){Y(n,a)}),this.update(e)}var Z="undefined"!=typeof window,tt=Z&&!("onscroll"in window)||"undefined"!=typeof navigator&&/(gle|ing|ro)bot|crawl|spider/i.test(navigator.userAgent),et=Z&&"IntersectionObserver"in window,nt=Z&&"classList"in document.createElement("p"),at=Z&&1<window.devicePixelRatio,it={elements_selector:".lazy",container:tt||Z?document:null,threshold:300,thresholds:null,data_src:"src",data_srcset:"srcset",data_sizes:"sizes",data_bg:"bg",data_bg_hidpi:"bg-hidpi",data_bg_multi:"bg-multi",data_bg_multi_hidpi:"bg-multi-hidpi",data_poster:"poster",class_applied:"applied",class_loading:"litespeed-loading",class_loaded:"litespeed-loaded",class_error:"error",class_entered:"entered",class_exited:"exited",unobserve_completed:!0,unobserve_entered:!1,cancel_on_exit:!0,callback_enter:null,callback_exit:null,callback_applied:null,callback_loading:null,callback_loaded:null,callback_error:null,callback_finish:null,callback_cancel:null,use_native:!1},ot="src",rt="srcset",ct="sizes",lt="poster",st="llOriginalAttrs",ut="loading",dt="loaded",ft="applied",_t="error",vt="native",gt="data-",bt="ll-status",pt=[ut,dt,ft,_t],ht=[ot],mt=[ot,lt],Et=[ot,rt,ct],It={IMG:function(t,e){m(t,function(t){A(t,Et),x(t,e)}),A(t,Et),x(t,e)},IFRAME:function(t,e){A(t,ht),w(t,ot,l(t,e.data_src))},VIDEO:function(t,e){a(t,function(t){A(t,ht),w(t,ot,l(t,e.data_src))}),A(t,mt),w(t,lt,l(t,e.data_poster)),w(t,ot,l(t,e.data_src)),t.load()}},yt=["IMG","IFRAME","VIDEO"],At={IMG:P,IFRAME:function(t){k(t,ht)},VIDEO:function(t){a(t,function(t){k(t,ht)}),k(t,mt),t.load()}},kt=["IMG","IFRAME","VIDEO"];return t.prototype={update:function(t){var e,n,a,i=this._settings,o=X(t,i);{if(h(this,o.length),!tt&&et)return H(i)?(e=i,n=this,o.forEach(function(t){-1!==kt.indexOf(t.tagName)&&F(t,e,n)}),void h(n,0)):(t=this._observer,i=o,t.disconnect(),a=t,void i.forEach(function(t){a.observe(t)}));this.loadAll(o)}},destroy:function(){this._observer&&this._observer.disconnect(),Q(this._settings).forEach(function(t){y(t)}),delete this._observer,delete this._settings,delete this.loadingCount,delete this.toLoadCount},loadAll:function(t){var e=this,n=this._settings;X(t,n).forEach(function(t){b(t,e),V(t,n,e)})},restoreAll:function(){var e=this._settings;Q(e).forEach(function(t){U(t,e)})}},t.load=function(t,e){e=i(e);V(t,e)},t.resetStatus=function(t){r(t)},Z&&function(t,e){if(e)if(e.length)for(var n,a=0;n=e[a];a+=1)o(t,n);else o(t,e)}(t,window.lazyLoadOptions),t});!function(e,t){"use strict";function a(){t.body.classList.add("litespeed_lazyloaded")}function n(){console.log("[LiteSpeed] Start Lazy Load Images"),d=new LazyLoad({elements_selector:"[data-lazyloaded]",callback_finish:a}),o=function(){d.update()},e.MutationObserver&&new MutationObserver(o).observe(t.documentElement,{childList:!0,subtree:!0,attributes:!0})}var d,o;e.addEventListener?e.addEventListener("load",n,!1):e.attachEvent("onload",n)}(window,document);</script><script data-no-optimize="1">var litespeed_vary=document.cookie.replace(/(?:(?:^|.*;\s*)_lscache_vary\s*\=\s*([^;]*).*$)|^.*$/,"");litespeed_vary||fetch("/wp-content/plugins/litespeed-cache/guest.vary.php",{method:"POST",cache:"no-cache",redirect:"follow"}).then(e=>e.json()).then(e=>{console.log(e),e.hasOwnProperty("reload")&&"yes"==e.reload&&(sessionStorage.setItem("litespeed_docref",document.referrer),window.location.reload(!0))});</script><script data-optimized="1" type="litespeed/javascript" data-src="https://foolishdeveloper.com/wp-content/litespeed/js/f21cbb88936c42dc19773a8407b9c20a.js?ver=519e0"></script><script>const litespeed_ui_events=["mouseover","click","keydown","wheel","touchmove","touchstart"];var urlCreator=window.URL||window.webkitURL;function litespeed_load_delayed_js_force(){console.log("[LiteSpeed] Start Load JS Delayed"),litespeed_ui_events.forEach(e=>{window.removeEventListener(e,litespeed_load_delayed_js_force,{passive:!0})}),document.querySelectorAll("iframe[data-litespeed-src]").forEach(e=>{e.setAttribute("src",e.getAttribute("data-litespeed-src"))}),"loading"==document.readyState?window.addEventListener("DOMContentLoaded",litespeed_load_delayed_js):litespeed_load_delayed_js()}litespeed_ui_events.forEach(e=>{window.addEventListener(e,litespeed_load_delayed_js_force,{passive:!0})});async function litespeed_load_delayed_js(){let t=[];for(var d in document.querySelectorAll('script[type="litespeed/javascript"]').forEach(e=>{t.push(e)}),t)await new Promise(e=>litespeed_load_one(t[d],e));document.dispatchEvent(new Event("DOMContentLiteSpeedLoaded")),window.dispatchEvent(new Event("DOMContentLiteSpeedLoaded"))}function litespeed_load_one(t,e){console.log("[LiteSpeed] Load ",t);var d=document.createElement("script");d.addEventListener("load",e),d.addEventListener("error",e),t.getAttributeNames().forEach(e=>{"type"!=e&&d.setAttribute("data-src"==e?"src":e,t.getAttribute(e))});let a=!(d.type="text/javascript");!d.src&&t.textContent&&(d.src=litespeed_inline2src(t.textContent),a=!0),t.after(d),t.remove(),a&&e()}function litespeed_inline2src(t){try{var d=urlCreator.createObjectURL(new Blob([t.replace(/^(?:<!--)?(.*?)(?:-->)?$/gm,"$1")],{type:"text/javascript"}))}catch(e){d="data:text/javascript;base64,"+btoa(t.replace(/^(?:<!--)?(.*?)(?:-->)?$/gm,"$1"))}return d}</script></body>

</html>
				
			

CSS (style.css)

				
					* {
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}

header {
  background-color: #333;
  color: #fff;
  text-align: center;
  padding: 1rem 0;
  animation: headerBgChange 4s infinite alternate;
}

/* Animate header background color */

@keyframes headerBgChange {
  0% {
    background-color: #333;
  }

  100% {
    background-color: #007bff;
  }
}

header h1 {
  margin: 0;
}

main {
  max-width: 800px;
  margin: 0 auto;
  padding: 1rem;
  background-color: #fff;
  border-radius: 5px;
}

#balance {
  text-align: center;
}

#balance h2 {
  margin: 0;
  font-size: 1.5rem;
}

#balance-amount {
  color: #28a745;
}

#transactions h2,
#add-transaction h2 {
  font-size: 1.2rem;
  margin-top: 1rem;
}

ul {
  list-style: none;
  padding: 0;
}

li {
  display: flex;
  justify-content: space-between;
  margin: 0.5rem 0;
  padding: 0.5rem;
  border: 1px solid #ccc;
  background-color: #fff;
  border-radius: 5px;
  animation: listItemFadeIn 0.5s ease-in-out;
}

/* Animate transaction list items */

@keyframes listItemFadeIn {
  0% {
    opacity: 0;
    transform: translateY(-10px);
  }

  100% {
    opacity: 1;
    transform: translateY(0);
  }
}

.income {
  color: #28a745;
}

.expense {
  color: #dc3545;
}

label,
input,
select,
button {
  display: block;
  margin-bottom: 0.5rem;
}

input[type='text'],
input[type='number'],
select {
  width: 100%;
  padding: 0.5rem;
  border: 1px solid #ccc;
  border-radius: 5px;
}

button {
  background-color: #007bff;
  color: #fff;
  border: none;
  padding: 0.5rem 1rem;
  border-radius: 5px;
  cursor: pointer;
}

button:hover {
  background-color: #0056b3;
}

button:hover {
  background-color: #0056b3;
  transform: scale(1.05);
  transition: background-color 0.3s, transform 0.3s;
}
				
			

JavaScript (index.js)

				
					const balanceAmount = document.getElementById('balance-amount');
const transactionList = document.getElementById('transaction-list');
const descriptionInput = document.getElementById('description');
const amountInput = document.getElementById('amount');
const transactionTypeInput = document.getElementById('transaction-type');
const addButton = document.getElementById('add-button');

let balance = 0;

function updateBalance() {
  balanceAmount.textContent = `$${balance.toFixed(2)}`;
}

function addTransaction(description, amount, type) {
  const transaction = document.createElement('li');
  transaction.classList.add(type);
  transaction.innerHTML = `
        <span>${description}</span>
        <span>$${amount.toFixed(2)}</span>
    `;
  transactionList.appendChild(transaction);
  balance += type === 'income' ? amount : -amount;
  updateBalance();
}

addButton.addEventListener('click', () => {
  const description = descriptionInput.value;
  const amount = parseFloat(amountInput.value);
  const type = transactionTypeInput.value;

  if (description.trim() === '' || isNaN(amount) || amount <= 0) {
    alert('Please enter a valid description and amount.');
    return;
  }

  addTransaction(description, amount, type);
  descriptionInput.value = '';
  amountInput.value = '';
});

// Initialize balance
updateBalance();

				
			

OUTPUT :

output