Adding Youtube Gallery to Squarespace with Markdown

To add a Youtube Gallery to Squarespace, like this.

#1. First, add a Markdown Block with Youtube URLs

#2. Next, find Markdown Block ID

#3. Next, use this code to Custom CSS

You can also use this Youtube Gallery free widget, you can add Youtube Gallery easier to Squarespace without complex code.

/* Youtube Grid Video */
.youtube-gallery-grid {
  display: grid;
  gap: 20px;
  width: 100%;
  margin: 20px 0;
}
.youtube-gallery-item {
  position: relative;
  width: 100%;
}
.youtube-video-container {
  position: relative;
  width: 100%;
  padding-bottom: 56.25%;
  background: #000;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.youtube-video-iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border: none;
}
.youtube-play-button {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: rgba(255, 0, 0, 0.9);
  color: #fff;
  border: none;
  border-radius: 12px;
  width: 80px;
  height: 56px;
  font-size: 0;
  cursor: pointer;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.3s ease;
}
.youtube-play-button::before {
  content: '';
  width: 0;
  height: 0;
  border-style: solid;
  border-width: 12px 0 12px 20px;
  border-color: transparent transparent transparent #fff;
  margin-left: 4px;
}
.youtube-play-button:hover {
  background: rgba(255, 0, 0, 1);
  transform: translate(-50%, -50%) scale(1.1);
}

@media (max-width: 768px) {
  .youtube-gallery-grid {
    grid-template-columns: 1fr !important;
    gap: 15px;
  }
}

#4. Use this code to Page Header Injection

<!-- @tuanphan Markdown Youtube Grid -->
<script>
const galleryConfig = {
  blockId: '#block-yui_3_17_2_1_1760339695956_13713',
  columns: 3,
  gap: '20px'
};

(function() {
  let videoPlayers = [];
  let ytReady = false;
  let initialized = false;

  window.onYouTubeIframeAPIReady = function() {
    ytReady = true;
    initGallery();
  };

  function loadYouTubeAPI() {
    if (window.YT && window.YT.Player) {
      ytReady = true;
      return;
    }
    const tag = document.createElement('script');
    tag.src = 'https://www.youtube.com/iframe_api';
    const firstScriptTag = document.getElementsByTagName('script')[0];
    firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
  }

  function extractYouTubeId(url) {
    const patterns = [
      /(?:youtube\.com\/watch\?v=|youtu\.be\/)([^&\?\/]+)/,
      /youtube\.com\/embed\/([^&\?\/]+)/,
      /youtube\.com\/v\/([^&\?\/]+)/
    ];
    for (let pattern of patterns) {
      const match = url.match(pattern);
      if (match) return match[1];
    }
    return null;
  }

  function createYouTubePlayer(containerId, videoId) {
    if (!window.YT || !window.YT.Player) return null;

    return new window.YT.Player(containerId, {
      videoId: videoId,
      playerVars: {
        autoplay: 0,
        controls: 1,
        rel: 0,
        modestbranding: 1,
        playsinline: 1
      },
      events: {
        onStateChange: function(event) {
          const playerData = videoPlayers.find(p => p.player === event.target);
          if (!playerData) return;

          if (event.data === YT.PlayerState.PLAYING) {
            playerData.playButton.style.display = 'none';
            videoPlayers.forEach(p => {
              if (p !== playerData && p.player) {
                p.player.pauseVideo();
              }
            });
          } else if (event.data === YT.PlayerState.PAUSED || event.data === YT.PlayerState.ENDED) {
            playerData.playButton.style.display = 'flex';
          }
        }
      }
    });
  }

  function createGalleryItem(videoId, index) {
    const item = document.createElement('div');
    item.className = 'youtube-gallery-item';

    const container = document.createElement('div');
    container.className = 'youtube-video-container';

    const iframeContainer = document.createElement('div');
    iframeContainer.className = 'youtube-video-iframe';
    iframeContainer.id = 'youtube-player-' + index;

    const playButton = document.createElement('button');
    playButton.className = 'youtube-play-button';
    playButton.setAttribute('aria-label', 'Play video');

    container.appendChild(iframeContainer);
    container.appendChild(playButton);
    item.appendChild(container);

    playButton.addEventListener('click', function(e) {
      e.preventDefault();
      const playerData = videoPlayers[index];
      if (playerData && playerData.player) {
        playerData.player.playVideo();
      }
    });

    return { item, iframeContainer, playButton };
  }

  function initGallery() {
    if (initialized || !ytReady) return;

    const block = document.querySelector(galleryConfig.blockId);
    if (!block) {
      console.log('Block not found: ' + galleryConfig.blockId);
      return;
    }

    const links = block.querySelectorAll('a[href*="youtube.com"], a[href*="youtu.be"]');
    if (links.length === 0) {
      console.log('No YouTube links found in block');
      return;
    }

    console.log('Found ' + links.length + ' YouTube videos');

    const videoIds = [];
    links.forEach(link => {
      const videoId = extractYouTubeId(link.href);
      if (videoId) videoIds.push(videoId);
    });

    if (videoIds.length === 0) return;

    const galleryGrid = document.createElement('div');
    galleryGrid.className = 'youtube-gallery-grid';
    galleryGrid.style.gridTemplateColumns = `repeat(${galleryConfig.columns}, 1fr)`;
    galleryGrid.style.gap = galleryConfig.gap;

    videoIds.forEach((videoId, index) => {
      const { item, iframeContainer, playButton } = createGalleryItem(videoId, index);
      galleryGrid.appendChild(item);

      setTimeout(() => {
        const player = createYouTubePlayer(iframeContainer.id, videoId);
        videoPlayers[index] = {
          player: player,
          playButton: playButton,
          videoId: videoId
        };
      }, 100 * index);
    });

    const blockContent = block.querySelector('.sqs-block-content');
    if (blockContent) {
      blockContent.innerHTML = '';
      blockContent.appendChild(galleryGrid);
    }

    initialized = true;
  }

  loadYouTubeAPI();

  function checkAndInit() {
    const block = document.querySelector(galleryConfig.blockId);
    if (block && !initialized && ytReady) {
      initGallery();
    }
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', function() {
      setTimeout(checkAndInit, 1000);
      setInterval(checkAndInit, 2000);
    });
  } else {
    setTimeout(checkAndInit, 1000);
    setInterval(checkAndInit, 2000);
  }
})();
</script>

#5. Remember to update Markdown Block ID & number of columns.

1 Like

it is my account, accidentally logged in and posted on the wrong account :sweat_smile:

2 Likes