Git-Pages #2 - Collapsible code blocks
While I’m on this whole “building a blog” thing, I’ve noticed that code blocks can get really long. When a code block has 50+ lines, it takes up a lot of vertical space and makes the post hard to read. Sure, you can scroll past it, but it’s not exactly elegant.

So I decided to make code blocks collapsible. Here’s how it works:
- Code blocks with 10 or fewer lines are displayed normally.
- Code blocks with more than 10 lines start collapsed, showing only the first 10.
- A “Show X more lines” button appears in the bottom right.
- Clicking it expands the full code block.
- The button then changes to “Hide” to collapse it again. I’m not sure it’s useful because by that point you’d already be ‘past’ the code, but it still seemed odd not to have this feature.
The implementation uses the standard Hugo “extra partials” feature, so no modifications to the theme were needed. I created two files:
layouts/_partials/extra-head.html with the CSS:
<style>
.code-collapsible {
position: relative;
display: block;
}
.code-collapsible .collapse-toggle {
display: block !important;
position: absolute;
bottom: 7px;
right: 70px;
background: rgba(120, 120, 120, 0.35);
border: 1px solid var(--border-color);
border-radius: 4px;
padding: 4px 10px;
font-size: 0.75rem;
color: inherit;
cursor: pointer;
opacity: 0.9;
font-family: inherit;
z-index: 5;
}
.code-collapsible:hover .collapse-toggle {
opacity: 1;
}
.code-collapsible .collapse-toggle:hover {
background: rgba(120, 120, 120, 0.5);
}
.code-collapsible .chroma {
max-height: none;
overflow: visible;
transition: max-height 0.3s ease;
}
.code-collapsible.collapsed .chroma {
max-height: calc(1.6em * 15); /* In my theme, 1.6 is the line height */
overflow: hidden;
}
</style>
And layouts/_partials/extra-foot.html with the JavaScript:
<script>
(function() {
try {
var codeBlocks = document.querySelectorAll('.highlight');
for (var i = 0; i < codeBlocks.length; i++) {
var lines = codeBlocks[i].querySelectorAll('.line');
if (lines.length > 10) {
codeBlocks[i].classList.add('code-collapsible', 'collapsed');
var btn = document.createElement('button');
btn.className = 'collapse-toggle';
btn.type = 'button';
btn.textContent = 'Show ' + (lines.length - 10) + ' more lines';
btn.onclick = (function(container) {
return function() {
if (container.classList.contains('expanded')) {
container.classList.remove('expanded');
container.classList.add('collapsed');
var l = container.querySelectorAll('.line').length;
this.textContent = 'Show ' + (l - 10) + ' more lines';
} else {
container.classList.remove('collapsed');
container.classList.add('expanded');
this.textContent = 'Hide';
}
};
})(codeBlocks[i]);
codeBlocks[i].appendChild(btn);
}
}
} catch(e) {}
})();
</script>
The theme I’m using, Hermit-V2, already supports extra-head.html and extra-foot.html - these are partials that get included in every page automatically. The copy button1 (provided by the theme) still works fine - it copies the entire code, not just the visible portion.
As I mentioned in my previous dev-blog, I’m just getting started with web development, so there’s definitely room for improvement here. I’m always open to suggestions.
That’s all for now. Ciao!
Don’t trust the ‘Copy’ buttons you find on random web pages; copy and paste the code yourself. Or, se ti pesa il culo, always check what you’re pasting, especially if it’s a script to be run in the terminal! ↩︎
Comments
You can use your Mastodon or other fediverse account to comment on this article by replying to the associated post .