{"record":{"id":"1b471bc2ad45e414","repo":"greensock/GSAP","slug":"scrollsmoother-needs-a-valid-content-element","errorCode":null,"errorMessage":"ScrollSmoother needs a valid content element.","messagePattern":"ScrollSmoother needs a valid content element\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/ScrollSmoother.js","lineNumber":377,"sourceCode":"\t\t\t\tstartupPhase ? ScrollTrigger.refresh() : adjustParallaxPosition([st], true); // all the effects need to go through the initial full refresh() so that all the pins and ratios and offsets are set up. That's why we do a full refresh() if it's during the startupPhase.\n\t\t\t}\n\t\t\ty = st.start / (ignoreSpeed ? speed : 1);\n\t\t\tst.kill(false);\n\t\t\ttarget.style.cssText = cssText;\n\t\t\tgsap.core.getCache(target).uncache = 1;\n\t\t\treturn y;\n\t\t};\n\n\t\tfunction refreshHeight() {\n\t\t\theight = content.clientHeight;\n\t\t\tcontent.style.overflow = \"visible\"\n\t\t\t_body.style.height = (_win.innerHeight + (height - _win.innerHeight) / speed) + \"px\";\n\t\t\treturn (height - _win.innerHeight);\n\t\t}\n\n\t\tthis.content = function(element) {\n\t\t\tif (arguments.length) {\n\t\t\t\tlet newContent = _toArray(element || \"#smooth-content\")[0] || console.warn(\"ScrollSmoother needs a valid content element.\") || _body.children[0];\n\t\t\t\tif (newContent !== content) {\n\t\t\t\t\tcontent = newContent;\n\t\t\t\t\tcontentCSS = content.getAttribute(\"style\") || \"\";\n\t\t\t\t\tresizeObserver && resizeObserver.observe(content);\n\t\t\t\t\tgsap.set(content, {overflow: \"visible\", width: \"100%\", boxSizing: \"border-box\", y: \"+=0\"});\n\t\t\t\t\tsmoothDuration || gsap.set(content, {clearProps: \"transform\"});\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t}\n\t\t\treturn content;\n\t\t}\n\n\t\tthis.wrapper = function(element) {\n\t\t\tif (arguments.length) {\n\t\t\t\twrapper = _toArray(element || \"#smooth-wrapper\")[0] || _wrap(content);\n\t\t\t\twrapperCSS = wrapper.getAttribute(\"style\") || \"\";\n\t\t\t\trefreshHeight();\n\t\t\t\tgsap.set(wrapper, smoothDuration ? {overflow: \"hidden\", position: \"fixed\", height: \"100%\", width: \"100%\", top: 0, left: 0, right: 0, bottom: 0} : {overflow: \"visible\", position: \"relative\", width: \"100%\", height: \"auto\", top: \"auto\", bottom: \"auto\", left: \"auto\", right: \"auto\"});","sourceCodeStart":359,"sourceCodeEnd":395,"githubUrl":"https://github.com/greensock/GSAP/blob/13e2b790546426a1a2e0e9b409f3f8dc6d6611f2/src/ScrollSmoother.js#L359-L395","documentation":"ScrollSmoother must know which element wraps the scrolling content (default selector \"#smooth-content\"). The content setter warns \"ScrollSmoother needs a valid content element.\" when _toArray resolves nothing, then falls back to _body.children[0].","triggerScenarios":"Creating a smoother when no element matches vars.content (default \"#smooth-content\") and the page body has no children to fall back on, or passing content: \"#wrong-id\"; also calling smoother.content(el) with a selector that matches nothing.","commonSituations":"Forgot to add the #smooth-content wrapper div in markup, content element rendered after smoother creation in an SPA, typo in the content selector, or the plugin instantiated before React/Vue mounts the layout.","solutions":["Add a wrapper element with id=\"smooth-content\" (or set vars.content to your existing wrapper selector)","Ensure the content element exists in the DOM before creating the smoother","Pass an actual Element reference as content instead of a selector","Create the smoother inside a useEffect/useMounted hook after layout renders"],"exampleFix":"// before\nconst smoother = ScrollSmoother.create({ smooth: 1 }); // no #smooth-content in DOM\n// after\n<div id=\"smooth-wrapper\"><div id=\"smooth-content\">...</div></div>\nconst smoother = ScrollSmoother.create({ smooth: 1, content: '#smooth-content' });","handlingStrategy":"validation","validationCode":"const contentSel = vars?.content || '#smooth-content';\nif (!document.querySelector(contentSel)) {\n  throw new Error(`ScrollSmoother content element missing: ${contentSel}`);\n}\nconst smoother = ScrollSmoother.create({ content: contentSel, ...vars });","typeGuard":"function isElement(v) { return v instanceof Element; }","tryCatchPattern":null,"preventionTips":["Always include #smooth-wrapper/#smooth-content markup when using ScrollSmoother","Create the smoother after layout render (useEffect/mounted)","Pass explicit content selectors/elements rather than relying on defaults"],"tags":["gsap","scrollsmoother","dom","selector"],"backgroundTag":"element-not-found","analyzedSha":"13e2b790546426a1a2e0e9b409f3f8dc6d6611f2","analyzedAt":"2026-08-29T08:34:05.027Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}