For example, to render the variously changing datetimes of a yearly-repeating event that lasts several days, having a re-usable single svg image that can take a data-datetime="yyyy-mm-dd" attribute from its svg tag and render that into a proper date that is subsequently displayed within the image. The reason one might want this is for say, a ticketing system that the display/splash/product image would otherwise have to be a separate image file for every day of the event, if you wanted that image to show the date within itself.
Something like this?
const formattedDate = dateText => new Date(dateText).toLocaleDateString('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric'
});
const updateSVGDate = svgElement => {
const dateText = svgElement.dataset.datetime;
const dateEmoji = svgElement.dataset.emoji;
if (dateText) {
const textElement = svgElement.querySelector('.event-date');
if (textElement) {
textElement.textContent = formattedDate(`${dateText}T15:00:00`); // force date to not be midnight
if (dateEmoji) textElement.textContent += ` ${dateEmoji}`;
}
}
}
window.addEventListener('load', () => { // when the page loads
document.querySelectorAll('.event-svg').forEach(updateSVGDate)
});
<svg class="event-svg" data-datetime="2025-02-14" data-emoji="❤️" width="200" height="100">
<rect width="200" height="100" fill="pink" />
<text class="event-date" x="50%"
y="50%"
text-anchor="middle"
dominant-baseline="middle" font-size="16" fill="black">Default Date</text>
</svg>
<svg class="event-svg" data-datetime="2025-04-01" data-emoji="🤡" width="200" height="100">
<rect width="200" height="100" fill="lightblue" />
<text class="event-date" x="50%"
y="50%"
text-anchor="middle"
dominant-baseline="middle" font-size="16" fill="black">Default Date</text>
</svg>
Here is a dynamically generated svg using an array for the events and a lookup table for the emoji
const formattedDate = dateText => {
const normalized = `${dateText}T15:00:00`; // make sure we do not have issues with timezones
return new Date(normalized).toLocaleDateString('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric',
});
};
const generateMonthDates = (year, month) => {
const lastDay = new Date(year, month + 1, 0); // Last day of the month
const totalDays = lastDay.getDate(); // Number of days in the month
return Array.from({ length: totalDays }, (_, i) => {
const day = i + 1; // Days start at 1
return `${year}-${String(month + 1).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
});
};
// Generate SVGs for a specific month and year
const svgNS = 'http://www.w3.org/2000/svg';
const renderMonthSVGs = (year, month) => {
const svgGrid = document.getElementById('svg-grid');
const monthDates = generateMonthDates(year, month);
monthDates.forEach(date => {
const monthDay = date.slice(5); // Extract MM-DD
const emojiData = emojis[monthDay] || {
"background-color": "lightblue",
"emoji": ""
};
// Create the SVG element
const svg = document.createElementNS(svgNS, "svg");
svg.setAttribute("class", "event-svg");
svg.setAttribute("data-datetime", date); // in case we need it later
svg.setAttribute("width", "200");
svg.setAttribute("height", "100");
// Create the rect element (background)
const rect = document.createElementNS(svgNS, "rect");
rect.setAttribute("width", "100%");
rect.setAttribute("height", "100%");
rect.setAttribute("fill", emojiData["background-color"]);
svg.appendChild(rect);
// Create the text element (date + emoji)
const text = document.createElementNS(svgNS, "text");
text.setAttribute("class", "event-date");
text.setAttribute("x", "50%");
text.setAttribute("y", "50%");
text.setAttribute("text-anchor", "middle");
text.setAttribute("dominant-baseline", "middle");
text.setAttribute("font-size", "16");
text.setAttribute("fill", "black");
text.textContent = formattedDate(date) + (emojiData.emoji ? ` ${emojiData.emoji}` : "");
svg.appendChild(text);
// Append the SVG to the grid
svgGrid.appendChild(svg);
});
};
// Render February 2025 SVGs
renderMonthSVGs(2025, 1); // 1 = February
.grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
/* Adjust columns as needed */
gap: 10px;
}
svg {
border: 1px solid #ccc;
}
<div id="svg-grid" class="grid"></div>
<script>
// testdata
const events = ["2025-02-14", "2025-02-16"]; // Specific event dates
const emojis = {
"02-14": {
"background-color": "pink",
"emoji": "❤️"
},
"02-16": {
"background-color": "orange",
"emoji": "🤡"
}
};
</script>