为什么iframe闪烁的CSS边框以及如何修复它?

时间:2017-09-14 10:43:50

标签: css html5 google-chrome iframe safari

我有一个使用CSS的iframe边框。随着页面调整大小,边框有时会在Chrome中消失,并在Safari中更改大小(在Firefox中很好)

enter image description here

是否有已知的解决方法?



const html = `
<style>
body { 
  background: #eee;
}
</style>
<body>
  <div>hello iframe</div>
</body>
`;

const blob = new Blob([html], {type: 'text/html'});
document.querySelector("iframe").src = URL.createObjectURL(blob);
&#13;
div {
  max-width: 90%;
  margin: 0 auto;
}
iframe {
  display: block;
  border: 1px solid black;
  width: 100%;
}
&#13;
<p>Size the window and watch the right border</p>
<!-- src set from JavaScript because offsite iframes are often banned -->
<div>
  <iframe></iframe>
</div>
&#13;
&#13;
&#13;

使用其他元素不会有同样的问题

&#13;
&#13;
div {
  max-width: 90%;
  margin: 1em auto;
}
span, canvas {
  display: block;
  border: 1px solid black;
  width: 100%;
  height: 60px;
  background: #eee;
}
&#13;
<p>no issue with other elements</p>
<div>
  <span></span>
</div>
<div>
  <canvas></canvas>
</div>
&#13;
&#13;
&#13;

请注意,它似乎与iframe中的背景颜色有关。如果我删除背景颜色,Chrome中的问题就会消失(虽然不是Safari)

&#13;
&#13;
const html = `
<body>
  <div>hello iframe</div>
</body>
`;

const blob = new Blob([html], {type: 'text/html'});
document.querySelector("iframe").src = URL.createObjectURL(blob);
&#13;
div {
  max-width: 90%;
  margin: 0 auto;
}
iframe {
  display: block;
  border: 1px solid black;
  width: 100%;
}
&#13;
<p>Size the window and watch the right border</p>
<!-- src set from JavaScript because offsite iframes are often banned -->
<div>
  <iframe></iframe>
</div>
&#13;
&#13;
&#13;

4 个答案:

答案 0 :(得分:1)

red 4red 5red 6red 7red 8red 9red 10green 11green 12green 13green 14green 15green 16green 17blue 18blue 19blue 20blue 21blue 22blue 23blue 24yellow 25yellow 26yellow 27yellow 28yellow 29yellow 30yellow 31
.ifrmoutr{
  border: 1px solid red;
  width:100%;
  overflow:hidden;
}
.ifrmoutr iframe{
  width:100%;
}

答案 1 :(得分:0)

为我添加一个带有command=php -d allow_url_fopen=On ... overflow: hidden;的包装div。

box-sizing: border-box;
const html = `
<style>
body { 
  background: #eee;
}
</style>
<body>
  <div>hello iframe</div>
</body>
`;

const blob = new Blob([html], {type: 'text/html'});
document.querySelector("iframe").src = URL.createObjectURL(blob);
div {
  max-width: 90%;
  margin: 0 auto;
}
.iframe-wrapper {
  border: 1px solid black;
  box-sizing: border-box;
  width: 100%;
  overflow: hidden;
}
iframe {
  display: block;
  width: 100%;
  border: none;
}

答案 2 :(得分:0)

我仍然在Chrome(而不是Safari)上看到该问题。似乎是边界可视化中的一个错误(仍然)。

一个选项可能是将SELECT xxx.commitment_number AS [Commitment Number], Sum(xxx.receipt_amount) AS Amount, xxx.Location_Name AS Child_Location_Name, xxx.Location_Name AS Parent_Location_Name, xxx.JNL_Sales AS ByPassSales, xxx.JNL_COGS AS ByPassCogs, xxx.order_type FROM ( SELECT * FROM master_export_pt AS mept, vw_items AS vi, BypassLocation AS bl, LocalLocation AS ll WHERE mept.item = vi.Item AND mept.location_id = bl.location_id AND bl.location_id = ll.Location_ID) AS xxx LEFT OUTER JOIN LocalLocation AS ll1 ON xxx.parent_location_id = ll1.Location_ID GROUP BY xxx.commitment_number, xxx.Location_Name, ll1.Location_Name, xxx.JNL_Sales, xxx.JNL_COGS, xxx.order_type; 的宽度更改为0,然后设置border。然后,这种效果消失了。我不知道这是否是最好的解决方案(轮廓通常用于突出显示聚焦/活动元素),但它与您所拥有的接近。

这是一个演示,只是进行了更改:

outline
const html = `
<style>
body { 
  background: #eee;
}
</style>
<body>
  <div>hello iframe</div>
</body>
`;

const blob = new Blob([html], {type: 'text/html'});
document.querySelector("iframe").src = URL.createObjectURL(blob);
div {
  max-width: 90%;
  margin: 0 auto;
}
iframe {
  display: block;
  border: 0;
  outline: 1px solid black;
  width: 100%;
}

答案 3 :(得分:0)

这是一个抗锯齿问题。
Chrome通常会避免在浮动像素上进行渲染,以免产生锯齿。它将尝试移动并调整大小到下一个四舍五入的像素。
在这种情况下,它将切断边框,而不是使其泄漏到iframe之外。

您可以通过使用浮动像素移动或调整iframe的大小来强制使用它:

const html = `
<style>
body { 
  background: #DDD;
}
</style>
<body>
  <div>hello iframe</div>
</body>
`;
const iframe = document.querySelector("iframe");
iframe.srcdoc = html;

document.querySelector("input").oninput = function(e) {
  iframe.style.marginLeft = this.value + 'px';
};
div {
  max-width: 90%;
  margin: 0 auto;
}
iframe {
  display: block;
  border: 1px solid black;
  width: 250.5px; /* force a floating pixel width */
  background: red;
}
<p>Edit the range and watch the right border</p>
<input type="range" min="0" max="1" value="0" step="0.01">
<!-- src set from JavaScript because offsite iframes are often banned -->
<div>
  <iframe></iframe>
</div>

我认为您很好地解决了这个问题,因为这绝对不是预期的行为。

由于您要的是一种解决方法,所以这不是一个完美的解决方法,它会在每次调整大小事件时导致两次重排,但应该可以解决该问题...

const html = `
<style>
body { 
  background: #DDD;
}
</style>
<body>
  <div>hello iframe</div>
</body>
`;
const iframe = document.querySelector("iframe");
iframe.srcdoc = html;

addEventListener('resize', resizeFrame, {passive: true});
resizeFrame();

function resizeFrame(_){
  iframe.style.width = null; // reset to 100%
  // force reflow by calling offsetWidth which is already rounded
  iframe.style.width = iframe.offsetWidth + 'px'; 
}
div {
  max-width: 90%;
  margin: 0 auto;
}
iframe {
  display: block;
  border: 1px solid black;
  width: 100%;
  background: red;
}
<p>Size the window and watch the right border</p>
<!-- src set from JavaScript because offsite iframes are often banned -->
<div>
  <iframe></iframe>
</div>

但是请注意,此代码仅处理调整大小的事件,如果您的iframe可以从其他事件(例如DOM操作,CSS等)调整大小,那么您可能希望使用包装器元素,在其上应用{{ 1}},然后通过ResizeObserver的回调更改iframe的宽度:

width:100%
const html = `
<style>
body { 
  background: #DDD;
}
</style>
<body>
  <div>hello iframe</div>
</body>
`;
const iframe = document.querySelector("iframe");
iframe.srcdoc = html;

if(window.ResizeObserver) {
  const observer = new ResizeObserver(entries => {
    iframe.style.width = iframe.parentNode.offsetWidth + 'px';
  });
  observer.observe(iframe.parentNode);
}
else {
  console.log('no support');
}
div {
  max-width: 90%;
  margin: 0 auto;
}
iframe {
  display: block;
  border: 1px solid black;
  width: 100%;
  background: red;
}
.iframe-wrapper {
  max-width: none;
  width: 100%;
}

in Blink only for now ...