<div class="custom-video-player">
<video id="main-video" src="https://codeshack.io/web/example.mp4" playsinline></video>
<div class="player-controls">
<button id="play-pause-btn" aria-label="Play">
<svg class="play-icon" viewBox="0 0 24 24" width="24" height="24" fill="currentColor">
<polygon points="5 3 19 12 5 21 5 3"></polygon>
</svg>
</button>
<div class="timeline-container" id="timeline">
<div class="timeline-progress" id="progress"></div>
<div class="chapter-marker" style="left: 25%" title="Intro"></div>
<div class="chapter-marker" style="left: 50%" title="Main Feature"></div>
<div class="chapter-marker" style="left: 80%" title="Conclusion"></div>
</div>
<span class="time-display" id="time-display">0:00</span>
</div>
</div>
*, *::before, *::after {
box-sizing: border-box;
}
body {
font-family: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
background: #f3f4f6;
display: flex;
justify-content: center;
padding: 40px;
margin: 0;
min-height: 100vh;
align-items: center;
}
.custom-video-player {
position: relative;
width: 100%;
max-width: 800px;
border-radius: 16px;
overflow: hidden;
background: #000000;
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1);
}
#main-video {
width: 100%;
display: block;
}
.player-controls {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background: linear-gradient(to top, rgba(0, 0, 0, 0.8), transparent);
padding: 20px;
display: flex;
align-items: center;
gap: 16px;
opacity: 0;
transition: opacity 0.3s;
}
.custom-video-player:hover .player-controls {
opacity: 1;
}
#play-pause-btn {
background: none;
border: none;
color: #ffffff;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
padding: 0;
transition: color 0.2s;
}
#play-pause-btn:hover {
color: #3b82f6;
}
.timeline-container {
flex-grow: 1;
height: 6px;
background: rgba(255, 255, 255, 0.3);
border-radius: 3px;
position: relative;
cursor: pointer;
}
.timeline-progress {
position: absolute;
left: 0;
top: 0;
bottom: 0;
background: #3b82f6;
border-radius: 3px;
width: 0%;
pointer-events: none;
}
.chapter-marker {
position: absolute;
top: -3px;
width: 4px;
height: 12px;
background: #ffffff;
border-radius: 2px;
transition: transform 0.2s;
}
.chapter-marker:hover {
transform: scale(1.5);
}
.chapter-marker:hover::after {
content: attr(title);
position: absolute;
top: -30px;
left: 50%;
transform: translateX(-50%) scale(0.66);
background: #111827;
color: #ffffff;
padding: 4px 8px;
border-radius: 4px;
font-size: 0.75rem;
white-space: nowrap;
}
.time-display {
color: #ffffff;
font-size: 0.875rem;
font-variant-numeric: tabular-nums;
}
const video = document.getElementById("main-video");
const playBtn = document.getElementById("play-pause-btn");
const timeline = document.getElementById("timeline");
const progress = document.getElementById("progress");
const timeDisplay = document.getElementById("time-display");
playBtn.addEventListener("click", () => {
if (video.paused) {
video.play();
playBtn.innerHTML = `<svg viewBox="0 0 24 24" width="24" height="24" fill="currentColor"><rect x="6" y="4" width="4" height="16"></rect><rect x="14" y="4" width="4" height="16"></rect></svg>`;
} else {
video.pause();
playBtn.innerHTML = `<svg viewBox="0 0 24 24" width="24" height="24" fill="currentColor"><polygon points="5 3 19 12 5 21 5 3"></polygon></svg>`;
}
});
video.addEventListener("timeupdate", () => {
const pct = (video.currentTime / video.duration) * 100;
progress.style.width = pct + "%";
const mins = Math.floor(video.currentTime / 60);
const secs = Math.floor(video.currentTime % 60).toString().padStart(2, "0");
timeDisplay.textContent = mins + ":" + secs;
});
timeline.addEventListener("click", (e) => {
const rect = timeline.getBoundingClientRect();
const clickPos = (e.clientX - rect.left) / rect.width;
video.currentTime = clickPos * video.duration;
});