JSFiddle - React, Tailwind, and code Playground

HTML

<h1 style="text-align: center;">JavaScript 系列五:第7課 ── 學會 AJAX 與 data attribute 的結合</h1>

<button id="load">Load Products</button>
<hr>
<ul></ul>

<!-- 彈跳視窗:商品詳情 -->
<div class="modal" id="detail-modal">
  <div class="detail-modal-div">
    <div class="pic">
      <img src="" alt="">
    </div>

    <div class="txt">
      <div class="name">
        <span class="title">名稱:</span>
        <span class="product-data"></span>
      </div>
      <div class="category">
        <span class="title">分類:</span>
        <span class="product-data"></span>
      </div>
      <div class="description">
        <span class="title">描述:</span>
        <span class="product-data"></span>
      </div>

      <div class="price">
        <span class="title">價格:</span>
        <span class="product-data"></span>
      </div>

      <div class="block-btn-group">
        <button class="block-btn btn-close" onclick="closeWindow()">關閉</button>
      </div>
    </div>

    <button class="x-btn" onclick="closeWindow()">X</button>
  </div>
</div>

CSS

* {
  padding: 0;
  margin: 0;
  list-style-type: none;
}

ul {
  display: flex;
  flex-wrap: wrap;
}

ul li {
  width: 25%;
  padding: 50px;
  box-sizing: border-box;
}

ul li .img-box {
  width: 100%;
  height: 200px;
}

ul li .img-box img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  transition: 0.5s;
}

ul li .img-box img.active {
  transform: scale(1.25);
}

ul li .txt-box {
  margin-top: 20px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  align-items: center;
  height: 200px;
}

ul li .txt-box span {
  text-align: center;
  line-height: 1.5;
  font-size: 18px;
}

ul li .txt-box button {
  font-size: 16px;
  display: inline-block;
  padding: 10px 20px;
  color: #fff;
  background-color: rgba(100, 100, 255, 1);
  border: none;
  border-radius: 10px;
  cursor: pointer;
}

#load {
  display: block;
  padding: 5px 10px;
  margin: 10px auto;
  cursor: pointer;
}

/* modal */
.modal {
  position: fixed;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  background-color: rgba(100, 100, 100, 0.7);
  opacity: 0;
  z-index: -1;
  transition: 0.5s;
}

.modal.active {
  opacity: 1;
  z-index: 1;
}

.modal .detail-modal-div {
  width: 1200px;
  position: absolute;
  padding: 20px;
  background-color: #ccc;
  top: 50%;
  left: 50%;
  transform: translateX(-50%) translateY(-50%);
  border-radius: 10px;
  display: flex;
  align-items: center;
}

.modal .detail-modal-div .pic {
  margin-right: 20px;
}

.modal .detail-modal-div .pic img {
  width: 250px;
  object-fit: contain;
}

.modal .detail-modal-div .txt div+div {
  margin-top: 20px;
}

.modal .detail-modal-div .txt .title {
  font-size: 18px;
  font-weight: 900;
  line-height: 1.5;
}

.modal .detail-modal-div .txt .product-data {
  line-height: 1.5;
}

.modal .detail-modal-div .block-btn-group {
  width: 100%;
}

.block-btn {
  padding: 5px 10px;
  box-sizing: border-box;
  width: 100%;
  line-height: 30px;
  font-size: 16px;
  font-weight: 900;
  border-radius: 10px;
 ...

JavaScript

let loadBtn = document.querySelector("#load");
let ul = document.querySelector("ul");

load.onclick = function loading() {
  fetch("https://fakestoreapi.com/products")
    .then((res) => res.json())
    .then((json) => {
      for (const product of json) {
        let list = document.createElement("li");

        let imgBox = document.createElement("div");
        imgBox.classList.add("img-box");
        let txtBox = document.createElement("div");
        txtBox.classList.add("txt-box");

        let img = document.createElement("img");
        img.src = product.image;

        let productNameSpan = document.createElement("span");
        productNameSpan.textContent = product.title;

        let detailBtn = document.createElement("button");
        detailBtn.textContent = "Details";
        detailBtn.onclick = function showDetails() {
          let list = event.target.closest("li");
          list.dataset.title = product.title;
          list.dataset.category = product.category;
          list.dataset.description = product.description;
          list.dataset.image = product.image;
          list.dataset.price = product.price;
          detailModal();
        };

        let deleteBtn = document.createElement("button");
        deleteBtn.textContent = "Delete";
        deleteBtn.onclick = function deleteProduct() {
          let id = product.id;
          let idList = event.target.closest("li");
          fetch("https://fakestoreapi.com/products/" + id, {
              method: "DELETE"
            })
            .then((res) => res.json())
            .then((json) => {
              idList.remove();
            })
            .catch((error) => {
              alert("請稍後再試");
            });
        };

        ul.append(list);
        list.append(imgBox);
        list.append(txtBox);

        imgBox.append(img);

        txtBox.append(productNameSpan);
        txtBox.append(detailBtn);
        txtBox.append(deleteBtn);

       ...