diff --git a/build.sh b/build.sh
index d5bade9..66bf894 100755
--- a/build.sh
+++ b/build.sh
@@ -6,6 +6,12 @@ set -euo pipefail
PATH="/tmp/claat:${PATH}" python3 ./build.py
sed -e 's#https://storage.googleapis.com/claat-public#/static#g' -i build/*/index.html
+# Stop focus() inside an embedding iframe from scrolling the parent page (see static/iframe-focus-fix.js)
+sed -e 's##' -i build/*/index.html
+if grep -L 'iframe-focus-fix.js' build/*/index.html | grep -q .; then
+ echo "iframe-focus-fix.js was not injected into every page - has claat's script tag changed?" >&2
+ exit 1
+fi
# The public static hosting seems offline (e.g. https://storage.googleapis.com/claat-public/codelab-elements.css) so we vendor these assets:
# Built by running `USE_BAZEL_VERSION=0.19.1 bazel build :bundle` with patches to:
diff --git a/static/iframe-focus-fix.js b/static/iframe-focus-fix.js
new file mode 100644
index 0000000..7237d37
--- /dev/null
+++ b/static/iframe-focus-fix.js
@@ -0,0 +1,13 @@
+// When a codelab is embedded in an iframe (e.g. on the CYF curriculum site),
+// codelab-elements.js focuses the current step on load. Focusing an element
+// inside an iframe scrolls the parent page to the iframe, losing the reader's
+// place. Force preventScroll on every focus() call, only when embedded.
+// Must load before codelab-elements.js.
+(function () {
+ if (window.self === window.top) return;
+ var originalFocus = HTMLElement.prototype.focus;
+ HTMLElement.prototype.focus = function (options) {
+ var opts = Object.assign({}, options, { preventScroll: true });
+ return originalFocus.call(this, opts);
+ };
+})();