diff --git a/web/src/index.js b/web/src/index.js
index e81bfd1af7d6a9681fa8cdcbd02ddb74e7f77f18..585d854b32a204573e8c650561fecb78514506ca 100644
--- a/web/src/index.js
+++ b/web/src/index.js
@@ -43,6 +43,8 @@ class App extends Component {
 		this.sendSticker = this.sendSticker.bind(this)
 		this.navScroll = this.navScroll.bind(this)
 		this.reloadPacks = this.reloadPacks.bind(this)
+		this.observeSectionIntersections = this.observeSectionIntersections.bind(this)
+		this.observeImageIntersections = this.observeImageIntersections.bind(this)
 	}
 
 	_getStickersByID(ids) {
@@ -129,15 +131,32 @@ class App extends Component {
 	}
 
 	observeSectionIntersections(intersections) {
+		const navWidth = this.navRef.getBoundingClientRect().width
+		let minX = 0, maxX = navWidth
+		let minXElem = null
+		let maxXElem = null
 		for (const entry of intersections) {
 			const packID = entry.target.getAttribute("data-pack-id")
 			const navElement = document.getElementById(`nav-${packID}`)
 			if (entry.isIntersecting) {
 				navElement.classList.add("visible")
+				const bb = navElement.getBoundingClientRect()
+				if (bb.x < minX) {
+					minX = bb.x
+					minXElem = navElement
+				} else if (bb.right > maxX) {
+					maxX = bb.right
+					maxXElem = navElement
+				}
 			} else {
 				navElement.classList.remove("visible")
 			}
 		}
+		if (minXElem !== null) {
+			minXElem.scrollIntoView({ inline: "start", behavior: "smooth" })
+		} else if (maxXElem !== null) {
+			maxXElem.scrollIntoView({ inline: "end", behavior: "instant" })
+		}
 	}
 
 	componentDidUpdate() {