检测用户启动的元素大小调整(与文档流大小调整不同)
Detecting user-initiated element resizing (as distinct from document flow resizing)
我想要一个 iframe,它可以水平显示所有可用的 space,并自动垂直调整自身大小以适应其内容(包括内容更改或 window 调整大小),但也可以通过用户,使用 CSS 属性 resize: both
。目的是嵌入一个设计,它默认填充可用 space,但也让用户看到它在不同屏幕尺寸下的工作方式。
iframe 同源,所以不存在安全问题——父 window 可以用 iframe.contentDocument
为所欲为。
自动调整 iframe 大小以适应其内容非常简单:
<iframe srcdoc="<h1>The quick brown fox jumps over the lazy doggerel."
style="width:calc(100% - 2px);border:1px solid black"
onload="
recalculate = () => {
this.style.height = this.contentDocument.documentElement.offsetHeight + 'px';
}
new ResizeObserver(recalculate).observe(this.contentDocument.documentElement);
recalculate();
"></iframe>
(哇,那个 HTML 语法高亮真的在那里崩溃了!另外,这里没有合适的“片段”,因为 CSP 似乎破坏了 contentDocument
访问。)
制作用户可调整大小的 iframe 非常简单:
<iframe srcdoc="<h1>The quick brown fox jumps over the lazy doggerel."
style="resize:both"></iframe>
… 但是这些技术不能很好地结合起来,因为随着用户调整大小与由于 window 尺寸变化等原因调整大小的方式相同,所以只要用户调整它的大小, 自动高度代码启动并忽略他们刚刚指定的高度。
因此,如果用户手动调整 iframe 的大小,我希望我的自动调整大小断开 ResizeObserver。
有没有什么方法可以区分由于用户操作(通过角落控制调整 iframe 大小)和由于环境变化(iframe 内的内容变化,或没有 iframe 的布局变化,包括视口)引起的调整大小调整大小)?
当您手动调整大小时,element.style.{width, height}
设置完毕。因此,一种解决方案是自动调整大小不使用这些属性,而是以其他方式设置宽度和高度,以便您可以区分值。
对于 width
,这很简单,因为自动调整大小仅设置 height
:如果设置了 width
(或者,如果您设置了 calc(100% - 2px)
这样的值, 设置为其他值), 断开自动调整大小。
求身高?这更难,但我想到了两种技巧:
- 在单独的样式表中设置高度(这样根本就不会设置
element.style.height
),并继续更新该样式元素的文本。
- 使用
height: var(--height)
,设置--height
为实际值。这样 element.style.height
不会改变,除非用户调整大小。我推荐这种技术,因为它更容易推理,而且我怀疑它可能会更快一点(尽管我根本没有测试过)。
<style>
iframe {
width: calc(100% - 2px);
border: 1px solid black;
resize: both;
}
</style>
<iframe srcdoc="<h1>The quick brown fox jumps over the lazy doggerel."
style="height:var(--height)"
onload="
recalculate = () => {
// (var(--height) could just as easily be shifted to the stylesheet,
// but I’m demonstrating a point here in how it can be done.)
if (this.style.width || this.style.height !== 'var(--height)') {
// User resizing has occurred.
if (observer) {
observer.disconnect();
}
return;
}
this.style.setProperty('--height', this.contentDocument.documentElement.offsetHeight + 'px');
}
var observer = window.ResizeObserver && new ResizeObserver(recalculate);
if (observer) {
observer.observe(this.contentDocument.documentElement);
}
recalculate();
"></iframe>
我想要一个 iframe,它可以水平显示所有可用的 space,并自动垂直调整自身大小以适应其内容(包括内容更改或 window 调整大小),但也可以通过用户,使用 CSS 属性 resize: both
。目的是嵌入一个设计,它默认填充可用 space,但也让用户看到它在不同屏幕尺寸下的工作方式。
iframe 同源,所以不存在安全问题——父 window 可以用 iframe.contentDocument
为所欲为。
自动调整 iframe 大小以适应其内容非常简单:
<iframe srcdoc="<h1>The quick brown fox jumps over the lazy doggerel."
style="width:calc(100% - 2px);border:1px solid black"
onload="
recalculate = () => {
this.style.height = this.contentDocument.documentElement.offsetHeight + 'px';
}
new ResizeObserver(recalculate).observe(this.contentDocument.documentElement);
recalculate();
"></iframe>
(哇,那个 HTML 语法高亮真的在那里崩溃了!另外,这里没有合适的“片段”,因为 CSP 似乎破坏了 contentDocument
访问。)
制作用户可调整大小的 iframe 非常简单:
<iframe srcdoc="<h1>The quick brown fox jumps over the lazy doggerel."
style="resize:both"></iframe>
… 但是这些技术不能很好地结合起来,因为随着用户调整大小与由于 window 尺寸变化等原因调整大小的方式相同,所以只要用户调整它的大小, 自动高度代码启动并忽略他们刚刚指定的高度。
因此,如果用户手动调整 iframe 的大小,我希望我的自动调整大小断开 ResizeObserver。
有没有什么方法可以区分由于用户操作(通过角落控制调整 iframe 大小)和由于环境变化(iframe 内的内容变化,或没有 iframe 的布局变化,包括视口)引起的调整大小调整大小)?
当您手动调整大小时,element.style.{width, height}
设置完毕。因此,一种解决方案是自动调整大小不使用这些属性,而是以其他方式设置宽度和高度,以便您可以区分值。
对于 width
,这很简单,因为自动调整大小仅设置 height
:如果设置了 width
(或者,如果您设置了 calc(100% - 2px)
这样的值, 设置为其他值), 断开自动调整大小。
求身高?这更难,但我想到了两种技巧:
- 在单独的样式表中设置高度(这样根本就不会设置
element.style.height
),并继续更新该样式元素的文本。 - 使用
height: var(--height)
,设置--height
为实际值。这样element.style.height
不会改变,除非用户调整大小。我推荐这种技术,因为它更容易推理,而且我怀疑它可能会更快一点(尽管我根本没有测试过)。
<style>
iframe {
width: calc(100% - 2px);
border: 1px solid black;
resize: both;
}
</style>
<iframe srcdoc="<h1>The quick brown fox jumps over the lazy doggerel."
style="height:var(--height)"
onload="
recalculate = () => {
// (var(--height) could just as easily be shifted to the stylesheet,
// but I’m demonstrating a point here in how it can be done.)
if (this.style.width || this.style.height !== 'var(--height)') {
// User resizing has occurred.
if (observer) {
observer.disconnect();
}
return;
}
this.style.setProperty('--height', this.contentDocument.documentElement.offsetHeight + 'px');
}
var observer = window.ResizeObserver && new ResizeObserver(recalculate);
if (observer) {
observer.observe(this.contentDocument.documentElement);
}
recalculate();
"></iframe>