Portfolio Header Navigation

I released new better version, you can check new instruction here

Portfolio header navigation 1

#1. Install Code

Add code to Code Injection > Footer

<!-- @tuanphan - Portfolio Header Navigation -->
<script>(function(){var targetSel='#work';var PORT_URL='/port-effect';function q(sel,root){return(root||document).querySelector(sel)}
function qa(sel,root){return Array.from((root||document).querySelectorAll(sel))}
function extractItemsFromJSON(data){if(!data||!data.items)return[];return data.items.map(function(item){var img=item.assetUrl||'';if(img)img+=(img.includes('?')?'&':'?')+'format=300w';return{href:item.fullUrl||'#',title:item.title||'',img:img}}).filter(function(it){return it.href&&it.title})}
function buildMenu(items){var ul=document.createElement('ul');ul.className='work-menu';ul.setAttribute('data-work-injected','1');items.forEach(function(it){var li=document.createElement('li');li.className='work-menu-item';var a=document.createElement('a');a.href=it.href;var th=document.createElement('span');th.className='work-thumb';var img=document.createElement('img');img.alt='';img.loading='lazy';img.decoding='async';img.src=it.img||'';var tt=document.createElement('span');tt.className='work-title';tt.textContent=it.title;th.appendChild(img);a.appendChild(th);a.appendChild(tt);li.appendChild(a);ul.appendChild(li)});return ul}
function inject(items){var target=q(targetSel);if(!target||!items||!items.length)return;qa('[data-work-injected="1"]',target).forEach(function(n){n.remove()});var existing=new Set(qa('a[href]',target).map(function(e){return e.getAttribute('href')}));var uniq=items.filter(function(it){return!existing.has(it.href)});uniq.sort(function(a,b){return a.title.localeCompare(b.title)});if(!uniq.length)return;target.appendChild(buildMenu(uniq))}
function saveCache(items){try{sessionStorage.setItem('workMenuCache',JSON.stringify({t:Date.now(),items:items}))}catch(e){}}
function loadCache(maxAgeMs){try{var raw=sessionStorage.getItem('workMenuCache');if(!raw)return null;var obj=JSON.parse(raw);if(!obj||!obj.items)return null;if(Date.now()-(obj.t||0)>maxAgeMs)return null;return obj.items}catch(e){return null}}
function fetchPortfolio(){var url=PORT_URL+(PORT_URL.includes('?')?'&':'?')+'format=json';return fetch(url,{credentials:'same-origin'}).then(function(r){if(!r.ok)throw new Error('HTTP '+r.status);return r.json()}).then(function(data){return extractItemsFromJSON(data)})}
function getItems(){var cached=loadCache(6*60*60*1000);if(cached)return Promise.resolve(cached);return fetchPortfolio().then(function(items){if(items.length)saveCache(items);return items}).catch(function(){return[]})}
function ensureMenu(){getItems().then(function(items){inject(items)})}
function start(){ensureMenu();var trigger=q('.header-nav-folder-title[href="/work"]');var container=q(targetSel);if(trigger&&container){trigger.addEventListener('mouseenter',ensureMenu);trigger.addEventListener('click',ensureMenu,{passive:!0})}
var i=0,iv=setInterval(function(){ensureMenu();if(++i>10)clearInterval(iv)},500);}
if(document.readyState!=='loading')start();else document.addEventListener('DOMContentLoaded',start)})()</script>

Portfolio header navigation 2

Next, add this code to Custom CSS

/* @tuanphan - Portfolio Header Navigation */
#work {
    --portfolio-columns: 3;
    --work-min-width: 500px;
    --work-pad: 11px;
    --work-bg: #fff;
    --work-radius: 0px;
    --work-grid-gap: 6px;
    --work-item-gap: 11px;
    --work-item-pad-y: 12px;
    --work-item-pad-x: 14px;
    --work-thumb-size: 36px;
    --work-thumb-radius: 0px;
    --work-title-size: 14px;
    --work-title-color: #111;
}
.header-nav-folder-content#work{min-width:var(--work-min-width);padding:var(--work-pad);background:var(--work-bg);border-radius:var(--work-radius);left:50%!important;transform:translateX(-50%)!important;width:auto!important}#work .work-menu{list-style:none;margin:0;padding:4px;display:grid;grid-template-columns:repeat(var(--portfolio-columns),1fr);gap:var(--work-grid-gap)}#work .work-menu-item a{display:flex;align-items:center;gap:var(--work-item-gap);padding:var(--work-item-pad-y) var(--work-item-pad-x);text-decoration:none}#work .work-thumb{width:var(--work-thumb-size);height:var(--work-thumb-size);border-radius:var(--work-thumb-radius);overflow:hidden;flex:0 0 var(--work-thumb-size)}#work .work-thumb img{width:100%;height:100%;object-fit:cover;display:block}#work .work-title{font-size:var(--work-title-size);color:var(--work-title-color)}

Portfolio header navigation 3

#2. Usage

In Main Navigation > Click Plus icon > Choose Dropdown

Portfolio header navigation 4

You can use any names, but URL must be /work

/work

Portfolio header navigation 5

Next, in Code Injection > Footer > Edit Portfolio Page URL Slug

In my example, I have Portfolio Page URL Slug: /port-effect

Portfolio header navigation 6

but if you have Portfolio Page URL: /projects you can enter /projects like this.

Portfolio header navigation 7

#3. Customize

All style options here

#work {
    --portfolio-columns: 3; /* number of columns */
    --work-min-width: 500px; /* minimum width of portfolio dropdown */
    --work-pad: 11px; /* space around dropdown */
    --work-bg: #fff; /* dropdown background color */
    --work-radius: 0px; /* rounded corners of dropdown */
    --work-grid-gap: 6px; /* space between items in dropdown */
    --work-item-gap: 11px; /* space between image - text */
    --work-item-pad-y: 12px; /* horizontal space between items */
    --work-item-pad-x: 14px; /* vertical space between items */
    --work-thumb-size: 36px; /* image size */
    --work-thumb-radius: 0px; /* rounded corners of image */
    --work-title-size: 14px; /* text size */
    --work-title-color: #111; /* text color */
}

Portfolio header navigation 8

Buy me a coffee