高度为0的iframe元素也能导致页面溢出滚动🧐?

发现问题

前段时间在迭代公司后台项目时,发现某几个页面滚动溢出了:

如图紫色方框中页面底部出现空白,且fixed定位的按钮也很乱。

顺手解决

打开控制台发现在 body 处就已经溢出了,当时没有多想这是什么原因造成的,自以为后台项目应该就是这些页面 table 列表展示,给 body 加个溢出样式就好了,不会影响整体页面展示。

less 复制代码
body {
	overflow: hidden;
}

于是我顺手就给这个bug"修复"了。

后面测试时,测试同学还专门问我什么时候把这个问题给修了,挺好的👍,因为这个问题之前就有,只是因为 "后台项目而已,又不是不能用" 没有提给开发同学🤣。

又有问题

但是没想到,这两天因为我加的这个overflow: hidden给另外的前端需求给搞出bug了。

原来和我当初迭代并行开发的一个 feature 做了一个页面预览功能,整个页面是要去溢出滚动的,但是因为是并行开发,当时没被我加上这个hidden,后面测试同学可能也没注意,两个 feature 都合并了之后出现了 bug,预览页面没法滚动了!😥

由于项目紧急,我当时修的这个 bug 也不影响使用,就把我修的 bug 作为新 bug 给修回去了😓。

问题排查

没办法,我就要去找找为啥页面会滚动了。

我先是认为部分元素的高度影响了页面,但挨个元素审查了一遍后并没有发现什么异常。

然后我发现项目刷新后并没有直接溢出滚动,且只有在部分页面向下滑动时才会出现这个现象,出现该现象后切换到其他页面,滚动不会消失。那会不会是某些页面给添加了某粒"老鼠屎",后面又没有去干掉它呢,于是我又去仔细看了第一次产生溢出的页面的dom,发现这里添加了一个iframe元素。

切换页面后,这个iframe一直还在页面上。看来罪魁祸首就是他了!

在代码里查了一下,发现这个iframe是用来进行文件下载时引入的。

js 复制代码
/**
 * Use iframe to download file.
 * Usage:
 *  downloadFile('/abc.xml');
 */
import Modal from 'common/modal';

const iframe = document.createElement('iframe');
iframe.setAttribute('frameborder', 0);
iframe.setAttribute('style', 'width:0;height:0;opacity:0;');
document.getElementsByTagName('body')[0].appendChild(iframe);

iframe.onload = function() {
  let text;
  try {
    const body = (
      (iframe.contentWindow && iframe.contentWindow.document) ||
      iframe.contentDocument.document ||
      iframe.contentDocument
    ).getElementsByTagName('body');
    text = body.textContent || body.innerText;
  } catch (e) {
    window.location.href = iframe.src;
  }
  let error;
  try {
    const json = JSON.parse(text);
    error = json.error || json.message || json;
  } catch (e) {
    error = text;
  }
  if (text) {
    Modal.error({ content: error, title: '文件下载失败!' });
  }
};

export default function downloadFile(url) {
  iframe.src = url;
}

应该是为了避免频繁创建和销毁 dom,所以在第一次引入下载时创建iframe元素,后面不再进行销毁了。

最终解决

于是我试着给这个iframe添加了display: none,页面滚动溢出问题果然解决了!

但是明明这个方法里给iframe设置了height: 0,为什么还会把页面给搞溢出呢🫤?

查阅文章《iframe 高度设置为0时还有占位_iframe占位》后发现:

iframe是一个内联元素,默认是跟baseline对齐的,iframe后边有个看不见、摸不着的行内空白节点,空白节点占据着高度,iframe与空白节点的基线对齐,导致了div被撑开,从而出现滚动条,查看空白节点捣鬼。

解决方案:

  1. 设置 iframe 的 vertical-align: top;
  2. 设置父 div 的 font-size: 0,从而影响空白节点的 line-height 是0,从而不占据高度;
  3. 改变 iframe 的内联元素性质,改为块级元素,display: block。

我又查阅了一下关于使用iframe进行文件下载的文章,发现基本都是设置iframe的样式为display: none

便采用display: none来解决了因为iframe空白占位导致的页面异常溢出滚动的问题🫡。

相关推荐
马玉霞1 分钟前
设置 某个文件git不提交,但是我不想写在 .gitignore 里面
前端·github
RichardLai884 分钟前
[Flutter 进阶] - Flutter 与原生通讯 - 你了解多少?
android·前端·flutter
玲小珑5 分钟前
Auto.js 入门指南(十三)数据存储与本地持久化
android·前端
Spirited_Away6 分钟前
什么你还不会用navigation来管理导航?
前端·javascript·面试
Hilaku8 分钟前
为什么 React 18 的 concurrent 模式没人敢开?真不是我怂,是它太怪
前端·javascript·react.js
梨子同志16 分钟前
防抖(debounce)
前端·javascript
Mintopia19 分钟前
Three.js 自定义相机脚本:让镜头舞动起来
前端·javascript·three.js
Mintopia22 分钟前
骨骼动画:让数字角色跳出生命之舞
前端·javascript·计算机图形学
迷你二鹏22 分钟前
前端之JavaScript
前端·javascript