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 π₯