Last active
February 2, 2026 16:09
-
-
Save andrewinsidelazarev/70f581460419813773aeb848f4ad8c62 to your computer and use it in GitHub Desktop.
Shortcode for Youtube video
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| function youtube_embed_shortcode($atts) { | |
| $atts = shortcode_atts(array( | |
| 'id' => '', | |
| 'sd' => 'false' // поддержка sd="true" | |
| ), $atts); | |
| if (empty($atts['id'])) return ''; | |
| $videoId = esc_attr($atts['id']); | |
| $containerId = 'yt-container-' . $videoId; | |
| $playerId = 'yt-player-' . $videoId; | |
| $fsBtnId = 'yt-fs-btn-' . $videoId; | |
| // Выбор миниатюры: WebP (как в оригинале) | |
| $thumbFile = ($atts['sd'] === 'true') ? 'sddefault.webp' : 'maxresdefault.webp'; | |
| $thumbUrl = 'https://i.ytimg.com/vi_webp/' . $videoId . '/' . $thumbFile; | |
| ob_start(); | |
| ?> | |
| <div id="<?= $containerId ?>" | |
| class="yt-custom-wrapper" | |
| tabindex="0" | |
| onclick="this.focus()"> | |
| <img src="<?= esc_url($thumbUrl) ?>" | |
| class="yt-thumb" | |
| alt="Video Thumbnail" | |
| onclick="ytInitPlayer('<?= $videoId ?>')"> | |
| <div class="yt-play-btn" onclick="ytInitPlayer('<?= $videoId ?>')"> | |
| <svg width="68" height="48" viewBox="0 0 68 48"> | |
| <path d="M66.52 7.68C65.76 5.23 63.97 3.44 61.52 2.68C57.68 1.48 34 1.48 34 1.48S10.32 1.48 6.48 2.68C4.03 3.44 2.24 5.23 1.48 7.68 0.28 11.52 0.28 24 0.28 24s0.28 12.48 1.48 16.32c.76 2.45 2.55 4.24 5 5 3.84 1.2 27.52 1.2 27.52 1.2s23.68 0 27.52-1.2c2.45-.76 4.24-2.55 5-5 1.2-3.84 1.2-16.32 1.2-16.32s0-12.48-1.2-16.32z" fill="red"/> | |
| <path d="M45 24L27 14V34L45 24Z" fill="white"/> | |
| </svg> | |
| </div> | |
| <div id="<?= $playerId ?>" class="yt-player-placeholder"></div> | |
| <button id="<?= $fsBtnId ?>" | |
| type="button" | |
| class="yt-fs-btn" | |
| tabindex="-1" | |
| onmousedown="event.preventDefault()" | |
| onclick="ytToggleFS('<?= $containerId ?>')"> | |
| <svg class="icon-enter" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"> | |
| <path d="M15 3h6v6M9 21H3v-6M21 15v6h-6M3 9V3h6"/> | |
| </svg> | |
| <svg class="icon-exit" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" style="display:none;"> | |
| <path d="M8 3v5H3M16 3v5h5M8 21v-5H3M16 21v-5h5"/> | |
| </svg> | |
| </button> | |
| </div> | |
| <?php | |
| static $js_added = false; | |
| if (!$js_added) : | |
| $js_added = true; | |
| ?> | |
| <style> | |
| .yt-custom-wrapper { | |
| position: relative; | |
| width: 100%; | |
| padding-top: 56.25%; | |
| background: #000; | |
| overflow: hidden; | |
| outline: none; | |
| } | |
| .yt-custom-wrapper img.yt-thumb { | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| bottom: 0; /* Страховка */ | |
| object-fit: cover; | |
| display: block; | |
| cursor: pointer; | |
| z-index: 10; | |
| margin: 0; /* Убираем возможные отступы темы */ | |
| } | |
| .yt-play-btn { | |
| position: absolute; | |
| top: 50%; | |
| left: 50%; | |
| transform: translate(-50%,-50%); | |
| cursor: pointer; | |
| z-index: 11; | |
| } | |
| .yt-player-placeholder { | |
| position: absolute; | |
| inset: 0; | |
| width: 100%; | |
| height: 100%; | |
| display: none; | |
| z-index: 5; | |
| } | |
| .yt-fs-btn { | |
| position: absolute; | |
| bottom: 10px; | |
| right: 15px; | |
| width: 35px; | |
| height: 35px; | |
| display: none; | |
| align-items: center; | |
| justify-content: center; | |
| padding: 0; | |
| border: none; | |
| border-radius: 0; | |
| background: rgba(0,0,0,0.6); | |
| cursor: pointer; | |
| z-index: 20; | |
| transition: opacity 0.3s; | |
| } | |
| </style> | |
| <script> | |
| var ytApiReady = false; | |
| var ytPlayers = {}; | |
| var ytQueue = []; | |
| var ytFsTimer = null; | |
| if (!window.YT_API_LOADING) { | |
| window.YT_API_LOADING = true; | |
| var tag = document.createElement('script'); | |
| tag.src = 'https://www.youtube.com/iframe_api'; | |
| document.head.appendChild(tag); | |
| } | |
| function onYouTubeIframeAPIReady() { | |
| ytApiReady = true; | |
| ytQueue.forEach(id => ytCreatePlayer(id)); | |
| ytQueue = []; | |
| } | |
| function ytInitPlayer(videoId) { | |
| if (!ytApiReady) { | |
| ytQueue.push(videoId); | |
| return; | |
| } | |
| ytCreatePlayer(videoId); | |
| } | |
| function ytCreatePlayer(videoId) { | |
| if (ytPlayers[videoId]) return; | |
| var wrapper = document.getElementById('yt-container-' + videoId); | |
| var holder = document.getElementById('yt-player-' + videoId); | |
| var fsBtn = document.getElementById('yt-fs-btn-' + videoId); | |
| // Безопасное удаление (вместо ?.) | |
| var thumb = wrapper.querySelector('.yt-thumb'); | |
| if (thumb) thumb.remove(); | |
| var playBtn = wrapper.querySelector('.yt-play-btn'); | |
| if (playBtn) playBtn.remove(); | |
| holder.style.display = 'block'; | |
| fsBtn.style.display = 'flex'; | |
| ytPlayers[videoId] = new YT.Player(holder, { | |
| videoId: videoId, | |
| playerVars: { autoplay: 1, rel: 0 } | |
| }); | |
| wrapper.focus(); | |
| if (!wrapper.dataset.fsListener) { | |
| wrapper.dataset.fsListener = "1"; | |
| wrapper.addEventListener("mousemove", function() { | |
| fsBtn.style.opacity = "1"; | |
| fsBtn.style.cursor = "pointer"; | |
| if (ytFsTimer) clearTimeout(ytFsTimer); | |
| if (document.fullscreenElement) { | |
| ytFsTimer = setTimeout(function() { | |
| fsBtn.style.opacity = "0"; | |
| fsBtn.style.cursor = "none"; | |
| }, 3000); | |
| } | |
| }); | |
| } | |
| } | |
| function ytToggleFS(containerId) { | |
| var el = document.getElementById(containerId); | |
| if (!document.fullscreenElement) { | |
| if(el.requestFullscreen) el.requestFullscreen(); | |
| else if(el.webkitRequestFullscreen) el.webkitRequestFullscreen(); | |
| } else { | |
| if(document.exitFullscreen) document.exitFullscreen(); | |
| else if(document.webkitExitFullscreen) document.webkitExitFullscreen(); | |
| } | |
| setTimeout(() => el.focus(), 50); | |
| } | |
| document.addEventListener("fullscreenchange", function() { | |
| var fsEl = document.fullscreenElement; | |
| document.querySelectorAll(".yt-custom-wrapper .icon-exit").forEach(el => el.style.display = 'none'); | |
| document.querySelectorAll(".yt-custom-wrapper .icon-enter").forEach(el => el.style.display = 'block'); | |
| if (fsEl && fsEl.classList.contains("yt-custom-wrapper")) { | |
| var btn = fsEl.querySelector(".yt-fs-btn"); | |
| if (btn) { | |
| btn.querySelector(".icon-enter").style.display = 'none'; | |
| btn.querySelector(".icon-exit").style.display = 'block'; | |
| } | |
| fsEl.focus(); | |
| } | |
| }); | |
| document.addEventListener('keydown', function(e) { | |
| if (e.code !== 'Space' && e.keyCode !== 32) return; | |
| var el = document.activeElement; | |
| if (!el || !el.classList.contains('yt-custom-wrapper')) return; | |
| e.preventDefault(); | |
| var videoId = el.id.replace('yt-container-', ''); | |
| var player = ytPlayers[videoId]; | |
| if (!player || typeof player.getPlayerState !== 'function') return; | |
| var state = player.getPlayerState(); | |
| (state === YT.PlayerState.PLAYING) ? player.pauseVideo() : player.playVideo(); | |
| }); | |
| </script> | |
| <?php | |
| endif; | |
| return ob_get_clean(); | |
| } | |
| add_shortcode('youtube_embed', 'youtube_embed_shortcode'); |
Author
Author
Теперь вы можете использовать шорткод так:
[youtube_embed id="VIDEO_ID"] для загрузки maxresdefault.webp.
[youtube_embed id="VIDEO_ID" sd="true"] для загрузки sddefault.webp.
Этот подход позволит гибко переключаться между вариантами миниатюр.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Explanation:
Play Button Overlay: A red circular div with border-radius: 50% is used to create the play button.
Play Icon: inline SVG
Use [youtube_embed id="VIDEO_ID"] to test it.