Responsive SVG backgrounds

November 27, 2018

SVG, also known as 'Scalable Vector Graphics', is by far my favorite image format for its small size and the ability to be manipulated dynamically via Javascript. However, it can be tricky to implement in some cases. One such case I recently came across is how to resize the SVG viewBox as the viewport resizes.

I'm by no means an expert on working with SVG, but I did discover one solution to this problem: using the window.matchMedia() web API:

// Grab SVG element
let bg = document.getElementById('bg-mbl')

// Media query event handler
if (matchMedia) {
	let mqls = [ // Array of media queries
		window.matchMedia("(min-width: 400px) and (max-width: 600px)"),
		window.matchMedia("(min-width: 600px) and (max-width: 800px)"),
		window.matchMedia("(min-width: 800px) and (max-width: 1000px)")

	for (i=0; i < mqls.length; i++) { // Loop though media queries
		mqls[i].addListener(widthChange) // Listen for queries
		widthChange(mqls[i]) // Call handler func at runtime

// Media query change
function widthChange(mql) {
	if (mqls[0].matches) { 
		bg.setAttribute("viewBox", "0 150 375 580")
	else if (mqls[1].matches) {
		bg.setAttribute("viewBox", "0 300 375 580")
	else if (mqls[2].matches) {
		bg.setAttribute("viewBox", "0 400 375 580")
	else {
		// Set default
		bg.setAttribute("viewBox", "0 0 375 580")

The matchMedia API lets you pass a media query string, such as min-width: 400px, and will return a new MediaQueryList, which is a fancy object that helps manage when the media query state changes. In our case, we're querying for viewport width, so as the screen width changes and one of the media query cases becomes true, we reset the size of the SVG viewBox to our liking. According to MDN:

MediaQueryList makes it possible to observe a document to detect when its media queries change, instead of polling the values periodically, and allows you to programmatically make changes to a document based on media query status.

If you'd like to see it in action, check out v2 of this site where I use the matchMedia approach to scale the blue sky at the top of the landing page.

Thanks for reading ❤️

If you're jazzed about this post, feel free to tweet this article 🐦

If I missed something, please do drop me a message and I'll fix it 🔨

Otherwise, read more articles! ✍️