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

tyg4sfes  于 2023-04-13  发布在  Flink
关注(0)|答案(6)|浏览(170)

我有一个使用CSS的iframe边框。当页面调整大小时,边框有时会在Chrome中消失,在Safari中改变大小(在Firefox中没有问题)

是否有已知的解决方法?

const html = `
<style>
body { 
  background: #DDD;
}
</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: 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>

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

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

请注意,这似乎与iframe中的背景颜色有关。如果我删除背景颜色,则在Chrome中问题消失(尽管不是Safari)

const html = `
<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: 1px solid black;
  width: 100%;
}
<p>Size the window and watch the right border</p>
<!-- src set from JavaScript because offsite iframes are often banned -->
<div>
  <iframe></iframe>
</div>
qnzebej0

qnzebej01#

我仍然在Chrome上看到这个问题(不是在Safari上)。它似乎是边框可视化的一个bug(仍然)。
一个选择是将border的宽度改为0,并设置为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%;
}
<p>Size the window and watch the right border</p>
<!-- src set from JavaScript because offsite iframes are often banned -->
<div>
  <iframe></iframe>
</div>
v8wbuo2f

v8wbuo2f2#

overflow: hidden;box-sizing: border-box;添加一个 Package 器div对我来说很有用。

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;
}
<p>Size the window and watch the right border</p>
<!-- src set from JavaScript because offsite iframes are often banned -->
<div>
  <div class="iframe-wrapper">
     <iframe></iframe>
  </div>
</div>
ymdaylpp

ymdaylpp3#

这是抗锯齿问题。
Chrome通常避免在浮动像素上渲染,以避免抗锯齿。它会尝试移动和调整大小到下一个圆形像素。
在这种情况下,它会切断你的边界,而不是让它泄漏到iframe之外。
你可以通过移动iframe或者通过floating-pixels来调整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>

但是请注意,这段代码只处理resize事件,如果你的iframe可以从其他事件(例如DOM manips,CSS等)调整大小,那么你可能需要使用一个 Package 器元素,在上面应用width:100%,并从ResizeObserver的回调中更改iframe的宽度:

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%;
}
<p>Size the window and watch the right border</p>
<!-- src set from JavaScript because offsite iframes are often banned -->
<div>
<div class="iframe-wrapper">
  <iframe></iframe>
</div>
</div>

也就是说,在眨眼只有现在...

qltillow

qltillow4#

上面的答案对我来说都不起作用。起作用的只是将iframe的宽度和高度设置为固定值,而不是百分比:
而不是:

a iframe {
    width: 100%;
    height: 100%;
    border: 1px solid #9af4b4;
}

将其更改为这样,因为iframe无论如何都在固定的widht容器中:

a iframe {
    width: 150px;
    height: 150px;
    border: 1px solid #9af4b4;
}
pxyaymoc

pxyaymoc5#

.ifrmoutr{
  border: 1px solid red;
  width:100%;
  overflow:hidden;
}
.ifrmoutr iframe{
  width:100%;
}
<div class="row">
  <div class="col-lg-12">
    <div class="ifrmoutr">
      <iframe></iframe>
    </div>
  </div>
  </div>
t30tvxxf

t30tvxxf6#

对于任何在2022年寻找答案的人来说,上述方法都不起作用,这是唯一对我有效的方法。
将以下CSS添加到iframe

clip-path: polygon(1% 1%, 99% 1%, 99% 99%, 1% 99%);

相关问题