Vimeo Pause/Play Toggle

by Michael Mandarino

HTML

<button class="pause-button" id="pauseBtn" type="button" aria-pressed="true">Pause</button>

		<div class="vimeo-container">
			<div class="poster-overlay is-visible" id="posterOverlay">
				<img id="posterImg" alt="Video loading" />
			</div>

			<iframe
				id="vimeoPlayer"
        src="https://player.vimeo.com/video/347119375?api=1&background=1&autoplay=1&loop=1"
        allowfullscreen="allowfullscreen"
				allow="autoplay; fullscreen; picture-in-picture"
				frameborder="0"
				title="Vimeo video"
			></iframe>
		</div>

		<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
		<script src="https://player.vimeo.com/api/player.js"></script>

CSS

body {
				margin: 0;
			}

			.vimeo-container {
				padding: 0;
				width: 100%;
				height: 100vh;
				overflow: hidden;
				position: relative;
			}

			.pause-button {
				position: fixed;
				top: 12px;
				left: 12px;
				z-index: 10;
			}

			/* Poster shown while the Vimeo iframe loads. */
			.poster-overlay {
				position: absolute;
				inset: 0;
				z-index: 2;
				background: #000;
				display: none;
				pointer-events: none;
			}

			.poster-overlay.is-visible {
				display: block;
			}

			.poster-overlay img {
				width: 100%;
				height: 100%;
				object-fit: cover;
				display: block;
			}

			iframe {
				box-sizing: border-box;
				width: 177.77777778vh;
				height: 56.25vw;
				min-width: 100%;
				min-height: 100%;
				position: absolute;
				top: 50%;
				left: 50%;
				transform: translate(-50%, -50%);
			}

JavaScript

// Wait for the DOM to be ready, then wire up the Vimeo player.
			$(function () {
				"use strict";

				// Grab elements.
				const iframeEl = document.getElementById("vimeoPlayer");
				const $toggleBtn = $("#pauseBtn");
				const $posterOverlay = $("#posterOverlay");
				const $posterImg = $("#posterImg");

				// Wrap the existing iframe with the Vimeo Player SDK.
				const player = new Vimeo.Player(iframeEl);

				// Local fallback state (used only if getPaused() fails).
				let lastKnownPaused = false;

				// Update the button UI to match player state.
				function renderButton(paused) {
					lastKnownPaused = paused;
					$toggleBtn.text(paused ? "Play" : "Pause");

					// For toggle buttons, aria-pressed should reflect the active state.
					// Here we treat "pressed" as "playing".
					$toggleBtn.attr("aria-pressed", paused ? "false" : "true");
				}

				// Sync initial label once the player is ready.
				function syncButtonWithPlayer() {
					return player
						.getPaused()
						.then(renderButton)
						.catch(function () {
							// If we can't read state, default to showing "Pause".
							renderButton(false);
						});
				}

				// Show a poster thumbnail while the iframe/player is loading.
				// We fetch a thumbnail from Vimeo's oEmbed endpoint using the video id.
				(function initPoster() {
					const src = String($(iframeEl).attr("src") || "");
					const match = src.match(/\/video\/(\d+)/);
					const videoId = match ? match[1] : null;

					if (!videoId) {
						// Can't determine the video id; keep the black overlay as a simple fallback.
						$posterOverlay.addClass("is-visible");
						return;
					}

					const oEmbedUrl = "https://vimeo.com/api/oembed.json";
					const videoUrl = "https://vimeo.com/" + videoId;

					$.getJSON(oEmbedUrl, { url: videoUrl })
						.done(function (data) {
							if (data && data.thumbnail_url) {
								$posterImg.attr("src",...