Building shopping cart with html, tailwindcss and Javascript

A shopping cart is a compulsory section in modern ecommerce web application. Ecommerce web apps processes payment of products. Through shopping cart, the web app is able to:

  • Keep track of items selected.
  • Get price of each selected item.
  • Get quantity of items to be purchased.
  • Compute shipping fees
  • Compute total amount to be paid for the items.

In summary, shopping cart facilitates the purchase of product or service.

In this tutorial, I'm going to illustrate how to build an interactive shopping cart with html, tailwindcss and javascript.

To follow along with this tutorial, you need to be familiar with the following:

  • html
  • tailwindcss
  • javascript
  • dom manipulation

NOTE: This tutorial assumes you already select items from the home page. Now you are in the shopping cart page.

Let's start creating shopping cart.

Create html file and configure tailwindcss

First create index.html file and configure tailwindcss to index.html. For installation of tailwindcss in your project, checkout here. Now lets create index.html in our project.

Add the head tag. Inside head tag, link the following:

  • google font to use in the project (fraunces, montserrat).
  • output.css file (generated by tailwindcss when project executes)
  • index.js file (created later)

Below is how head tag looks

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <link rel="preconnect" href="https://fonts.googleapis.com" />
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
  <link
    href="https://fonts.googleapis.com/css2?family=DM+Sans:opsz,wght@9..40,400;9..40,700&family=Fraunces:opsz,wght@9..144,500;9..144,700&family=Montserrat:wght@400;500;700&display=swap"
    rel="stylesheet"
  />
  <link rel="stylesheet" href="./output.css" />
  <script type="module" src="./index.js" defer></script>
  <title>cart</title>
</head>

Now let's go to the body tag. The body tag contains, the header tag, section tag and footer tag.

The header tag consist of the cart logo. The section tag is currently empty (later add cart items). The footer tag contains cart total price, shipping fee and checkout price and checkout button.

<body>
    <main class="md:p-6 md:pt-10 px-2 pt-6">
        <div class="md:flex md:flex-row md:items-center md:justify-between">
        <header class=" flex md:flex flex-row gap-x-2 pb-3 items-center">
          <img src="./images/bag-2.png" alt="" srcset="" />
          <p class="text-darkBlue text-2xl font-bold">Cart</p>
        </header>
      </div>
         <section class="lg:flex lg:flex-row lg:justify-start">
          <section class="lg:w-[65%] lg:pr-4">
           <div
           class="md:w-full border-y-2 py-4 border-lineColor flex flex-row justify-between text-grey font-medium"
         >
           <div class="md:flex md:w-[45%] md:flex-row md:justify-between ">
             <p>PRODUCT</p>
             <p>PRICE</p>
           </div>
           <div class="md:flex md:w-[30%] md:flex-row md:justify-between">
             <p>TOTAL</p>
             <p>QTY</p>
           </div>
         </div>
         <section id="add-items" class="add-cart-items">
              <!-- purchased items -->
         </section>
         <footer class="bg-totalsGrey p-4 lg:px-4 lg:p-0 lg:w-[35%]">
           <div class="total-section">
             <p class="total-amount-name">TOTAL AMOUNT IN CART</p>
             <p id="add-items-cost" class="total-amount">$</p>
           </div>
           <div class="total-section">
             <p class="total-amount-name">SHIPPING FEE</p>
             <p id="shipping-fee" class="total-amount">$</p>
           </div>
           <div class="total-section">
             <p class="total-amount-name">TOTAL AMOUNT</p>
             <p id="total-amount-to-pay" class="total-amount">$</p>
           </div>
           <button id='checkout-btn' class="total-amount mt-4 py-3 w-full active:bg-grey hover:bg-darkBlue bg-blue text-white ">Checkout <span id="checkout-btn-amount">708.85</span></button>
          </footer>
         </section>
       </main>
</body>

NOTE: The colors used in this project are custom colors (not tailwind default colors). These colors are darkBlue, totalsGrey, grey. For more information about tailwind custom colors check here.

Create two javascript files

The first file is item.js file. This file has newItem function. The newItem function takes an object as a parameter. The object has three properties(image, name, price).

The function has two local variables named createDiv and itemHtml. Variable createDiv stores newly created html div. The itemHtml stores html code in a string variable.

The innerHtml property of createDiv is assign to itemHtml. The newItem function returns createDiv. The function is then exported.

export default function newItem(item){
  const createDiv = document.createElement("div");
    const itemHtml = `<div class="border-b-2 md:justify-between border-lineColor flex flex-row py-6">
    <div class="flex md:w-[45%] md:justify-between flex-col md:flex-row md:items-center w-[60%] ">
      <div class="flex flex-row gap-x-2">
        <img class="max-w-[7.5rem] h-auto" src="${item.image}" alt="" srcset="" />
        <div class="md:pr-6 md:flex md:flex-col md:justify-center" >
          <p class="text-lightGrey text-sm md:text-base">Footwear</p>
          <p  style="white-space:wrap;overflow:hidden;width:100%" class="item-description md:text-lg text-base">
            ${item.name}
          </p>
        </div>
      </div>
      <p class="self-end md:self-center text-xl md:text-2xl font-bold mr-4 md:mr-0">${item.price}</p>
    </div>
    <div class="w-[40%] md:w-[30%] flex md:flex-row-reverse md:items-center flex-col items-end justify-between">
      <p id="total-item-cost" class="text-xl md:text-2xl text-purple font-bold">${item.price}</p>
      <div
        class="flex flex-row gap-x-2 items-center border-y-[2px] border-lineColor"
      >
        <button id="decrease" class="increment-btn">-</button>
        <p class="px-2">1</p>
        <button id="increase" class="increment-btn ">+</button>
      </div>
    </div>
  </div>`;
  createDiv.innerHTML = itemHtml;
return createDiv;
}

To the second file now. Create index.js file. In index.js file import the newItem function from item.js file. Rename the imported function to newShoeItem.

import newShoeItem from "./item.js";

The index.js file, contains an array of objects named shoes. The object has image, name and price properties. The objects displays later as cart selected items.

const shoes = [
    {
      name:"Nike Air Force 1",
      price:110,
      image:"https://static.nike.com/a/images/c_limit,w_592,f_auto/t_product_v1/e777c881-5b62-4250-92a6-362967f54cca/air-force-1-07-womens-shoes-b19lqD.png"
    },
    {
      name:"Air Jordan 4 'Black Cat'",
      price:240,
      image:"https://images.stockx.com/images/Air-Jordan-4-Retro-Black-Cat-2020-Product.jpg?fit=fill&bg=FFFFFF&w=700&h=500&fm=webp&auto=compress&q=90&dpr=2&trim=color&updated_at=1606315877"
    },
    {  
      name: "Air Jordan 7 Retro",
      price: 200,
      image: "https://static.nike.com/a/images/t_PDP_864_v1/f_auto,b_rgb:f5f5f5/bd3da02f-2ddc-4f0c-bb7b-f94c634cc0dd/air-jordan-7-retro-mens-shoes-7Zr804.png",  
    },
    {
      name: "Air Jordan 1 Utility",
      price: 170,
      image: "https://static.nike.com/a/images/c_limit,w_592,f_auto/t_product_v1/956b0723-ef2f-4b49-8982-e2ec37e14f9c/air-jordan-1-utility-mens-shoes.png"
    }];

Add DOMContentLoaded event listener. The event calls addItemToCart function after loading dom content.

The addItemsToCart function does the follow:

  1. Get empty select tag with id add-items

  2. Create a loop to get each item object in the array of shoes

  3. Call newShoeItem(imported function) passing each shoe as argument

  4. Insert returned html code to empty select tag of id add-items

     document.addEventListener("DOMContentLoaded",addItemToCart);
    
     function addItemToCart() {
     const addSelectedShoes = document.getElementById("add-items");
     shoes.forEach(shoe=>{
       addSelectedShoes.appendChild(shoeItem(shoe));
       })
     }
    

    Now run index.html file in the browser. Your output should resemble the image below

Initial stage of shopping cart

Quantity manipulation

You'll notice the increment(+) and decrement(-) buttons are not working when clicked. Let's make the buttons functional in index.js file.

Increment quantity

Let's start with increment button.To make items quantity increase when + button is clicked, follow the steps below:

Inside addItemsToCart function

  1. Get all increment buttons

     const incrementButtons = document.querySelectorAll("#increase");
    
  2. Use forEach method to trigger increaseItems function on each button.

     incrementButtons.forEach(increaseItems)
    
  3. The increaseItems function, does the following

    1. Pass in button as parameter
    2. Add click event listener to the button
    3. Use event object to get the current quantity of the items
    4. Increments the current quantity
       function increaseItems(button){
       button.addEventListener("click", function (e){
       e.target.previousElementSibling.textContent++;
        })
       }
      

      Decrement quantity

Making items quantity decrease when clicking - button.

Inside addItemsToCart function

  1. Get all decrement buttons
     const decrementButtons = document.querySelectorAll("#decrease");
    
  2. Use forEach method to trigger decreaseItems function on each button.

     decrementButtons.forEach(decreaseItems)
    
  3. The decreaseItems function does the following:

    1. Pass in button as parameter
    2. Add click event listener to the button
    3. Use event object to get current item quantity
    4. Decrement current quantity, if current quantity is greater than 1
       function decreaseItems(button) {
       button.addEventListener("click", function (e) {
       let currentQuantity = e.target.nextElementSibling.textContent;
       if(currentQuantity > 1){
       e.target.nextElementSibling.textContent--;
           }
         });
       }
      
      Now, we are able to increment and decrement the quantity when + button and - button are clicked as shown below. increment and decrement items quantity in shopping cart We are able to increase and decrease the quantity. But the quantity amount is still constant.

Updating total item price

We need to multiply item price with quantity to get total item price

Create totalItemPrice function. The function will take in two parameters element and siblingPostion. The totalItemPrice function does the following:

  1. Use element parameter(clicked button) to get item price by dom traverse

  2. Use siblingPosition parameter to get item quantity

  3. Multiply item price with item quantity to get total item price

  4. Use element to get text content of total item price and update total item price

     function totalItemPrice(element,siblingPosition){
     let itemPrice = element.parentElement.parentElement.previousElementSibling.children[1].textContent.slice(1);
     let itemQuantity = siblingPosition.textContent;
     let totalItemPrice = itemPrice * itemQuantity;
     element.parentElement.previousElementSibling.textContent = `$${totalItemPrice}`;
     }
    

    Now we need to call totalItemPrice function inside decreaseItem and increaseItem function. This will make item total price update everytime increment and decrement button is clicked.

We'll call totalItemPrice function inside click event function of increaseItem and decreaseItem function.

We'll use the event object to get the arguments in totalItemPrice.

In increaseItem the arguments used in event function are e.target and e.target.previousElementSibling.

const previousSibling = e.target.previusElementSibling;
totalItemPrice(e.target,previousSibling);

In decreaseItem the arguments used in event function are e.target and e.target.nextElementSibling.

const nextSibling = e.target.nextElementSibling;
totalItemPrice(e.target,previousSibling);

The e.target is the button clicked. The e.target.previousElementSibling and e.target.nextElementSibling gets item quantity

Total item price updates when + and - buttons are clicked. update item total price when increase or decrease button is pressed Now we need to sum up item total price.

Compute cart Total price, shipping fee and checkout price

A cart need to sum up total item price, compute shipping fees and calculate the checkout price of the items. We're going to create calculateTotals function. The function returns an array.

calculateTotals function does the following:

  1. Declare cartTotalPrice variable and initialize cartTotalPrice to 0.
  2. Get each item total price and add them to cartTotalPrice.
  3. Declare shippingFee variable and initialize it to 7% of cartTotalPrice.
  4. Declare totalCashToPay variable and initialize it to sum of cartTotalPrice and shippingFee.
  5. Returns an array consisting of three variables; cartTotalPrice, shippingFee and totalCashToPay.
    function calculateTotals() {
     let cartTotalPrice = 0;
     const getItemPrices = document.querySelectorAll("#total-item-cost");
     getItemPrices.forEach(itemPrice =>{
       cartTotalPrice += Number(itemPrice.textContent.slice(1));
     })
     const shippingFee = (cartTotalPrice*7/100);
     const totalCashToPay = cartTotalPrice + shippingFee;
     return [cartTotalPrice.toFixed(2), shippingFee.toFixed(2), totalCashToPay.toFixed(2)]
     }
    

    Updating cart Total price, shipping fee and checkout price on corresponding elements

    We need to update the UI with computed values. Everytime the user decrement or increment quantity, the UI needs to show real time values.

We create updateTotals function which takes in two parameters. The parameters are elementId and value. It then gets the element of the id and update the element text content with the value.

function updateTotals(elementId,value){
  const element = document.querySelector(elementId);
  element.textContent = value;
}

We'll call calculateTotals and updateTotals function inside the totalItemPrice function. This will make updates when either increment or decrement button is clicked.

The calculateTotals function will return an array. Then destructure the array to get three independent value.

const [totalPrice,shippingFee,checkoutPrice] = calculateTotals();

Now we call the updateTotals function to change the initial value of the elements to current value.

  1. Update content of element with id add-items-cost to totalPrice value.
  2. Update content of element with id shipping-fee to shippingFee value.
  3. Update content of element with id total-amount-to-pay to checkoutPrice value.
  4. Update checkout button to read checkoutPrice.
     updateTotals("#add-items-cost",`$${totalPrice}`);
     updateTotals("#shipping-fee",`$${shippingFee}`);
     updateTotals("#total-amount-to-pay",`$${checkoutPrice}`);
     updateTotals("#checkout-btn",`Checkout $${checkoutPrice}`);
    
    Finally your shopping cat should be responsive and resemble the image below. Final shopping cart image Now the shopping cart is responsive and manipulable. In summary the shopping cart is able to:
    • Increase and decrease item quantity
    • Compute item total price
    • Sum item total price
    • Compute shipping fee
    • Compute total checkout price