2

I've been trying to learn Javascript for a while now and came across the term 'Tutorial Purgatory' which i realised applies to me. So I thought I'd make something using what I thought I'd learned so far.

I particularly wanted to create something using objects, function constructors and prototypes. What I wanted was a sort of shopping cart feature which you'll see in the Codepen link below. Rather than manually adding objects for each of the items/products, I wanted to have my code dynamically find all the items/products and convert them to objects which I could access and manipulate in my Javascript. I appreciate there is probably a better was to achieve what I'm looking to do but it's a project that came to my mind that I wanted to have a go at.

I've spent a considerable amount of time trying different things out and have considered taking an easier approach that I feel i could manage (using data attributes) but having spent so long on this I just would like to know if what i'm doing is possible.

At this stage I'd just like to be able to click on the 'add to quote' button and console.log the object/product's properties and values. Line 16 of the JS in the pen is where I'm struggling console.log(this.productTitle);

https://codepen.io/rosstr2/pen/MWaJgZx

(function() {
  // Declare global variables
  const product = new Product();
  const productArr = [];

  // Create Product function constructor
  function Product(productTitle, productPrice, cartBtn) {
    this.productTitle = productTitle;
    this.productPrice = productPrice;
    this.cartBtn = cartBtn;
  }
  // Event listener for logging the product when clicked
  Product.prototype.listProduct = function() {
    this.cartBtn.addEventListener('click', function(event) {
      event.preventDefault();
      console.log(this.productTitle);
    })
  }


  // Seach for all products on the page and convert to objects
  const products = document.querySelectorAll('.product-box');
  for (let i = 0; i < products.length; i++) {
    const singleProduct = products[i];
    const title = singleProduct.querySelector('.product-title').textContent;
    const price = singleProduct.querySelector('.product-price').textContent;
    const btn = singleProduct.querySelector('.add-quote');

    const product = new Product(title, price, btn);
    // add product objects to array
    productArr.push(product);
    product.listProduct();
  }

})();
html {
  box-sizing: border-box;
}

*,
*:before,
*:after {
  box-sizing: inherit;
}

:root {
  --turqoise: #00a492;
  --green: #8fb91e;
  --blue: #00a9e2;
  --black: #333333;
}

body {
  font-family: 'Roboto', sans-serif;
}

.container {
  width: 90%;
  max-width: 1400px;
  margin: 0 auto;
  padding-top: 3em;
}

.site-header {}

.product-box-wrap {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
}

.product-box {
  min-width: 300px;
  width: 22%;
  margin: 1em;
  border: solid 4px var(--turqoise);
  padding: 2em 1.5em;
  border-radius: 3px;
  box-shadow: 3px 3px 3px #ccc;
  display: flex;
  flex-direction: column;
  position: relative;
}

.product-box.active {
  background: #e2e2e2;
  border: solid 4px red;
  box-shadow: none;
}

.product-box h1 {
  font-size: 1.75em;
  font-weight: 700;
  color: var(--turqoise);
  margin-bottom: 0.4em;
}

.product-box p {
  font-size: 1.1em;
  font-weight: 300;
  line-height: 1.5em;
  color: var(--black);
  margin-bottom: 1em;
}

.product-price {
  position: absolute;
  padding: 10px;
  left: 0;
  bottom: 0;
  font-weight: 700;
  font-size: 1.2em;
  color: #fff;
  display: block;
  margin-top: 0.5em;
  background: var(--blue);
}

.add-quote {
  position: absolute;
  padding: 10px;
  right: 0;
  bottom: 0;
  font-weight: 700;
  text-transform: uppercase;
  text-decoration: none;
  font-size: 1.2em;
  color: #fff;
  display: block;
  margin-top: 0.5em;
  background: var(--green);
  transition: background .2s ease-in-out;
}

.add-quote:hover {
  background: var(--turqoise);
}

.quote-output {
  margin: 3em 0;
}

.quote-output h2 {
  font-size: 2.7em;
  color: var(--turqoise);
  margin-bottom: 0.5em;
}

.quote-row {
  display: flex;
  padding: 1.5em 0;
  font-size: 1.7em;
  border-bottom: dotted 1px #000;
}

.remove-item {
  margin-right: 1em;
  text-decoration: none;
  font-weight: 700;
  color: red;
}

.cart-product {
  margin: 0 3em;
}

.cart-total {
  margin-top: 2em;
  font-size: 1.7em;
}

.cart-total p span {
  font-weight: 700;
  padding-right: 3em;
}
<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>Product Totter Upperer</title>
  <meta name="viewport" content="width=device-width; initial-scale=1.0">
  <link href="https://fonts.googleapis.com/css2?family=Bebas+Neue&family=Roboto:ital,wght@0,300;0,400;0,700;0,900;1,300;1,400&display=swap" rel="stylesheet">
  <link rel="stylesheet" href="style.css" />
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>

<body>
  <div class="container">
    <div class="product-box-wrap">

      <div class="product-box active" id="business-cards" data-product="business-cards">
        <h1 class="product-title">Business Cards</h1>
        <p>Business Cards are the most fundamental way to exchange business or personal contact information, therefore the importance of a professionally designed and printed Business Card is greater than ever to secure a long lasting impression of you and
          your company.</p>
        <span class="product-price" data-price="£100">&pound;100.00</span>
        <a href="#" class="add-quote" id="b-card-btn">Add to Cart</a>
      </div>
      <!-- product-box -->

      <div class="product-box lealfet" id="leaflets" data-product="leaflets">
        <h1 class="product-title">Leaflets</h1>
        <p>Printed leaflets are a really effective tool to reach out to potential customers. Whether you're a new business start up or established business, leaflets have a number of purposes when promoting your products/services. </p>
        <span class="product-price" data-price="£50">&pound;50.00</span>
        <a href="#" class="add-quote" id="leaflet-btn">Add to Cart</a>
      </div>
      <!-- product-box -->

      <div class="product-box letterheads" id="letterheads" data-product="letterheads">
        <h1 class="product-title">Letterheads</h1>
        <p>Business Stationery is a key tool for your business, as it will leave a lasting impression of you and your company. A professionally designed stationery set is what will set you apart from the competition giving you the edge to thrive within your
          trade.</p>
        <span class="product-price" data-price="£120">&pound;120.00</span>
        <a href="#" class="add-quote" id="letterhead-btn">Add to Cart</a>
      </div>
      <!-- product-box -->

      <div class="product-box website" id="website" data-product="website">
        <h1 class="product-title">Website</h1>
        <p>We work with businesses of all sizes to create high impact, mobile friendly websites that get results. Whether you're a new business start-up or long established, we can help to build your online presence.</p>
        <span class="product-price" data-price="£500">&pound;500.00</span>
        <a href="#" class="add-quote" id="website-btn">Add to Cart</a>
      </div>
      <!-- product-box -->

    </div>
    <!-- product-box-wrap -->


    <div class="quote-output">
      <h2>Cart</h2>
      <div class="quote-row">
        <a href="" class="remove-item">X</a>
        <p class="cart-product">Business Cards</p><span class="cart-price">&pound;100.00</span>
      </div>

      <div class="quote-row">
        <a href="" class="remove-item">X</a>
        <p class="cart-product">Business Cards</p><span class="cart-price">&pound;100.00</span>
      </div>

      <div class="quote-row">
        <a href="" class="remove-item">X</a>
        <p class="cart-product">Business Cards</p><span class="cart-price">&pound;100.00</span>
      </div>

      <div class="quote-row">
        <a href="" class="remove-item">X</a>
        <p class="cart-product">Business Cards</p><span class="cart-price">&pound;100.00</span>
      </div>

      <div class="quote-row">
        <a href="" class="remove-item">X</a>
        <p class="cart-product">Business Cards</p><span class="cart-price">&pound;100.00</span>
      </div>

      <div class="quote-row">
        <a href="" class="remove-item">X</a>
        <p class="cart-product">Business Cards</p><span class="cart-price">&pound;100.00</span>
      </div>
      <div class="cart-total">
        <p class="cart-total-output"><span>Total:</span> &pound;200.00</p>
      </div>
      <!-- cart-total -->
    </div>
  </div>
  <!-- container -->

  <script src="script.js"></script>
</body>

</html>

7
  • 1
    Sorry, i'm new to this. Commented May 28, 2020 at 11:03
  • 1
    I made you a snippet Commented May 28, 2020 at 11:03
  • 1
    Hi! Welcome to SO! This site is not really a good fit for code reviews or how to's. Instead we're giving specific answers to specific questions. Try to narrow down the problem to a specific piece of code, include that in the question, describe what you think it is supposed to do and what doesn't work, then we'll be glad to help :) Commented May 28, 2020 at 11:04
  • 1
    @JonasWilms At this stage I'd just like to be able to click on the 'add to quote' button and console.log the object/product's properties and values. Line 16 of the JS in the pen is where I'm struggling Commented May 28, 2020 at 11:06
  • 1
    @mplungjan and what's supposed to happen in that case? That's the missing part. Commented May 28, 2020 at 11:08

1 Answer 1

1

I converted your code to jQuery (because you tagged it jQuery when I read the question) and removed the initial product assignment

Vanilla

window.addEventListener("load",function() {
  // Declare global variables
  const productArr = [];

  // Create Product function constructor
  function Product(productTitle, productPrice, cartBtn) {
    this.productTitle = productTitle;
    this.productPrice = productPrice;
    this.cartBtn = cartBtn;
    this.cartBtn.dataset.title = productTitle; // better: a key to an object
    // Event listener for logging the product when clicked
    this.cartBtn.addEventListener('click', function(event) { // this "this" is the product
      event.preventDefault();
      console.log(this.dataset.title); // this this is the button object
    })
  };


  // Seach for all products on the page and convert to objects
  [...document.querySelectorAll('.product-box')].forEach(function(box) {
    const title = box.querySelector('.product-title').textContent;
    const price = box.querySelector('.product-price').textContent;
    const btn = box.querySelector('.add-quote');
    const product = new Product(title, price, btn);
    // add product objects to array
    productArr.push(product);
  });

});
html {
  box-sizing: border-box;
}

*,
*:before,
*:after {
  box-sizing: inherit;
}

:root {
  --turqoise: #00a492;
  --green: #8fb91e;
  --blue: #00a9e2;
  --black: #333333;
}

body {
  font-family: 'Roboto', sans-serif;
}

.container {
  width: 90%;
  max-width: 1400px;
  margin: 0 auto;
  padding-top: 3em;
}

.site-header {}

.product-box-wrap {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
}

.product-box {
  min-width: 300px;
  width: 22%;
  margin: 1em;
  border: solid 4px var(--turqoise);
  padding: 2em 1.5em;
  border-radius: 3px;
  box-shadow: 3px 3px 3px #ccc;
  display: flex;
  flex-direction: column;
  position: relative;
}

.product-box.active {
  background: #e2e2e2;
  border: solid 4px red;
  box-shadow: none;
}

.product-box h1 {
  font-size: 1.75em;
  font-weight: 700;
  color: var(--turqoise);
  margin-bottom: 0.4em;
}

.product-box p {
  font-size: 1.1em;
  font-weight: 300;
  line-height: 1.5em;
  color: var(--black);
  margin-bottom: 1em;
}

.product-price {
  position: absolute;
  padding: 10px;
  left: 0;
  bottom: 0;
  font-weight: 700;
  font-size: 1.2em;
  color: #fff;
  display: block;
  margin-top: 0.5em;
  background: var(--blue);
}

.add-quote {
  position: absolute;
  padding: 10px;
  right: 0;
  bottom: 0;
  font-weight: 700;
  text-transform: uppercase;
  text-decoration: none;
  font-size: 1.2em;
  color: #fff;
  display: block;
  margin-top: 0.5em;
  background: var(--green);
  transition: background .2s ease-in-out;
}

.add-quote:hover {
  background: var(--turqoise);
}

.quote-output {
  margin: 3em 0;
}

.quote-output h2 {
  font-size: 2.7em;
  color: var(--turqoise);
  margin-bottom: 0.5em;
}

.quote-row {
  display: flex;
  padding: 1.5em 0;
  font-size: 1.7em;
  border-bottom: dotted 1px #000;
}

.remove-item {
  margin-right: 1em;
  text-decoration: none;
  font-weight: 700;
  color: red;
}

.cart-product {
  margin: 0 3em;
}

.cart-total {
  margin-top: 2em;
  font-size: 1.7em;
}

.cart-total p span {
  font-weight: 700;
  padding-right: 3em;
}
<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>Product Totter Upperer</title>
  <meta name="viewport" content="width=device-width; initial-scale=1.0">
  <link href="https://fonts.googleapis.com/css2?family=Bebas+Neue&family=Roboto:ital,wght@0,300;0,400;0,700;0,900;1,300;1,400&display=swap" rel="stylesheet">
  <link rel="stylesheet" href="style.css" />
</head>

<body>
  <div class="container">
    <div class="product-box-wrap">

      <div class="product-box active" id="business-cards" data-product="business-cards">
        <h1 class="product-title">Business Cards</h1>
        <p>Business Cards are the most fundamental way to exchange business or personal contact information, therefore the importance of a professionally designed and printed Business Card is greater than ever to secure a long lasting impression of you and
          your company.</p>
        <span class="product-price" data-price="£100">&pound;100.00</span>
        <a href="#" class="add-quote" id="b-card-btn">Add to Cart</a>
      </div>
      <!-- product-box -->

      <div class="product-box lealfet" id="leaflets" data-product="leaflets">
        <h1 class="product-title">Leaflets</h1>
        <p>Printed leaflets are a really effective tool to reach out to potential customers. Whether you're a new business start up or established business, leaflets have a number of purposes when promoting your products/services. </p>
        <span class="product-price" data-price="£50">&pound;50.00</span>
        <a href="#" class="add-quote" id="leaflet-btn">Add to Cart</a>
      </div>
      <!-- product-box -->

      <div class="product-box letterheads" id="letterheads" data-product="letterheads">
        <h1 class="product-title">Letterheads</h1>
        <p>Business Stationery is a key tool for your business, as it will leave a lasting impression of you and your company. A professionally designed stationery set is what will set you apart from the competition giving you the edge to thrive within your
          trade.</p>
        <span class="product-price" data-price="£120">&pound;120.00</span>
        <a href="#" class="add-quote" id="letterhead-btn">Add to Cart</a>
      </div>
      <!-- product-box -->

      <div class="product-box website" id="website" data-product="website">
        <h1 class="product-title">Website</h1>
        <p>We work with businesses of all sizes to create high impact, mobile friendly websites that get results. Whether you're a new business start-up or long established, we can help to build your online presence.</p>
        <span class="product-price" data-price="£500">&pound;500.00</span>
        <a href="#" class="add-quote" id="website-btn">Add to Cart</a>
      </div>
      <!-- product-box -->

    </div>
    <!-- product-box-wrap -->


    <div class="quote-output">
      <h2>Cart</h2>
      <div class="quote-row">
        <a href="" class="remove-item">X</a>
        <p class="cart-product">Business Cards</p><span class="cart-price">&pound;100.00</span>
      </div>

      <div class="quote-row">
        <a href="" class="remove-item">X</a>
        <p class="cart-product">Business Cards</p><span class="cart-price">&pound;100.00</span>
      </div>

      <div class="quote-row">
        <a href="" class="remove-item">X</a>
        <p class="cart-product">Business Cards</p><span class="cart-price">&pound;100.00</span>
      </div>

      <div class="quote-row">
        <a href="" class="remove-item">X</a>
        <p class="cart-product">Business Cards</p><span class="cart-price">&pound;100.00</span>
      </div>

      <div class="quote-row">
        <a href="" class="remove-item">X</a>
        <p class="cart-product">Business Cards</p><span class="cart-price">&pound;100.00</span>
      </div>

      <div class="quote-row">
        <a href="" class="remove-item">X</a>
        <p class="cart-product">Business Cards</p><span class="cart-price">&pound;100.00</span>
      </div>
      <div class="cart-total">
        <p class="cart-total-output"><span>Total:</span> &pound;200.00</p>
      </div>
      <!-- cart-total -->
    </div>
  </div>
  <!-- container -->

  <script src="script.js"></script>
</body>

</html>

Search for all products on the page and convert to objects

would be better the other way around. Have a product catalogue and create the items on the page from that

Vanilla

const products = [{
    "id": "business-cards",
    "title": "Business Cards",
    "description": "Business Cards are the most fundamental way to exchange business or personal contact information, therefore the importance of a professionally designed and printed Business Card is greater than ever to secure a long lasting impression of you and your company.",
    "price": 100
  },
  {
    "id": "leaflets",
    "title": "Leaflets",
    "description": "Printed leaflets are a really effective tool to reach out to potential customers. Whether you're a new business start up or established business, leaflets have a number of purposes when promoting your products/services.",
    "price": 50
  },
  {
    "id": "letterheads",
    "title": "Letterheads",
    "description": "Business Stationery is a key tool for your business, as it will leave a lasting impression of you and your company. A professionally designed stationery set is what will set you apart from the competition giving you the edge to thrive within your trade.",
    "price": 120
  }, {
    "id": "website",
    "title": "Website",
    "description": "We work with businesses of all sizes to create high impact, mobile friendly websites that get results. Whether you're a new business start-up or long established, we can help to build your online presence.",
    "price": 500
  }
]
window.addEventListener("load",function() { 
  const $container = document.getElementById("container");
  products.forEach(function(item,i) {
    $container.innerHTML += 
      `<div class="product-box-wrap">
      <div class="product-box active" id="${item.id}" data-product="${item.id}">
        <h1 class="product-title">${item.title}</h1>
        <p>${item.description}</p>
        <span class="product-price" data-price="${item.price}">&pound;${item.price.toFixed(2)}</span>
        <a href="#" class="add-quote" data-idx="${i}">Add to Cart</a>
      </div>`;
  })
  $container.addEventListener("click",function(e) {
    e.preventDefault();
    const tgt = e.target;
    if (tgt.classList.contains("add-quote")) {
      console.log(products[tgt.dataset.idx])
    }  
  })

});
html {
  box-sizing: border-box;
}

*,
*:before,
*:after {
  box-sizing: inherit;
}

:root {
  --turqoise: #00a492;
  --green: #8fb91e;
  --blue: #00a9e2;
  --black: #333333;
}

body {
  font-family: 'Roboto', sans-serif;
}

.container {
  width: 90%;
  max-width: 1400px;
  margin: 0 auto;
  padding-top: 3em;
}

.site-header {}

.product-box-wrap {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
}

.product-box {
  min-width: 300px;
  width: 22%;
  margin: 1em;
  border: solid 4px var(--turqoise);
  padding: 2em 1.5em;
  border-radius: 3px;
  box-shadow: 3px 3px 3px #ccc;
  display: flex;
  flex-direction: column;
  position: relative;
}

.product-box.active {
  background: #e2e2e2;
  border: solid 4px red;
  box-shadow: none;
}

.product-box h1 {
  font-size: 1.75em;
  font-weight: 700;
  color: var(--turqoise);
  margin-bottom: 0.4em;
}

.product-box p {
  font-size: 1.1em;
  font-weight: 300;
  line-height: 1.5em;
  color: var(--black);
  margin-bottom: 1em;
}

.product-price {
  position: absolute;
  padding: 10px;
  left: 0;
  bottom: 0;
  font-weight: 700;
  font-size: 1.2em;
  color: #fff;
  display: block;
  margin-top: 0.5em;
  background: var(--blue);
}

.add-quote {
  position: absolute;
  padding: 10px;
  right: 0;
  bottom: 0;
  font-weight: 700;
  text-transform: uppercase;
  text-decoration: none;
  font-size: 1.2em;
  color: #fff;
  display: block;
  margin-top: 0.5em;
  background: var(--green);
  transition: background .2s ease-in-out;
}

.add-quote:hover {
  background: var(--turqoise);
}

.quote-output {
  margin: 3em 0;
}

.quote-output h2 {
  font-size: 2.7em;
  color: var(--turqoise);
  margin-bottom: 0.5em;
}

.quote-row {
  display: flex;
  padding: 1.5em 0;
  font-size: 1.7em;
  border-bottom: dotted 1px #000;
}

.remove-item {
  margin-right: 1em;
  text-decoration: none;
  font-weight: 700;
  color: red;
}

.cart-product {
  margin: 0 3em;
}

.cart-total {
  margin-top: 2em;
  font-size: 1.7em;
}

.cart-total p span {
  font-weight: 700;
  padding-right: 3em;
}
<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>Product Totter Upperer</title>
  <meta name="viewport" content="width=device-width; initial-scale=1.0">
  <link href="https://fonts.googleapis.com/css2?family=Bebas+Neue&family=Roboto:ital,wght@0,300;0,400;0,700;0,900;1,300;1,400&display=swap" rel="stylesheet">
  <link rel="stylesheet" href="style.css" />
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>

<body>
  <div class="container" id="container">
  </div>
  <div id="cart">

    <div class="quote-output">
      <h2>Cart</h2>
      <div class="quote-row">
        <a href="" class="remove-item">X</a>
        <p class="cart-product">Business Cards</p><span class="cart-price">&pound;100.00</span>
      </div>

      <div class="quote-row">
        <a href="" class="remove-item">X</a>
        <p class="cart-product">Business Cards</p><span class="cart-price">&pound;100.00</span>
      </div>

      <div class="quote-row">
        <a href="" class="remove-item">X</a>
        <p class="cart-product">Business Cards</p><span class="cart-price">&pound;100.00</span>
      </div>

      <div class="quote-row">
        <a href="" class="remove-item">X</a>
        <p class="cart-product">Business Cards</p><span class="cart-price">&pound;100.00</span>
      </div>

      <div class="quote-row">
        <a href="" class="remove-item">X</a>
        <p class="cart-product">Business Cards</p><span class="cart-price">&pound;100.00</span>
      </div>

      <div class="quote-row">
        <a href="" class="remove-item">X</a>
        <p class="cart-product">Business Cards</p><span class="cart-price">&pound;100.00</span>
      </div>
      <div class="cart-total">
        <p class="cart-total-output"><span>Total:</span> &pound;200.00</p>
      </div>
      <!-- cart-total -->
    </div>
  </div>
  <!-- container -->


</body>

</html>

jQuery

const products = [{
    "id": "business-cards",
    "title": "Business Cards",
    "description": "Business Cards are the most fundamental way to exchange business or personal contact information, therefore the importance of a professionally designed and printed Business Card is greater than ever to secure a long lasting impression of you and your company.",
    "price": 100
  },
  {
    "id": "leaflets",
    "title": "Leaflets",
    "description": "Printed leaflets are a really effective tool to reach out to potential customers. Whether you're a new business start up or established business, leaflets have a number of purposes when promoting your products/services.",
    "price": 50
  },
  {
    "id": "letterheads",
    "title": "Letterheads",
    "description": "Business Stationery is a key tool for your business, as it will leave a lasting impression of you and your company. A professionally designed stationery set is what will set you apart from the competition giving you the edge to thrive within your trade.",
    "price": 120
  }, {
    "id": "website",
    "title": "Website",
    "description": "We work with businesses of all sizes to create high impact, mobile friendly websites that get results. Whether you're a new business start-up or long established, we can help to build your online presence.",
    "price": 500
  }
]
$(function() {
  const $container = $("#container");
  $.each(products, function(i,item) {

    $container.append(
      `<div class="product-box-wrap">
      <div class="product-box active" id="${item.id}" data-product="${item.id}">
        <h1 class="product-title">${item.title}</h1>
        <p>${item.description}</p>
        <span class="product-price" data-price="${item.price}">&pound;${item.price.toFixed(2)}</span>
        <a href="#" class="add-quote" data-idx="${i}">Add to Cart</a>
      </div>`)

  })
  $container.on("click",".add-quote",function(e) {
    e.preventDefault();
    console.log(products[$(this).data("idx")])
  })

});
html {
  box-sizing: border-box;
}

*,
*:before,
*:after {
  box-sizing: inherit;
}

:root {
  --turqoise: #00a492;
  --green: #8fb91e;
  --blue: #00a9e2;
  --black: #333333;
}

body {
  font-family: 'Roboto', sans-serif;
}

.container {
  width: 90%;
  max-width: 1400px;
  margin: 0 auto;
  padding-top: 3em;
}

.site-header {}

.product-box-wrap {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
}

.product-box {
  min-width: 300px;
  width: 22%;
  margin: 1em;
  border: solid 4px var(--turqoise);
  padding: 2em 1.5em;
  border-radius: 3px;
  box-shadow: 3px 3px 3px #ccc;
  display: flex;
  flex-direction: column;
  position: relative;
}

.product-box.active {
  background: #e2e2e2;
  border: solid 4px red;
  box-shadow: none;
}

.product-box h1 {
  font-size: 1.75em;
  font-weight: 700;
  color: var(--turqoise);
  margin-bottom: 0.4em;
}

.product-box p {
  font-size: 1.1em;
  font-weight: 300;
  line-height: 1.5em;
  color: var(--black);
  margin-bottom: 1em;
}

.product-price {
  position: absolute;
  padding: 10px;
  left: 0;
  bottom: 0;
  font-weight: 700;
  font-size: 1.2em;
  color: #fff;
  display: block;
  margin-top: 0.5em;
  background: var(--blue);
}

.add-quote {
  position: absolute;
  padding: 10px;
  right: 0;
  bottom: 0;
  font-weight: 700;
  text-transform: uppercase;
  text-decoration: none;
  font-size: 1.2em;
  color: #fff;
  display: block;
  margin-top: 0.5em;
  background: var(--green);
  transition: background .2s ease-in-out;
}

.add-quote:hover {
  background: var(--turqoise);
}

.quote-output {
  margin: 3em 0;
}

.quote-output h2 {
  font-size: 2.7em;
  color: var(--turqoise);
  margin-bottom: 0.5em;
}

.quote-row {
  display: flex;
  padding: 1.5em 0;
  font-size: 1.7em;
  border-bottom: dotted 1px #000;
}

.remove-item {
  margin-right: 1em;
  text-decoration: none;
  font-weight: 700;
  color: red;
}

.cart-product {
  margin: 0 3em;
}

.cart-total {
  margin-top: 2em;
  font-size: 1.7em;
}

.cart-total p span {
  font-weight: 700;
  padding-right: 3em;
}
<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>Product Totter Upperer</title>
  <meta name="viewport" content="width=device-width; initial-scale=1.0">
  <link href="https://fonts.googleapis.com/css2?family=Bebas+Neue&family=Roboto:ital,wght@0,300;0,400;0,700;0,900;1,300;1,400&display=swap" rel="stylesheet">
  <link rel="stylesheet" href="style.css" />
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>

<body>
  <div class="container" id="container">
  </div>
  <div id="cart">

    <div class="quote-output">
      <h2>Cart</h2>
      <div class="quote-row">
        <a href="" class="remove-item">X</a>
        <p class="cart-product">Business Cards</p><span class="cart-price">&pound;100.00</span>
      </div>

      <div class="quote-row">
        <a href="" class="remove-item">X</a>
        <p class="cart-product">Business Cards</p><span class="cart-price">&pound;100.00</span>
      </div>

      <div class="quote-row">
        <a href="" class="remove-item">X</a>
        <p class="cart-product">Business Cards</p><span class="cart-price">&pound;100.00</span>
      </div>

      <div class="quote-row">
        <a href="" class="remove-item">X</a>
        <p class="cart-product">Business Cards</p><span class="cart-price">&pound;100.00</span>
      </div>

      <div class="quote-row">
        <a href="" class="remove-item">X</a>
        <p class="cart-product">Business Cards</p><span class="cart-price">&pound;100.00</span>
      </div>

      <div class="quote-row">
        <a href="" class="remove-item">X</a>
        <p class="cart-product">Business Cards</p><span class="cart-price">&pound;100.00</span>
      </div>
      <div class="cart-total">
        <p class="cart-total-output"><span>Total:</span> &pound;200.00</p>
      </div>
      <!-- cart-total -->
    </div>
  </div>
  <!-- container -->


</body>

</html>

Sign up to request clarification or add additional context in comments.

5 Comments

Thank you for your help (and patience) with this. I was hoping to be able to do this in vanilla JS. Is it a lot more complex doing it this way?
Please see update. And PLEASE DO NOT TAG jQuery if you do not want jQuery. I have now spent time doing it in jQuery when I could just as easily done it in vanilla
Ok, I added the vanilla version of the second example
Thank you very much for this. :-) I didn't realise i'd tagged jquery so apologies for that
Ok, I converted the first example to vanilla too

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.