Changeset cb95343 in Klonkt


Ignore:
Timestamp:
06/27/2026 08:30:29 AM (2 months ago)
Author:
Robin Genis <roboburr@…>
Branches:
main
Children:
a3e0746
Parents:
9e4e4ff
Message:

fix(embeds): plain responsive iframe on mobile/touch

The custom JS-mounted player cards need the platform API + an i.ytimg.com poster, both
of which mobile Safari tracking-protection blocks → a blank/black box. On touch / coarse-
pointer devices, render the plain platform iframe directly (YouTube/SoundCloud/Spotify),
using a padding-ratio wrapper that reserves height on every browser incl. old iOS Safari.
Desktop keeps the rich card. embed.css v9, embed-player.js v17.

Location:
src
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • src/assets/css/embed.css

    r9e4e4ff rcb95343  
    275275.pcms-embed-pp,
    276276.pcms-embed-poster { -webkit-tap-highlight-color: transparent; }
     277
     278/* ---- Mobile / touch: plain platform iframe instead of the JS-mounted card.
     279   padding-ratio reserves height on every browser (incl. old iOS Safari). ---- */
     280.pcms-embed-plain { background: transparent; box-shadow: none; }
     281.pcms-embed-ratio { position: relative; width: 100%; padding-bottom: 56.25%; height: 0; }
     282.pcms-embed-ratio iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; border-radius: 10px; }
     283.pcms-embed-plain-frame { width: 100%; border: 0; display: block; border-radius: 10px; }
     284.pcms-embed-plain-link { display: inline-block; padding: .5rem .9rem; }
  • src/assets/js/embed-player.js

    r9e4e4ff rcb95343  
    153153  const LABEL = { youtube: 'YouTube', soundcloud: 'SoundCloud', spotify: 'Spotify' };
    154154
     155  // Touch / coarse-pointer (phones, most tablets): the custom JS-mounted card is
     156  // fragile — Safari tracking-protection blocks the platform API scripts AND the
     157  // poster thumbnails (i.ytimg.com) → a black/blank box. Render the plain, reliable
     158  // platform iframe directly instead (same approach the News feed uses). The
     159  // padding-ratio wrapper reserves height on every browser incl. old iOS Safari
     160  // (no `aspect-ratio` dependency). Desktop keeps the rich custom card.
     161  const IS_TOUCH = !!(window.matchMedia && window.matchMedia('(hover: none) and (pointer: coarse)').matches);
     162
     163  function mountPlain(el, provider, ref, url) {
     164    el.classList.add('pcms-embed-card', 'pcms-embed-card--' + provider, 'pcms-embed-plain');
     165    el.classList.remove('pcms-embed-loading');
     166    let html = '';
     167    if (provider === 'youtube') {
     168      const id = ytId(ref, url);
     169      html = id
     170        ? '<div class="pcms-embed-ratio"><iframe src="https://www.youtube-nocookie.com/embed/' + encodeURIComponent(id) + '?rel=0" title="YouTube" loading="lazy" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>'
     171        : '<a class="pcms-embed-plain-link" href="' + escAttr(safeHref(url)) + '" target="_blank" rel="noopener">YouTube</a>';
     172    } else if (provider === 'soundcloud') {
     173      html = '<iframe class="pcms-embed-plain-frame" style="height:166px" src="https://w.soundcloud.com/player/?url=' + encodeURIComponent(ref || url) + '&color=%23ff5500&visual=false" title="SoundCloud" loading="lazy" frameborder="0" allow="autoplay" scrolling="no"></iframe>';
     174    } else if (provider === 'spotify') {
     175      const m = (ref || '').match(/^spotify:(\w+):(\w+)$/);
     176      const src = m ? 'https://open.spotify.com/embed/' + m[1] + '/' + m[2] : (url || '');
     177      html = '<iframe class="pcms-embed-plain-frame" style="height:152px" src="' + escAttr(src) + '" title="Spotify" loading="lazy" frameborder="0" allow="encrypted-media"></iframe>';
     178    } else {
     179      html = '<a class="pcms-embed-plain-link" href="' + escAttr(safeHref(url)) + '" target="_blank" rel="noopener">' + (LABEL[provider] || provider) + '</a>';
     180    }
     181    el.innerHTML = html;
     182  }
     183
    155184  // ============================================================
    156185  // 3. Card controller — builds the on-brand card + delegates to an adapter
     
    161190    const url = el.dataset.embedUrl || '';
    162191    if (!provider) return;
     192    if (IS_TOUCH) { mountPlain(el, provider, ref, url); return; }
    163193
    164194    el.classList.add('pcms-embed-card', 'pcms-embed-card--' + provider);
  • src/views/shell.ejs

    r9e4e4ff rcb95343  
    252252<link rel="stylesheet" href="/assets/css/audio.css?v=11">
    253253<!-- Eigen custom media-embeds (YouTube/SoundCloud/Spotify) in huisstijl. -->
    254 <link rel="stylesheet" href="/assets/css/embed.css?v=8">
     254<link rel="stylesheet" href="/assets/css/embed.css?v=9">
    255255
    256256<%- include('partials/shared-styles') %>
     
    385385<!-- Eigen custom media-embeds (YouTube/SoundCloud/Spotify) via de echte
    386386     player-API's + gedeelde mutual-exclusion registry met de site-speler. -->
    387 <script src="/assets/js/embed-player.js?v=16" defer></script>
     387<script src="/assets/js/embed-player.js?v=17" defer></script>
    388388<% if (site && site.enable_audio_player && audioTracks && audioTracks.length > 0) { %>
    389389  <script>window.PCMS_SITE_TRACKS = <%- JSON.stringify(audioTracks) %>;</script>
Note: See TracChangeset for help on using the changeset viewer.