Sync Blog Excerpt to Gallery Masonry text

To add rich text to Gallery Masonry text, like this.

We can use Blog Excerpt, then sync Excerpt with Masonry Caption text. Follow these steps.

#1. First edit Masonry Gallery > Enable Captions

#2. Add to Description of all images

#3. Create a Blog Page with URL: /sync-blog

#4. Create some blog post items, then add your desired text to Excerpt

#5. Use this code to Page Header Injection (page where you use Masonry Gallery)

<!-- Masonry Gallery - Blog Excerpt - @tuanphan - 23-09-2025 -->
<script>(function(){function all(s,r){return Array.prototype.slice.call((r||document).querySelectorAll(s))}
function textOnly(s){var d=document.createElement('div');d.innerHTML=s||'';return(d.textContent||'').replace(/\s+/g,' ').trim()}
function sanitize(html){var allowed={strong:1,b:1,em:1,i:1,u:1,br:1,p:1,a:1};var tmp=document.createElement('div');tmp.innerHTML=html||'';(function walk(node){var children=Array.prototype.slice.call(node.childNodes);children.forEach(function(n){if(n.nodeType===1){var tag=n.tagName.toLowerCase();if(!allowed[tag]){var rep=document.createTextNode(n.textContent||'');n.parentNode.replaceChild(rep,n);return}
if(tag==='a'){Array.prototype.slice.call(n.attributes).forEach(function(a){if(a.name!=='href')n.removeAttribute(a.name);});var href=n.getAttribute('href')||'';var ok=/^(https?:\/\/|\/|mailto:|tel:)/i.test(href);if(!ok){n.removeAttribute('href');n.replaceWith(document.createTextNode(n.textContent||''));return}
n.setAttribute('target','_blank');n.setAttribute('rel','noopener noreferrer')}else{Array.prototype.slice.call(n.attributes).forEach(function(a){n.removeAttribute(a.name)})}
walk(n)}else if(n.nodeType===3){return}else{n.parentNode.removeChild(n)}})})(tmp);return tmp.innerHTML}
function getBlogExcerptsHTMLFromJSON(path){return fetch(path+'?format=json-pretty',{credentials:'same-origin'}).then(function(r){if(!r.ok)throw 0;return r.json()}).then(function(j){var items=(j&&j.items)||[];var out=[];for(var i=0;i<items.length;i++){var it=items[i];var raw=(it.excerpt&&it.excerpt.length?it.excerpt:it.body)||'';var cleaned=sanitize(raw);if(textOnly(cleaned))out.push(cleaned);}
return out})}
function getBlogExcerptsHTMLFromHTML(path){return fetch(path,{credentials:'same-origin'}).then(function(r){if(!r.ok)throw 0;return r.text()}).then(function(h){var doc=new DOMParser().parseFromString(h,'text/html');var els=all('.blog-excerpt-wrapper, .blog-excerpt',doc);var out=els.map(function(el){return sanitize(el.innerHTML||'')}).filter(function(s){return textOnly(s).length>0});return out})}
function getExcerptsHTML(path){return getBlogExcerptsHTMLFromJSON(path).catch(function(){return getBlogExcerptsHTMLFromHTML(path)})}
function ensureCaption(fig){var wrap=fig.querySelector('.gallery-masonry-item-wrapper')||fig;var cap=fig.querySelector('figcaption.gallery-caption, .gallery-caption');if(!cap){cap=document.createElement('figcaption');cap.className='gallery-caption';wrap.appendChild(cap)}
return cap}
function enableCaptions(){var g=document.querySelector('.gallery-masonry');if(g&&g.getAttribute('data-show-captions')!=='true')g.setAttribute('data-show-captions','true');}
function syncRich(excerptsHTML){if(!excerptsHTML||!excerptsHTML.length)return!1;enableCaptions();var figs=all('.gallery-masonry .gallery-masonry-item');if(!figs.length)return!1;var n=Math.min(figs.length,excerptsHTML.length);for(var i=0;i<n;i++){var fig=figs[i];var cap=ensureCaption(fig);var html=excerptsHTML[i];if(cap.innerHTML!==html)cap.innerHTML=html;if(fig.hasAttribute('data-caption'))fig.removeAttribute('data-caption');}
return!0}
function start(blogPath){var cached=[];var syncing=!1;function trySync(){if(syncing)return;syncing=!0;var apply=function(list){if(list&&list.length)cached=list;var ok=syncRich(cached);syncing=!1;return ok};if(cached.length){apply();return}
getExcerptsHTML(blogPath).then(function(list){apply(list)}).catch(function(){syncing=!1})}
var tries=0;var tick=setInterval(function(){tries++;trySync();if(tries>100)clearInterval(tick);},150);var mo=new MutationObserver(function(){trySync()});mo.observe(document.body,{childList:!0,subtree:!0})}
function main(){var blogPath='/sync-blog';if(location.pathname.replace(/\/+$/,'')===blogPath)return;if(!document.querySelector('.gallery-masonry'))return;start(blogPath)}
if(document.readyState==='complete'||document.readyState==='interactive')main();else document.addEventListener('DOMContentLoaded',main,{once:!0})})();</script>
<style>figcaption.gallery-caption.gallery-caption-grid-masonry{position:absolute!important;top:0;left:0;width:calc(100% - 20px);height:100%;display:flex;align-items:center;justify-content:center;flex-direction:column;padding-left:10px;padding-right:10px;background-color:rgb(255 255 255 / .95);opacity:0;transition:all 0.3s ease;pointer-events:none}figure:hover figcaption.gallery-caption.gallery-caption-grid-masonry{opacity:1;transition:all 0.3s ease}</style>

#6. If you use another url for blog page, you can change url here

Buy me a coffee