you can extend it too. here are my CSS and JS
CSS:
/* Wrapper around each avatar so hats can be absolutely positioned */
.avatar-festive-wrapper {
position: relative;
display: inline-block;
}
/* Base hat positioning; size and top are handled in JS */
.avatar-festive-hat {
position: absolute;
left: 50%;
transform: translateX(-50%);
pointer-events: none;
z-index: 2;
}
.PostUser-avatar + .avatar-festive-hat {
transform: translateX(-150%); /* instead of -50% */
}
JS:
<script>
(function () {
const AVATAR_SELECTOR = 'span.Avatar';
const svgns = 'http://www.w3.org/2000/svg';
function createSvg(tag) {
return document.createElementNS(svgns, tag);
}
function getAvatarSizePx(avatar) {
const styles = getComputedStyle(avatar);
let sizeVar = styles.getPropertyValue('--size').trim();
if (sizeVar) {
const n = parseFloat(sizeVar);
if (!isNaN(n)) return n;
}
const w = avatar.offsetWidth;
if (w > 0) return w;
return 36; // safe default
}
function addHatToAvatar(avatar) {
if (avatar.dataset.festiveDecorated === '1') return;
avatar.dataset.festiveDecorated = '1';
// Wrap avatar
let wrapper = avatar.parentElement;
if (!wrapper || !wrapper.classList.contains('avatar-festive-wrapper')) {
wrapper = document.createElement('span');
wrapper.className = 'avatar-festive-wrapper';
avatar.parentNode.insertBefore(wrapper, avatar);
wrapper.appendChild(avatar);
}
const size = getAvatarSizePx(avatar); // 36, 64, 96…
const hats = ['santa', 'elf', 'reindeer'];
const hat = hats[Math.floor(Math.random() * hats.length)];
let svg;
if (hat === 'santa') {
// Santa hat
svg = createSvg('svg');
svg.setAttribute('viewBox', '0 0 100 60');
const triangle = createSvg('path');
triangle.setAttribute('d', 'M10 55 L60 5 L90 55 Z');
triangle.setAttribute('fill', '#e53935');
const brim = createSvg('rect');
brim.setAttribute('x', '10');
brim.setAttribute('y', '45');
brim.setAttribute('width', '80');
brim.setAttribute('height', '15');
brim.setAttribute('rx', '7');
brim.setAttribute('fill', '#ffffff');
const pom = createSvg('circle');
pom.setAttribute('cx', '60');
pom.setAttribute('cy', '8');
pom.setAttribute('r', '8');
pom.setAttribute('fill', '#ffffff');
svg.appendChild(triangle);
svg.appendChild(brim);
svg.appendChild(pom);
} else if (hat === 'elf') {
// Elf hat
svg = createSvg('svg');
svg.setAttribute('viewBox', '0 0 100 60');
const triangle = createSvg('path');
triangle.setAttribute('d', 'M10 55 L60 5 L90 55 Z');
triangle.setAttribute('fill', '#3cb371'); // green
const brim = createSvg('rect');
brim.setAttribute('x', '10');
brim.setAttribute('y', '45');
brim.setAttribute('width', '80');
brim.setAttribute('height', '15');
brim.setAttribute('rx', '7');
brim.setAttribute('fill', '#ffffff');
const bauble = createSvg('circle');
bauble.setAttribute('cx', '85');
bauble.setAttribute('cy', '45');
bauble.setAttribute('r', '7');
bauble.setAttribute('fill', '#ff0000'); // red
svg.appendChild(triangle);
svg.appendChild(brim);
svg.appendChild(bauble);
} else {
// Reindeer antlers
svg = createSvg('svg');
svg.setAttribute('viewBox', '0 0 120 80');
const leftMain = createSvg('path');
leftMain.setAttribute('d', 'M40 70 C20 40, 35 20, 30 5');
leftMain.setAttribute('stroke', '#8b4513');
leftMain.setAttribute('stroke-width', '7');
leftMain.setAttribute('fill', 'none');
const leftBranch1 = createSvg('path');
leftBranch1.setAttribute('d', 'M30 25 C15 20, 15 10, 18 5');
leftBranch1.setAttribute('stroke', '#8b4513');
leftBranch1.setAttribute('stroke-width', '6');
leftBranch1.setAttribute('fill', 'none');
const leftBranch2 = createSvg('path');
leftBranch2.setAttribute('d', 'M35 35 C18 32, 18 22, 22 18');
leftBranch2.setAttribute('stroke', '#8b4513');
leftBranch2.setAttribute('stroke-width', '6');
leftBranch2.setAttribute('fill', 'none');
const rightMain = createSvg('path');
rightMain.setAttribute('d', 'M80 70 C100 40, 85 20, 90 5');
rightMain.setAttribute('stroke', '#8b4513');
rightMain.setAttribute('stroke-width', '7');
rightMain.setAttribute('fill', 'none');
const rightBranch1 = createSvg('path');
rightBranch1.setAttribute('d', 'M90 25 C105 20, 105 10, 102 5');
rightBranch1.setAttribute('stroke', '#8b4513');
rightBranch1.setAttribute('stroke-width', '6');
rightBranch1.setAttribute('fill', 'none');
const rightBranch2 = createSvg('path');
rightBranch2.setAttribute('d', 'M85 35 C102 32, 102 22, 98 18');
rightBranch2.setAttribute('stroke', '#8b4513');
rightBranch2.setAttribute('stroke-width', '6');
rightBranch2.setAttribute('fill', 'none');
svg.appendChild(leftMain);
svg.appendChild(leftBranch1);
svg.appendChild(leftBranch2);
svg.appendChild(rightMain);
svg.appendChild(rightBranch1);
svg.appendChild(rightBranch2);
}
svg.classList.add('avatar-festive-hat');
// Autoscaling for all sizes (36, 64, 96…)
let widthFactor, topFactor;
if (hat === 'reindeer') {
widthFactor = 0.95; // antlers are wider
topFactor = -0.36; // sit a bit higher
} else {
widthFactor = 0.68; // hats ~68% of avatar width
topFactor = -0.29; // slightly above the circle
}
svg.style.width = size * widthFactor + 'px';
svg.style.top = size * topFactor + 'px';
wrapper.appendChild(svg);
}
function decorateAllAvatars() {
document.querySelectorAll(AVATAR_SELECTOR).forEach(addHatToAvatar);
}
function init() {
decorateAllAvatars();
const observer = new MutationObserver(decorateAllAvatars);
observer.observe(document.body, { childList: true, subtree: true });
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();
</script>