Responsive SVG backgrounds

SVG is by far my favorite image format for its small size and 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.

Happy querying!


Thanks for reading! Go home for more notes.