如何让NextUI模态框内的Iframe无滚动,由模态框处理滚动?
问题:NextUI模态框内嵌Iframe高度自适应,由模态框处理滚动
我在NextUI模态框中嵌入了一个Iframe,由于Iframe内的页面高度各不相同,无法为其设置固定高度。当我将高度设为100%时,Iframe仅显示150px高度且出现内部滚动。请问如何设置高度,让Iframe无滚动,由设置了scrollBehavior:outside的NextUI模态框来处理滚动?
Iframe组件原代码:
const IframeComponent = () => { return <iframe title="wheel" url="XXXX" className="h-full w-full rounded-[30px]" /> } export default IframeComponent
模态框组件原代码:
import { Modal, ModalBody, ModalContent, ModalProps, useDisclosure } from "@nextui-org/react" import Image from "next/image" import { useEffect, useState } from "react" import IframeComponent from "./Iframe" const IframeWrapper = () => { const { isOpen, onOpen, onClose, onOpenChange } = useDisclosure() const [scrollBehavior, _setScrollBehavior] = useState<ModalProps["scrollBehavior"]>("outside") // Open the modal on load. // Does the modal need to open on each load? useEffect(() => { onOpen() }, [onOpen]) return ( <> <Modal isOpen={isOpen} onOpenChange={onOpenChange} size="5xl" placement="center" hideCloseButton={true} radius="lg" scrollBehavior={scrollBehavior} className="w-[90vw]" > <ModalContent> <> <ModalBody className="p-0"> <button onClick={onClose} className="absolute right-4 top-3 select-none appearance-none rounded-full p-2 text-foreground-500 outline-none tap-highlight-transparent data-[focus-visible=true]:z-10 data-[focus-visible=true]:outline-2 data-[focus-visible=true]:outline-offset-2 data-[focus-visible=true]:outline-focus rtl:left-1 rtl:right-[unset] lg:right-10 lg:top-7" > <Image src="/icons/closeModal.svg" alt="close button" width={0} height={0} className="h-8 w-8 lg:h-16 lg:w-16" /> </button> <IframeComponent /> </ModalBody> </> </ModalContent> </Modal> </> ) } export default IframeWrapper
解决方案
要实现Iframe高度自适应内容、禁用内部滚动,让模态框处理滚动,需要从以下几个方面调整:
1. 调整Iframe组件配置
- 修正Iframe的
src属性(原代码误写为url) - 禁用Iframe内部滚动,添加
scrolling="no"属性 - 监听Iframe加载完成事件,动态设置其高度为内容实际高度
修改后的Iframe组件:
import { useEffect, useRef } from "react"; const IframeComponent = () => { const iframeRef = useRef<HTMLIFrameElement>(null); useEffect(() => { const iframe = iframeRef.current; if (!iframe) return; // 监听Iframe加载完成,获取内容高度 const handleLoad = () => { try { // 同源页面直接获取内容高度 const contentHeight = iframe.contentWindow?.document.body.scrollHeight || 0; iframe.style.height = `${contentHeight}px`; } catch (e) { // 跨域页面需子页面配合发送高度数据 window.addEventListener('message', (event) => { if (event.data?.height) { iframe.style.height = `${event.data.height}px`; } }); } }; iframe.addEventListener("load", handleLoad); return () => iframe.removeEventListener("load", handleLoad); }, []); return ( <iframe ref={iframeRef} title="wheel" src="XXXX" className="w-full rounded-[30px]" scrolling="no" style={{ border: "none" }} /> ); }; export default IframeComponent;
2. 调整模态框及ModalBody样式
- 确保ModalBody不设置固定高度,添加
min-h-0类移除默认最小高度限制 - 保持模态框
scrollBehavior="outside"配置,让模态框容器处理滚动
修改后的模态框关键部分:
<Modal isOpen={isOpen} onOpenChange={onOpenChange} size="5xl" placement="center" hideCloseButton={true} radius="lg" scrollBehavior="outside" className="w-[90vw]" > <ModalContent> <> <ModalBody className="p-0 min-h-0"> <button onClick={onClose} className="absolute right-4 top-3 select-none appearance-none rounded-full p-2 text-foreground-500 outline-none tap-highlight-transparent data-[focus-visible=true]:z-10 data-[focus-visible=true]:outline-2 data-[focus-visible=true]:outline-offset-2 data-[focus-visible=true]:outline-focus rtl:left-1 rtl:right-[unset] lg:right-10 lg:top-7" > <Image src="/icons/closeModal.svg" alt="close button" width={0} height={0} className="h-8 w-8 lg:h-16 lg:w-16" /> </button> <IframeComponent /> </ModalBody> </> </ModalContent> </Modal>
3. 跨域场景补充
如果Iframe加载跨域页面,直接获取内容高度会触发安全限制,需要子页面配合发送高度信息:
在子页面代码中添加:
// 页面加载或内容变化时发送高度 const sendHeight = () => { const height = document.body.scrollHeight; window.parent.postMessage({ height }, '*'); // 建议替换*为目标域名提升安全性 }; window.addEventListener('load', sendHeight); // 若内容动态加载,需额外监听内容变化触发sendHeight
内容的提问来源于stack exchange,提问作者Rom-888
相关产品推荐
相关产品推荐

