Nah ini problem UI yang real banget β€” dan kalau gak diberesin, UX kamu bakal jelek walaupun engine-nya bagus.

πŸ‘‰ Masalah kamu:

  • video 9:16 (vertical)
  • modal fullscreen β†’ jadi kepanjangan
  • tombol close ketutup / susah diklik ❌

🎯 SOLUSI YANG BENAR

πŸ‘‰ Jangan biarkan video β€œngatur layout”
πŸ‘‰ Kita yang kontrol container-nya


⚑ FIX 1 β€” Batasi tinggi player (WAJIB)

Di .player-content, tambahin:

.player-content {
  background: #181818;
  width: 100%;
  max-width: 1000px;
  border-radius: 12px;
  padding: 16px;
  position: relative;

  max-height: 90vh;   /* πŸ”₯ penting */
  overflow: auto;     /* πŸ”₯ biar scroll kalau tinggi */
}

⚑ FIX 2 β€” Paksa video supaya gak overflow

Tambahin ini:

.player-content video {
  width: 100%;
  max-height: 80vh;   /* πŸ”₯ ini kunci */
  object-fit: contain;
}

πŸ‘‰ hasil:

  • video tinggi β†’ di-scale
  • tidak keluar layar
  • tetap proporsional

⚑ FIX 3 β€” Close button harus selalu terlihat

Upgrade tombol close:

.player-close {
  position: fixed;   /* πŸ”₯ bukan absolute */
  top: 20px;
  right: 20px;
  font-size: 28px;
  cursor: pointer;
  z-index: 1000;
  background: rgba(0,0,0,0.6);
  padding: 5px 10px;
  border-radius: 6px;
}

πŸ‘‰ sekarang:

  • selalu di atas
  • gak ketutup video

⚑ FIX 4 (OPSIONAL tapi bagus) β€” Center vertical video

Tambahin wrapper:

Di app.js: FULL

const gallery = document.getElementById("gallery");
const modal = document.getElementById("playerModal");
const player = document.getElementById("player");

let currentHls = null;

fetch("data.json")
  .then(res => res.json())
  .then(data => {
    data.forEach(item => {
      const div = document.createElement("div");
      div.className = "card";

      div.innerHTML = `
        <img src="${item.thumb}" alt="${item.title}">
        <p>${item.title}</p>
      `;

      div.onclick = () => openPlayer(item);
      gallery.appendChild(div);
    });
  })
  .catch(err => {
    console.error("Gagal load data.json:", err);
  });

function openPlayer(item) {
  modal.classList.remove("hidden");

  // bersihkan player sebelumnya
  if (currentHls) {
    currentHls.destroy();
    currentHls = null;
  }

  player.innerHTML = "";

  if (item.type === "mp4") {
    player.innerHTML = `
      <div class="video-wrapper">
        <video controls autoplay playsinline>
          <source src="${item.src}" type="video/mp4">
        </video>
      </div>
    `;
  }

  else if (item.type === "image") {
    player.innerHTML = `
      <div class="image-wrapper">
        <img src="${item.src}" alt="${item.title}">
      </div>
    `;
  }

  else if (item.type === "iframe") {
    player.innerHTML = `
      <div class="iframe-wrapper">
        <iframe 
          src="${item.src}" 
          allowfullscreen 
          loading="lazy"
          referrerpolicy="strict-origin-when-cross-origin">
        </iframe>
      </div>
    `;
  }

  else if (item.type === "m3u8") {
    player.innerHTML = `
      <div class="video-wrapper">
        <video id="hlsPlayer" controls autoplay playsinline></video>
      </div>
    `;

    const video = document.getElementById("hlsPlayer");

    if (window.Hls && Hls.isSupported()) {
      currentHls = new Hls();
      currentHls.loadSource(item.src);
      currentHls.attachMedia(video);
    } else if (video.canPlayType("application/vnd.apple.mpegurl")) {
      video.src = item.src;
    } else {
      player.innerHTML = `<p>Browser tidak mendukung HLS.</p>`;
    }
  }

  else {
    player.innerHTML = `<p>Tipe media tidak dikenali.</p>`;
  }
}

function closePlayer() {
  modal.classList.add("hidden");

  if (currentHls) {
    currentHls.destroy();
    currentHls = null;
  }

  player.innerHTML = "";
}

CSS: FULL

/* ===== BASE ===== */
body {
  background: #111;
  color: white;
  font-family: Arial, sans-serif;
  margin: 0;
  padding: 20px;
}

h1 {
  margin: 0 0 20px;
}

/* ===== GALLERY ===== */
#gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 16px;
}

.card {
  background: #1b1b1b;
  border-radius: 10px;
  overflow: hidden;
  cursor: pointer;
  transition: transform 0.2s ease;
}

.card:hover {
  transform: translateY(-4px);
}

.card img {
  width: 100%;
  height: 140px;
  object-fit: cover;
  display: block;
}

.card p {
  margin: 0;
  padding: 10px;
  font-size: 14px;
}

/* ===== MODAL ===== */
#playerModal {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.9);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  z-index: 999;
}

.hidden {
  display: none !important;
}

/* ===== PLAYER CONTAINER ===== */
.player-content {
  background: #181818;
  width: 100%;
  max-width: 1000px;
  max-height: 90vh;
  border-radius: 12px;
  padding: 16px;
  position: relative;
  overflow: auto;
}

/* ===== CLOSE BUTTON ===== */
.player-close {
  position: fixed;
  top: 20px;
  right: 20px;
  font-size: 28px;
  cursor: pointer;
  z-index: 1000;
  background: rgba(0, 0, 0, 0.6);
  padding: 6px 12px;
  border-radius: 8px;
}

/* ===== WRAPPERS ===== */
.video-wrapper,
.image-wrapper,
.iframe-wrapper {
  display: flex;
  justify-content: center;
  align-items: center;
}

/* ===== VIDEO ===== */
.video-wrapper video {
  width: auto;
  max-width: 100%;
  max-height: 80vh;
  object-fit: contain;
}

/* ===== IMAGE ===== */
.image-wrapper img {
  max-width: 100%;
  max-height: 80vh;
  object-fit: contain;
}

/* ===== IFRAME ===== */
.iframe-wrapper iframe {
  width: 100%;
  height: 80vh;
  border: 0;
}

πŸ‘‰ ini bikin:

  • video 9:16 jadi center (kayak TikTok viewer)

πŸ’¬ Real talk (ini insight penting)

Platform besar juga handle ini:

  • TikTok β†’ vertical dominant
  • YouTube β†’ horizontal dominant

πŸ‘‰ kamu sekarang sudah masuk problem:

β€œmulti aspect ratio UI”

Dan kamu handle dengan benar πŸ‘


πŸš€ Next upgrade (kalau mau makin enak)

Kalau kamu lanjut, ini yang keren:

πŸ”₯ Detect aspect ratio otomatis

  • kalau portrait β†’ center
  • kalau landscape β†’ full width

πŸ”₯ Auto label

  • β€œVERTICAL”
  • β€œHLS”
  • β€œMP4”

πŸ‘‰ Sekarang

Coba apply:

  • max-height
  • object-fit
  • fixed close button

Kalau sudah enak:
πŸ‘‰ bilang "UI nyaman"

Kalau masih ganggu:
πŸ‘‰ kirim screenshot lagi

Kita rapihin sampai feel-nya kayak platform beneran πŸ”₯