背景:使用ai根据用户的需求生成应用,使用html+js+tailwind实现。导航页与页面内容分开,页面内容的html通过iframe标签嵌套的导航页中。

问题:如果导航页生成的页面超出浏览器窗口出现滚动条,iframe中内容超出高度也会滚动条。一个页面会出现双滚动条。

目的:iframe不出现滚动条

目前解决方案:使用iframe通信,在子页面onload后,获取子页面内容高度,通知导航页调整iframe标签的height。

导航页:修改iframe高度

function ytGetIframeResize (iframe) {
  window.addEventListener('message', function(e) {
    // 确保消息来自可信源
    if (e.data && e.data.type === 'iframe-resize') {
      iframe.style.height = e.data.height + 'px';
      const style = window.getComputedStyle(iframe.parentElement)
      //   导航页在左侧时,iframe超出部分被隐藏了
      if (style.overflow === 'hidden') {
        iframe.parentElement.style.overflow = 'auto'
      }
    }
  })
}
View Code

 

iframe内嵌页面:页面加载完成后,获取内嵌页面高度

function ytSendPageSize () {function sendHeightToParent(e) {
        ytSendPageSizeBefor()
        let height = Math.max(
            document.body.scrollHeight,
            document.body.offsetHeight,
            document.documentElement.clientHeight,
            document.documentElement.scrollHeight,
            document.documentElement.offsetHeight
        );
        // iframe如果有横向滚动条,需要加上横向滚动条的高度
        if (hasHorizontalScrollbar()) {
            height += 20 
        }
        
        window.parent.postMessage({
            type: 'iframe-resize',
            height: height
        }, '*'); // 生产环境应替换为具体的父页面域名
    }

    function loadPage (e) {
        window.scrollTo(0, 500);   // 生成的页面会通过监听滚动条动态显示内容,通过改变滚动条位置将隐藏的内容显示出来
        setTimeout(()=>{
          sendHeightToParent(e)
          // 如果内容动态加载,可能需要MutationObserver
          const observer = new MutationObserver(sendHeightToParent);
          observer.observe(document.body, {
            attributes: true,
            childList: true,
            subtree: true,
            characterData: true
          });
        }, 300)
    }
    window.addEventListener('load', loadPage);
}

如果内嵌页面出现横向滚动条时,内容高度还有加上滚动条的高度。监听是否有横向滚动条:

function hasHorizontalScrollbar() {
        // 检查html元素
        const html = document.documentElement;
        if (html.scrollWidth > html.clientWidth) return true;
        // 检查body元素
        const body = document.body;
        if (body.scrollWidth > body.clientWidth) return true;
        return false;
    }
View Code

如果内嵌页面出现vh单位时,当iframe高度变化元素会根据iframe高度撑高导致变型。将vh转为px:

function ytSendPageSizeBefor () {
   // 获取当前视口高度
  const vh = window.innerHeight / 100;
  
  const allElements = document.body.querySelectorAll('*');
  
  allElements.forEach(el => {
    // 内联样式(优先级最高)
    if (el.style.height && el.style.height.includes('vh')) {
      const value = parseFloat(el.style.height);
      el.style.height = `${value * vh}px`;
    }

    // 计算样式(包括 Tailwind 普通类名如 h-screen)
    const computedHeight = getComputedStyle(el).height;
    if (computedHeight.endsWith('vh')) {
      el.style.height = `${parseFloat(computedHeight) * vh}px`;
    }
  });

  // 2. 专门处理 Tailwind 任意值类名(如 h-[70vh])
  const twVhRegex = /h-\[(\d+)vh\]/; // 匹配 h-[70vh] 类名
  document.body.querySelectorAll('[class*="h-["]').forEach(el => {
    const classList = el.classList;
    
    classList.forEach(className => {
      const match = className.match(twVhRegex);
      if (match) {
        classList.remove(className)
        const vhValue = parseFloat(match[1]);
        el.style.height = `${vhValue * vh}px`;
      }
    });
  });
}
View Code

 

posted on 2025-08-19 13:45  wxx17513  阅读(28)  评论(0)    收藏  举报