Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[css-sizing] Auto-resize iframes based on content #1771

tabatkins opened this issue Aug 31, 2017 · 58 comments

[css-sizing] Auto-resize iframes based on content #1771

tabatkins opened this issue Aug 31, 2017 · 58 comments


Copy link

In, Craig Francis said:

Just re-raising the suggestion of allowing an iframe or textarea to increase its height based on its content.

Mats Palmgren suggested that I raise this issue again, as Firefox is unlikely to implement it unless the CSSWG agrees to spec it.

For iframes, this feature would allow easy and secure (isolated) embedding of third party content without issues relating to scroll bars (i.e. needing custom JavaScript to ask the parent page, via postMessage, to change the iframe height).

For textrareas, this is just a convenience feature, as trying to get JavaScript to do this is tricky (e.g. the browser can automatically add/remove scroll bars, which can throw off the calculations).

When we discussed this last time (after the @seamless attribute on the <iframe> was removed from the WHATWG spec), it was suggested that we used:

textrarea {
    height: max-content;

In the case of the iframe, the child page would need to send a HTTP header (e.g. Expose-Height-Cross-Origin: 1), so it does not leak information about that website (e.g. if the user is logged in).

PS: This has been discussed in a number of times before, the earliest one I've found is 16 years old:

And I've written up some notes about this feature, which includes the suggestion of using it for element height animation (e.g. disclosure widgets):

Copy link

tomhodgins commented Aug 31, 2017

I don't understand why “expand to fit scrollHeight” hasn't been the default behaviour for <textarea> all along. In a lot of my demos where I want to add this sort of functionality I achieve this effect by somehow running the following 2 lines of JavaScript from the context of an element: = 'inherit' = element.scrollHeight + 'px'

I've written a little JavaScript function that can help me apply an auto-height or auto-width to elements that match CSS selectors here that uses this same logic:

Mixin Demo:

Another Auto-Height demo:

Another Auto-Width demo:

As for auto-height <iframe>, I believe I've seen this happen on iOS before, but I'm not sure I could dig up the CSS. I'll see if I can recreate it :D

Copy link

With iOS, this is their default behaviour for iframes... they call it frame flattening.

Copy link

eeeps commented Aug 31, 2017

What happens when

  p { font-size: 100px; }
  @media (min-height: 50px) { p { font-size: 1px; } }

gets iframed into

<style>iframe { height: max-content; }</style>
<iframe src="is-this-a-circular-dependency.html"></iframe>


UPDATE: I see this has already been asked and that there are already some proposed answers.

Copy link

As a website developer, I'd be happy for the iframe to simply increase in size (so the scroll bars weren't required), and to not bother scaling back again.

Which works quite well with the name max-content.

Copy link

This could be a win for accessibility (and monetization/conversion) for inserted adverts, where e.g. the user has specified a larger minimum text size than the default, but at the expense of page reflows as each ad slot gets populated.

Copy link

The Working Group just discussed Auto resizing of iframes and textarea based on content size, and agreed to the following resolutions:

  • RESOLVED: Add textarea sizing to Sizing L4
The full IRC log of that discussion <gregwhitworth> Topic: Auto resizing of iframes and textarea based on content size
<astearns> github:
<gregwhitworth> TabAtkins: there have been many requests for textarea and iframes resize on content
<gregwhitworth> TabAtkins: we talked it over and thought, yeah probably ok
<gregwhitworth> TabAtkins: we started experimenting with this
<gregwhitworth> TabAtkins: figure our some mechanism content based sizing for textarea and iframes
<gregwhitworth> TabAtkins: we learned some issues impl seamless with iframes due to COR leaking information
<gregwhitworth> TabAtkins: we suspect we'd walk up the frame tree until we hit a fixed size to resolve the mqs
<gregwhitworth> TabAtkins: Someone from Moz impl this
<gregwhitworth> dbaron: we got the spec to say that's how media queries work, but seamless was removed
<gregwhitworth> dbaron: we have code for it - but it's not necessarily something you can write up in a spec
<gregwhitworth> dbaron: you need to figure out how to spec it
<gregwhitworth> iank_: what type of interesting things
<gregwhitworth> dbaron: I'd need to look, like it tries to do layout
<fantasai> s/do layout/do layout, and then tries again/
<gregwhitworth> rossen: we used to have a technology that would allow you to do layout based on then content size and we killed it
<smfr> q+
<gregwhitworth> Rossen: performance becomes a concern for those
<tantek> The iframe use-case for me is known width (set by container), auto (preferably auto-expanding) height
<gregwhitworth> Rossen: when you consider extensions they try to size the box, and it's shrink to fit it becomes very bad for perf
<gregwhitworth> Rossen: Our experimentation for this suggests it was bad, but maybe you'll find something
<gregwhitworth> TabAtkins: they're both pretty separate features anyways
<Rossen> q?
<gregwhitworth> TabAtkins: are we ok experimenting in this space
<gregwhitworth> TabAtkins: the textarea would go into sizing 4
<gregwhitworth> smfr: we've had the auto sizing of the iframe even COR
<gregwhitworth> smfr: it makes your frame layout outside in rather than inside out
<gregwhitworth> smfr: we've had quite a few media query bugs
<gregwhitworth> smfr: we ran into media query cycles
<gregwhitworth> TabAtkins: that means that you weren't doing media queries the way we defined
<smfr> q-
<gregwhitworth> smfr: it does bring about nasty things in the code
<gregwhitworth> TabAtkins: how is this different from regular layout
<gregwhitworth> smfr: you can avoid laying out the iframe, if you have to you have to dirty the other nodes
<gregwhitworth> TabAtkins: ok, let's talk about this later
<gregwhitworth> dbaron: I think the media query problems you had were due to doing what authors weren't expecting
<gregwhitworth> TabAtkins: this would be opt in
<gregwhitworth> tantek: how do you trigger behavior in iOS
<gregwhitworth> smfr: you always get it
<gregwhitworth> smfr: users don't experience nested scrollers, we always wanted page scrolling to win so you don't get trapped
<gregwhitworth> tantek: width is expected and height is auto
<gregwhitworth> smfr: yes
<gregwhitworth> Rossen: ok, so - it seems that Google wants to experiment with this - Apple has it and wants to remove it
<gregwhitworth> Rossen: do you want a resolution
<gregwhitworth> TabAtkins: The textarea one is simple enough to go into sizing 4
<gregwhitworth> TabAtkins: the iframe one can go in WICG
<gregwhitworth> Rossen: any objections to adding textareas to CSS Sizing L3
<gregwhitworth> fantasai: yes
<gregwhitworth> TabAtkins: I said 4
<gregwhitworth> Rossen: Ok, L4
<gregwhitworth> fantasai: ok - I'm ok with that
<gregwhitworth> Rossen: Changes to sizing L4
<fantasai> fantasai: we can add a note for L3
<gregwhitworth> Resolved: Add textarea sizing to Sizing L4
<fantasai> RESOLVED: Add textarea sizing to Sizing L4
<gregwhitworth> *discuss whether to do in WICG*
<gregwhitworth> TabAtkins to spin up a WICG regarding auto sizing of iframes
<tantek> I'm a bit surprised that we're not even putting into a WD something that's been shipping in iOS for 10 years

Copy link

tantek commented Nov 7, 2017

The auto-resizing (specifically height) of iframes is a highly desirable feature for authors.

I have been using this feature for quite some time on my event posts, e.g.:

I use an iframe to embed an unknown number of RSVPs generated by an external service, and it is quite handy (e.g. on iOS Safari) for that iframe of RSVPs to auto-grow (in height) as more RSVPs come in.

I'd very much like to see iframe auto-sizing added to Sizing L4 as well.

Copy link

@tantek I'm in favor, but that requires addressing the security concerns at the very least; textarea doesn't have that consideration. If we work it out in the same timeframe as the rest of the features and get implementer backing, I'd be happy to have it in L4.

Copy link

Nadya678 commented Jan 7, 2018

I vote for max-content for <textarea/> and other elements but against for not sameorigin <iframe/> and <object/>. If <iframe/> is not sameorigin, the value should be resolved to auto.

Reason: the autosizing of textarea should be implemented, and also horizontal equivalent for width for <input/> but without security problems.

BTW. <iframe/> is old technology and this attribute doesn't have to be implemented on it.

Copy link

fantasai commented Feb 6, 2018

Moving textarea and input discussion to #2141 ; this one will remain open for iframe, since its security implications are more complex.

@fantasai fantasai changed the title [css-sizing] Auto-resize iframes and textarea based on content [css-sizing] Auto-resize iframes based on content Feb 6, 2018
Copy link

fantasai commented Mar 4, 2018

Note: The CSSWG resolved to accept this for textarea and text input fields in #2141.

Copy link

Malvoz commented Oct 16, 2018

In the case of the iframe, the child page would need to send a HTTP header (e.g. Expose-Height-Cross-Origin: 1), so it does not leak information about that website

From whatwg/html#555:

For cross-origin I suppose the embeddee would need to opt-in somehow (e.g. meta tag), to not expose new information cross-origin.

Now that we have Feature Policy, I think that's the way to go about that. Similarly, there is a proposal to expose bounds cross-origin.

Copy link

Since an <iframe> src can be set to an SVG, would max-content work for SVGs as well?

This is actually great that something might actually happen, because it means we could finally:

  1. Have HTML partials!
  2. Emulate container queries!

Copy link

indolering commented Mar 26, 2019

I don't buy the security argument, who cares if someone knows that you are logged in somewhere? When couldn't you infer the same information using timing attacks to see if a resource has been cached? And any half-competent sysadmin worried about that kind of leak should be blocking frame embedding entirely.

Copy link

prlbr commented Apr 30, 2019

Could it be implemented for same-origin iframes please even if not all security concerns are sorted out for the foreign-origin scenario yet?

@astearns astearns added this to the EUR VF2F-2021-04-06 milestone Apr 2, 2021
Copy link

The CSS Working Group just discussed [css-sizing] Auto-resize iframes based on content.

The full IRC log of that discussion <astearns> topic: [css-sizing] Auto-resize iframes based on content
<TabAtkins> github:
<fantasai> TabAtkins: Fairly old issue, #1171
<fantasai> TabAtkins: originated in HTML in the form of 'seamless' attribute on iframes
<fantasai> TabAtkins: meant to allow isolating parts of a page, but still lay them out as if in the page
<fantasai> TabAtkins: there were a bunch of issues, dropped from HTML
<fantasai> TabAtkins: core ideas still requested by people, in various variants
<fantasai> TabAtkins: We believe there's a useful and safe set of resizing behavior that we could expose now
<fantasai> TabAtkins: that would solve some of the use cases
<fantasai> TabAtkins: Core idea is that just the resizing portion of seamless is value
<fantasai> TabAtkins: But security issues around being able to tell the size of 3rd-party content
<fantasai> TabAtkins: bare minimum, different sizes of content depending on logged in or not
<fantasai> TabAtkins: So should only be allowed to take size of 3rd-party content if it wants to allow that
<fantasai> TabAtkins: Another problem, if 3rd-party page can trigger resizing without consent of containing page, can create problems as well
<fantasai> TabAtkins: So 2-way agreement on sizing
<fantasai> TabAtkins: First, outer page needs to opt into resizing based on iframe content
<fantasai> TabAtkins: Suggestion is to use new 'resize' value in 'allow' attribute
<fantasai> TabAtkins: Then for 3rd-party content, there's a window.resizeTo() method which is a no-op in iframes
<fantasai> TabAtkins: Inner page can request such sizes
<fantasai> TabAtkins: using this API
<fantasai> TabAtkins: Whenever inner page wants a resize, triggers an event on iframe which bubbles up
<fantasai> TabAtkins: if not prevetnDefault, then the iframe changes it's size
<fantasai> TabAtkins: if cancelled, doesn't change size
<fantasai> TabAtkins: This allows control over layout behavior across the page
<fantasai> astearns: Possible scripts using resizeTo() and relying on the fact that it does nothing?
<fantasai> TabAtkins: it's a no-op currently, so don't think so
<fantasai> TabAtkins: ... [ missed ]
<fantasai> astearns: Making page decide to allow event or not, already in place due to opt-in to resize behavior
<fantasai> cbiesinger: Nothing sounds like CSS thing
<fantasai> TabAtkins: kinda sorta
<florian> q+ to ask at which level of sizing this works. natural size of the iframe? something else?
<fantasai> TabAtkins: it's a cross-spec thing, does interact with CSS by adjusting intrinsic size of iframe
<gregwhitworth> q+
<fantasai> TabAtkins: gets into issue of same-origin content
<TabAtkins> fantasai: YOu wanted a 2-way handshake for security
<TabAtkins> fantasai: resizeTo() gives you 2-way for page consenting
<TabAtkins> fantasai: If that page is already firing resizeTo() and expecting it not to ahve sec implications
<TabAtkins> fantasai: I don't think paying attention to resizeTo() would break the framed page...
<TabAtkins> fantasai: But if they're asking for it and it's currently not changing size, the outer page probably isn't expecting a problem.
<gregwhitworth> q--
<gregwhitworth> ack gregwhitworth
<TabAtkins> fantasai: [clarifying] the issue isn't an attack due to sizing, it's a possibly unexpected info leak from the frame'd page, leaking the size it wants to size to
<astearns> ack fantasai
<fantasai> florian: currently, calling resizeTo() doesn't leak information
<fantasai> TabAtkins: could check if stuff in iframes do this currently...
<fantasai> fremy: It's not about stuff currently in iframes, but a page could put *anything* into an iframe
<fantasai> fremy: which would leak information from that page, which was not intended to be in an iframe
<fantasai> florian: resizeTo() doesn't have an effect on pages that are loaded into a window with multiple tabs
<fantasai> florian: for exactly this reason: it would leak information about that page to other pages in the same window
<astearns> ack florian
<Zakim> florian, you wanted to ask at which level of sizing this works. natural size of the iframe? something else?
<fantasai> florian: opening up this leak through iframes is similarly bad (worse maybe)
<iank_> another path would be an additional dictionary argument to resizeTo, e.g. window.resizeTo(100, 100, {something: true});
<fantasai> TabAtkins: Yeah, OK, we need to think about that more. Maybe needs a new API
<fantasai> +1 iank_
<fantasai> florian: In the case where resize does work, thing it affects is the natural size, right?
<fantasai> TabAtkins: Yes. Right now iframes have natural size of 300x150, and this would change that
<fantasai> TabAtkins: totally controllable, it's the weakest size input possible
<fantasai> fremy: [missed]
<fantasai> TabAtkins: currently iframes do not have an aspect ratio
<fantasai> TabAtkins: Ability to infer an aspect ratio is an interesting possibility
<jensimmo_> q+
<fantasai> florian: As long as we're there, should we specify min size and max size separately
<fremy> s/[missed]/do iframes have an aspect-ratio applied to that intrinsic size?
<fantasai> TabAtkins: Interesting. Not unreasonable to consider.
<emilio> q+
<astearns> ack jensimmo_
<fremy> q+
<fantasai> jensimmo_: Curious about use cases
<fantasai> jensimmo_: All I can think of is what ad networks will do, and I don't like those thoughts.
<fantasai> TabAtkins: There's another proposal for 1st-party content, which addresses more use cases
<fantasai> TabAtkins: but even within 3rd-party stuff, currently they do this resizing already, just with postMessage back and forth
<fantasai> TabAtkins: This would standardize that
<fantasai> TabAtkins: There's also things like Disqus, which does such special-case postMessage things
<fantasai> TabAtkins: which is complicated and no standardized way to handle across multiple systems
<smfr> q+
<fantasai> TabAtkins: YouTube player, e.g., might want to do this. CodePen might want to ask for sizes on its examples. Anything that wants to embed, has a reasonable use case for wanting to request a particular size and have it potentially honored by containing page
<fantasai> jensimmo_: If goal is to reduce jankiness of ad network...
<fantasai> TabAtkins: that is one goal, but not all of it!
<leaverou_> need to drop off briefly for another call, but I'm very supportive of this, and I hope we can find a way to implement it in a privacy and security preserving way.
<astearns> ack emilio
<fantasai> emilio: How do you react to resize in parent page when using the API?
<fantasai> emilio: User shrinks the page, need to somehow coordinate between both. No auto size, only fixed intrinsic size
<fantasai> TabAtkins: I don't think there's a reasonable direct analog to block auto-sizing ..
<fantasai> emilio: I guess at that point... You don't really need JS on the parent page to get auto height
<fantasai> emilio: If you require JS on the parent page then it's not great
<fantasai> emilio: So inner page can send resizeTo() whenever it gets Resize event
<fantasai> emilio: and then containing page doesn't need to do anything ...
<fantasai> emilio: [missed]
<fantasai> TabAtkins: possible this makes it easy enough that it's a concern
<fantasai> emilio: resize event ... your own resize event
<fantasai> TabAtkins: I suspect that's something that would show up fairly quickly
<fantasai> emilio: It only consumes CPU, not while:true. I send a message, it resizes me, sends a message back. Code keeps working, just uses a ton of CPU
<fantasai> emilio: It's a bug in the page, but.
<fantasai> TabAtkins: no-op loops can't happen because if the iframe's resizeTo() doesn't change its size, won't get an event because size didn't change.
<fantasai> TabAtkins: Either it'll grow or shrink infinitely, or will jiggle, which should be noticeable
<fantasai> emilio: Concerned about e.g. floating point issues, and rounding errors
<fantasai> emilio: I've seen that kind of stuff happen
<iank_> we also already have the "jiggle" problem today with frame by frame resize-observers.
<fantasai> if not causing change in size, then shouldn't cause a problem
<fantasai> fremy: can't put a breakpoint in the main page to figure it out because no JS
<fantasai> fremy: Already have these kinds of bugs today
<astearns> ack fremy
<fantasai> smfr: The HTML5 event loop spec is very specific about when resize steps happen
<fantasai> smfr: when we spec this, we need to spec it in terms of that event loop spec
<fantasai> smfr: Nobody mentioned resizeobserver yet
<fantasai> smfr: it's designed to avoid infinite recursion
<fantasai> smfr: we might need something here with nested iframes, so don't get into crazy infinite resizing
<dholbert> q+
<fantasai> TabAtkins: yes, want to handle events in descending order like resizeobserver does
<fantasai> TabAtkins: need some thought to ensure not creating bad cross-tree resizing behaior
<fantasai> TabAtkins: Not too concerned about page vs iframe vibration, but much worse if grandparent grandchild interactions cause problem, because then nobody knows what's going on
<fantasai> fremy: Main question here was, I guess point of allow attribute is to allow resize
<fantasai> fremy: External page wants to allow iframe to resize
<fantasai> fremy: Not sure I understand point of resize function
<dholbert> q-
<fantasai> fremy: why not some CSS value that allows resizing by containing page
<fantasai> fremy: reason I think about htat is that resize takes 2 arguments, width and height.
<fantasai> fremy: not that interesting to change intrinsic width of iframe
<gregwhitworth> +1 to fremy
<fantasai> fremy: why not say that "I'm fine with my scrollHeight to be reported to the containing page"
<fantasai> iank_: scrollHeight isn't always what you want
<fantasai> fremy: could be something smarter, max-content maybe
<astearns> q?
<fantasai> TabAtkins: Second part of proposal also, about same-origin content and no-JS solution
<fantasai> smfr: Other point, iframe calls resizeTo() and has to provide a size. What size should it provide? does it doe getBoundingClientRect() on the body or what?
<fantasai> smfr: Is there some convenient way to get the height of the content?
<fantasai> TabAtkins: For 1st-party content, making it easy. But for 3rd-party content wanted to be more explicit
<fantasai> TabAtkins: But maybe we can reduce that restriction
<fantasai> TabAtkins: 2nd part of proposal is about same-origin content
<fantasai> TabAtkins: right now, minimum solution still requires some JS on the framed page (not containing page)
<fantasai> TabAtkins: but for same-origin content, there's a certain degree of implicit trust we can rely on
<fantasai> TabAtkins: and might not require auditing
<fantasai> TabAtkins: for this, I propose that on a 1st-party iframe, or something that's srcdoc
<fantasai> emilio: srcdoc is not ?
<fantasai> emilio: data URIs are
<fantasai> TabAtkins: sorry, I'm thinking about sandbox
<gregwhitworth> q+
<fantasai> TabAtkins: In my original proposal, I had a new property that could be set on the root element to set the requested intrinsic size for each axis (auto | <length>)
<emilio> q+
<fantasai> TabAtkins: page could opt into ? via 'from-element' keyword, providing fallback length
<fantasai> TabAtkins: fantasai later suggested the page could just set an explicit width/height on the HTML element
<fantasai> TabAtkins: Possibly we don't need to mint a new property, can just take from the root element
<fantasai> TabAtkins: if that's problematic from existing, maybe mint something new
<fantasai> TabAtkins: but either way, that'll allow getting the size without JS
<fantasai> TabAtkins: Just set allow=resize, and inner page does whatever it needs to do
<fantasai> TabAtkins: and those sizes automatically communicate back and forth
<fantasai> TabAtkins: acts like an element, no JS required
<fantasai> fremy: that only works in 1D, right? you can't do both dimensions
<fantasai> fremy: then you wouldn't get the resize
<fantasai> fremy: if you get width + height, wouldn't know you need more space
<fantasai> TabAtkins: If you set both to auto, you'll need to rely on outer page to set your width...
<fantasai> fremy: ah, ok, make sense
<fantasai> iank_: I don't think that width/height on HTML will work, because people do set an explicit width on HTML and use e.g. auto margins to center
<fantasai> iank_: HTML is not the root, bit of disconnect
<fantasai> iank_: likely for auto behavior, might want something like scrollWidth/scrollHeight as was discussed
<fantasai> iank_: There's a little bit of danger here
<fremy> +1 to scrollWidth/scrollHeight (adjusted if necessary)
<fantasai> iank_: you might get content that, if you have a fixed-position content that rises to ICB, and has height 120%, could create an infinitely-growing iframe that way?
<fantasai> iank_: I'm not too concerned about that
<fantasai> TabAtkins: Yeah, need to think about loop detection...
<fantasai> fremy: we can set a threshold, if you fire too many resize events in a certain amount of time don't allow it or whateer
<fantasai> iank_: That might block some valid use cases. E.g. comment expansion might want to animate growing
<gregwhitworth> resizeObserver has the same error handling
<astearns> ack gregwhitworth
<fantasai> gregwhitworth: Effectively what you just outlined is something we wanted at Salesforce. All over the web ppl using Salesforce but not aware of it.
<fantasai> gregwhitworth: would like to see ???
<fantasai> gregwhitworth: enable this auto behavior for cross-origin
<fantasai> gregwhitworth: if a grid with min/max content, how can I lay out my content and pass back my height
<astearns> s/???/network headers/
<fantasai> gregwhitworth: I can work it out in JS, but want it automatic
<fantasai> TabAtkins: Reason restricted right now is trying to be cautious
<fantasai> gregwhitworth: we could write blog posts about how to do it, but would rather not
<fantasai> TabAtkins: I would want to have more security eyes on it
<fantasai> gregwhitworth: ...
<fantasai> emilio: There is some kind of precedent for this, loading a doc and sizing it intrinsically, which is SVG
<fantasai> emilio: Even if the SVG is not an actual image, if you have an object tag with SVG source, that's actually a document that's ...
<fantasai> emilio: in FF and Chrome at least, that size is intrinsic to SVG's viewbox
<fantasai> emilio: it would be good to figure out if there's something that we need to learn from that or not
<fantasai> emilio: that's probably legacy behavior
<fantasai> emilio: While we were doing ??
<fantasai> emilio: I just wanted to mention that precedent
<fantasai> emilio: I think those can run script, even if SVG
<dlibby> s/??/site isolation/
<fantasai> TabAtkins: A few people in thread mentioned OBJECT
<fantasai> TabAtkins: If currently allows that behavior and think it's OK, then maybe can allow it
<fantasai> TabAtkins: I haven't thought about it yet
<astearns> ack emilio
<astearns> ack fantasai
<TabAtkins> fantasai: on the topic of 3rd party sizing info without JS, I think i tmakes sense to allow
<TabAtkins> fantasai: If both the container and the inner page have explicitly allowed for it
<TabAtkins> fantasai: That indicates trust between the two
<TabAtkins> fantasai: For doing it declaratively, Ian's pointa bout width/height on root not being what we want makes sense
<TabAtkins> fantasai: Tab mentioned setting a property giving the behavior explicitly
<TabAtkins> fantasai: I don't think that's a CSS property, it's more of a security handshake
<gregwhitworth> +1 fantasai
<dholbert> q+
<TabAtkins> fantasai: So maybe an attribute on <html> that opts the iframe'd page into the behavior
<TabAtkins> fantasai: And would let you specify which size you want (scroll height, border-box height, etc)
<fantasai> fantasai: I think the size shouldn't be specified in HTML, should be in CSS; but allowing this should be an HTML attribute
<fantasai> dholbert: Should any page on the internet be able to get that info?
<fantasai> dholbert: maybe same-origin addresses it
<fantasai> dholbert: don't want to allow inadvertent stealing of info from the page
<fantasai> TabAtkins: right, which was why I initially wanted to disallow it
<fantasai> TabAtkins: and fantasai was talking about explicit opt-in
<fantasai> TabAtkins: I think there's some kind of iframing options setting?
<fantasai> iank_: There's ??? HTTP Header which restricts which origins you can be embedded in. Most banks etc. use that.
<fantasai> TabAtkins: requiring that, reasonable thing to start with
<fantasai> iank_: would need to set Access-control: allow-origin or whatever
<fantasai> astearns: Sounds like you got some good feedback, something to work on
<fantasai> TabAtkins: plan is that parts of this that relevant to CSS would go to contain spec
<fantasai> TabAtkins: and sizing spec
<fantasai> TabAtkins: to talk about natural size being controllable this way
<fantasai> TabAtkins: if we do have a new property... probably in sizing? maybe contain?
<fantasai> TabAtkins: rest will be pursued in HTMLWG
<fantasai> astearns: Should CSS part depend on the HTML part being accepted?
<fantasai> TabAtkins: sure
<myles> q+
<astearns> ack dholbert
<astearns> ack myles
<fantasai> myles: This entire discussion about how / technical considerations. Not about whether to do it all.
<fantasai> myles: Want to make sure that it's not a foregone conclusion that we should do this.
<fantasai> TabAtkins: Decent part of this was sussing out whether there's interest in doing this
<fantasai> TabAtkins: seems people are interested
<fantasai> TabAtkins: I suspect discussion in HTMLWG will be more contentious
<fantasai> TabAtkins: OK to object over there :)
<fantasai> astearns: but feel free to object over here also, if you think it's a terrible idea!
<fantasai> TabAtkins: We don't have any major internal partners clamoring for this, it's an old issue that's a frequent author requested, and we found a way to address an important part of it
<TabAtkins> <br dur=12min>
<fantasai> <br duration=12min>

Copy link

@jensimmons Because you had strong concerns against this. Let me note again that there are use cases besides the ad frameworks one.

The company I work for has different websites based on different server software stacks. Though all of them share specific widgets on special occasions. These widgets are surved from a general internal domain and embedded via iframes. We are currently using the postMessage() method mentioned by several people here in this thread for resizing the iframes to avoid the scrollbars to be shown.

So therefore I'd also welcome this feature. Regarding security, as discussed already, it needs to be ensured that both sides express trust in each other.


Copy link

Here's a popular example, to support my point that I think it would overall increase security of the web to make this possible:

GitHub recommends embedded Gists into other websites using a <script> tag.


If we look at what that script does, e.g., we see that all it does is use document.write() to add a CSS styleheet and output HTML with the Gist.
There is no reason this would have to need a <script> tag, other than that if embedding worked through an <iframe>, there would be no easy way for GitHub to resize it based on the Gist size (not without telling embedders to add JS to their page that communicates through postMessage(), which is too much to ask for). So instead, they go with a simple <script> tag.

What does this mean for security? That script can execute any JS in the context of the page and has full control of the DOM. Gists are user content, and that user content is escaped by the GitHub backend and put into the string passed to document.write(). If there is any bug in that escaping logic, a malicious user could craft a Gist that doesn't escape properly and injects arbitrary JS into any page embedding the Gist. And if you get access to someone's GitHub account, you can change Gists that are already embedded somewhere (e.g. it's the most common method to embed code snippets in Medium blog posts).

I think this is a huge security flaw "forced" by the shortcomings of the platform atm.

Now imagine if GitHub could simply use <iframe>s. They would be sandboxed and the JS could get compromised as much as you want - it could never affect the parent page (besides growing in size, which is easy to control with CSS from the outside, even with a style tag on the snippet that GitHub would recommend).

Copy link

Regarding "use cases" - Consider all 3rd party content, like user comments (disqus), videos, maps, tweets, facebook feeds, calendars, gists, ads, etc... it would be much safer if they were in an <iframe>, using their own isolated process (ref spectre), and did not involve the host website including an unsafe/dangerous 3rd party <script> (which grants far too much access).

I should also note that before Safari 13 on iOS, iframes were re-sized automatically (to avoid the scroll bar), with none of these security considerations.

@astearns astearns moved this from Layout to Math in EUR July 27 2021 vFTF Meeting Jul 24, 2021
@astearns astearns removed this from the EUR VF2F-2021-04-06 milestone Jul 24, 2021
Copy link

domenic commented Sep 2, 2021

Heya, @chrishtr asked me to take a look at the proposal here to give my thoughts. Based on #1771 (comment) and some subsequent ones here is what comes to mind:

  • Using resizeTo(), instead of e.g. a HTTP header, is a nice trick and should make this more usable for people.

  • It seems like there are two opt-ins on the outer side: first, you have to set allow="resize", and second, you have to actually use the from-element keyword. I don't know if we need both of these. I would probably cut the allow="resize" since the CSS from-element seems nice and versatile.

  • The dance where the parent is allowed to cancel the event seems potentially tricky to implement and could cause slowness, for out-of-process iframes. You would need to send an IPC to the parent frame to fire the resize event, which would then send an IPC to the child frame telling it the result, before any resizing actually happens. It seems doable, but maybe worth considering whether or not running a full JS function here is really needed. The alternative is basically trusting any iframe that you set contain-intrinsic-size: from-element on, plus you could impose declarative constraints (e.g. max-width/max-height).

  • However, I'll note that window.resizeTo() is already async (test). So there's at least some precedent for resizes not taking effect synchronously. It just might be bad for users if resizes are slower than they need to be.

  • +1 to the promise return value not making too much sense, because the resize only had an effect if the outer page uses from-element.

  • This whole feature needs to not work for situations like fenced frames or portals where we also censor postMessage(). That seems fine.

  • I would not auto-inject into srcdoc; that seems strange.

  • +1 for strong event loop/ResizeObserver integration at the spec level. I don't think this should be too hard.

  • I can't quite tell from the minutes but it seemed like people might be saying there's precedent for not requiring an embedee opt-in, and thus we should consider not requiring it for this feature? That'd be a very bad cross-origin information leak so please don't do that.

I hope this helps, and would look forward to working on this feature with you all!

Copy link

LB-- commented Sep 3, 2021

It's been briefly mentioned earlier in the thread, but being able to support this without any scripting at all would also be great. It would allow treating an iframe as if it were just an ordinary block element in the page, complete with dynamic resizing just based on CSS alone. In theory it could also perform better as no JavaScript handshake would be necessary.

In fact, since JavaScript can already resize a page as desired, I'm not sure why separate new communication methods are needed if a scriptless method is available: the page in the iframe could just resize itself and the parent would not need to differentiate between a resize caused by CSS only or a resize caused by JavaScript.

I think the talk of using a header to opt-in from the embedee side was specifically intended to support the noscript scenario.

Copy link


It's been briefly mentioned earlier in the thread, but being able to support this without any scripting at all would also be great.

This would be ideal -- if an iframe could be treated like a type of inline block content that just resizes based on vertical (and/or horizontal?) overflow (and depending on whatever security measures are needed to whitelist the iframe). A script could therefore just change the CSS property to set resizing behavior.

Copy link

domenic commented Nov 23, 2021

Hi folks,

@tabatkins, @chrishtr, and I spent some time working on this offline. We ended up with the explainer at . Summary:

<iframe style="contain-intrinsic-size: from-element 500px 500px"

<!-- In iframe.html --->
<html requestedwidth="480" requestedheight="320">

We did manage to come up with a solution that doesn't require JavaScript in the simplest cases, where the iframe knows specific pixel values for the width and height it requests. But for dynamic resize-to-content, it's quite tricky, as discussed in our section "But what about auto-resizing?". (The basic problem is how it can cause infinite resize loops.) So the initial proposal would require JavaScript to hook up a ResizeObserver or similar and manipulate document.documentElement.requestedWidth and requestedHeight, like in this example.

Feedback is welcome, either on that repository if you want to have a more focused discussion on individual aspects of the proposal, or here if you'd prefer that.

Copy link

Agenda+ to propose adding the from-element syntax and requestedwidth/requestedheight attributes.

Notes on from-element:

  • It should (of course) apply to iframes
  • Should it apply to object and embed? SVG embedded in these already have an intrinsic sizing capability similar to the proposed iframe thing.
  • Should it apply to other replaced types such as image and video?

I would propose it applies to all replaced elements which have a communicated intrinsic sizing, but I may be missing cases where this is not desirable.

Notes on requestedwidth / requsetedheight:

  • As noted in the explainer, this could also be a CSS property, or even a javascript method. We could discuss tradeoffs.

Copy link

it's easy for this to cause infinite resize loops, where the changing viewport size causes an changing requested size, which causes a changing viewport size, etc.

Can we apply a few iterations of resizing until the size 'settles'? And if it doesn't settle, log an error to help developers debug and give up until the next window resize event?

Copy link

I like the use of attributes, so the width/height can be provided to the iframe as soon as the HTML is received... out of interest, would there be any benefit to using a single attribute, like requestedsize="300 400", in the same way that the srcset attribute contains multiple values (maybe string parsing would be an unnecessary complication, and future values like "300 auto-on-load" might be a bit weird)?

I like the auto-on-load suggestion, and I'm happy to wait for that to be introduced in the future (this proposal would help the main issue today, to include 3rd party content, which nearly always uses JS anyway; delaying that for everyone to agree on how an auto value should work, probably isn't a good idea).

Thank you for writing this up, and providing examples to show how it can be used.

Copy link

annevk commented Nov 25, 2021

I don't think we should add these to embed and object. Those elements are poorly defined at the moment and we need to change how they work to address various leaks. Adding more complexity to them does not seem warranted.

Copy link

domenic commented Nov 29, 2021

maybe string parsing would be an unnecessary complication, and future values like "300 auto-on-load" might be a bit weird

That was my instinct, plus the fact that most of the precedents in HTML are to use separate attributes.

I don't think we should add these to embed and object

I agree with this in general, although @chrishtr pointed out that SVG-in-<object> has auto-sizing behavior already, which makes this worth thinking about.

Copy link

annevk commented Nov 29, 2021

The way that sizing works is not interoperable and has some cross-origin leakage problems, in particular if you navigate the <object> element to and from SVG resources. (See; whatwg/html#7037 is also relevant here. whatwg/fetch might also have some relevant discussion in a PR somewhere.)

Copy link

The CSS Working Group just discussed [css-sizing] Auto-resize iframes based on content, and agreed to the following:

  • RESOLVED: Use HTML mechanism (either attributes or meta) to express the intrinsic size of the child
  • RESOLVED: Add `contain-intrinsic-size: from-element` with a note that it needs further discussion on the name
The full IRC log of that discussion <emilio> topic: [css-sizing] Auto-resize iframes based on content
<astearns> github:
<fantasai> scribe+
<emilio> Domenic: This is a widely-desired feature for devs, I've worked with tab, iank and chrishtr on how a solution could look like
<emilio> ... I've got the explainer (^) but basically content inside iframe requests content size, and the page can use css to decide to honor it
<emilio> ... which resizes the iframe element and in turn the viewport in the inner iframe and so on
<emilio> ... you can restrict it to honor only height / width, or using max/min-width to constraint
<emilio> ... there's also some discussion to try avoiding shifts
<emilio> ... what devs really want is auto-sizing
<emilio> ... and the iframe will auto-resize its content
<emilio> ... we were not able to figure out how to best do this
<emilio> ... biggest problem is resize loops
<emilio> ... like 100vh inside the iframe which would change the element size, which would change the viewport, etc...
<chrishtr> q+
<emilio> ... so MVP is just allowing devs to request exact sizes
<emilio> ... there's also some ideas about snapshotting stuff at the load event
<emilio> ... or special layout modes that make vh behave differently to avoid the loops
<emilio> ... but the discussions about it are on the issue tracker
<emilio> ... there's some discussion of the alternatives and so on
<astearns> would be unhappy with modes that change how things behave
<bkardell_> is there something here we could borrow from how image sizing works maybe?
<emilio> ... I think from the CSSWG we should get some expertise... Should the sizes be communicated via css? should we use contain-intrinsic-size to opt-into this from the iframe?
<emilio> q?
<astearns> ack chrishtr
<emilio> q+
<bkardell_> like, you could set px values or fit-like things?
<emilio> chrishtr: it seems the main thing we should focus on is the mechanism for communicating the intrinsic sizing
<bkardell_> feels like those two options would cover most kinds of cases I can think of
<emilio> ... so the specific proposal is that it'd be a keyword on the `contain-intrinsic-size` property
<Domenic> `contain-intrinsic-size: from-element 500px 500px`where 500px 500px is the initial/fallback size
<emilio> ... I think that one makes sense
<emilio> ... The other bit is whether on the child we should use a css property vs. attributes
<smfr> q+
<emilio> ... and whether it could be `contain-intrinsic-size` or other thing
<astearns> ack emilio
<fantasai> emilio: Wanted to ask why is 'contain-intrinsic-size' the right property for this
<fantasai> emilio: I thought it mostly only worked on contained stuff
<fantasai> emilio: It communicates a size, but...
<fantasai> iank_: It could work a lot of different ways, but contain-intrinsic-size allows ...
<fantasai> iank_: It's the mechanism at the moment that we have for changing the intrinsic size of an element
<fantasai> iank_: Did you have something else in mind?
<fantasai> emilio: I wasn't aware of that overriding replaced element intrinsic size already
<fantasai> iank_: If you set c-i-s: 100px 100px on an image element, it will override the image's size
<florian> q?
<florian> q+
<fantasai> iank_: we could explore a different mechanism, but as a first shot seems reasonable
<fantasai> emilio: With this proposal, would you need to use 'contain: size' on the iframe?
<florian> q-
<fantasai> iank_: I believe ???
<fantasai> s/???/that is true/
<fantasai> iank_: I may be wrong
<Domenic> Interesting, I did not know that. I kind of assumed replaced elements were size-contained by default.
<fantasai> iank_: Other nice thing about this is that it provides a fallback size
<fantasai> iank_: if you can't get that size, it'll back
<fantasai> emilio: OK
<chrishtr> (we could also define replaced elements to be implicitly contain:size)
<fantasai> emilio: Didn't want to use for something totally unrelated
<smfr> q-
<fantasai> <fantasai> Domenic, that might be a reasonable thing to do
<fantasai> <fantasai> Maybe should be considered
<Domenic> to track updating the explainer
<Domenic> Oh cool, thanks fantasai
<emilio> chrishtr: probably not right? Otherwise you break intrinsic-sizing of images by default
<fantasai> astearns: Borrow something from image sizing, e.g. setting px values or fit-like things?
<bkardell_> yes right iank_
<florian> q+
<fantasai> iank_: like to get letterboxing?
<emilio> iank_: we've discussed this previously
<emilio> ... there's an argument to be made about object-fit applying to iframes
<emilio> ... but I think that's orthogonal to this issue
<emilio> Domenic: It's orthogonal in the sense that the size would be used as the viewport but on the parent document it'd be letterboxed
<emilio> iank_: There's another issue about an iframe not wanting to change size but not wanting to overflow either but it's orthogonal to this
<emilio> Domenic: I think it layers well with this proposal
<astearns> ack florian
<emilio> astearns: is there an issue already on object-fit for iframes? if not may be worth filing one bkardell_
<emilio> florian: so contain-intrinsic-size is conditional on contain:size but afaict that's a no-op on `<iframe>`
<emilio> ... should we add it by default on a UA sheet?
<Domenic> +1 if possible
<emilio> iank_: I'd have to try the existing behavior
<emilio> florian: Spec says contain-intrinsic-size applies to elements with size containment so it doesn't kick in automatically
<emilio> iank_: right, so adding it to iframes in the ua sheet might make stuff suddenly kick in
<emilio> ... I need to refresh my memory on how iframe intrinsic sizing works
<chrishtr> q+
<emilio> ... because if we make contain:size by default on element we might stop respecting width/height
<emilio> florian: I suspect it would work but there might be a reason it doesn't
<emilio> iank_: makes sense
<astearns> ack chrishtr
<emilio> chrishtr: so sounds like contain-intrinsic-size is fine but need to make sure ergonomics are fine
<emilio> ... what about the child document sizes?
<dholbert> We'd need to be sure this is well-defined for <iframe style="contain:initial"> (presumably then contain-intrinsic-size would be ignored?)
<emilio> Domenic: currently from the outside you can do this by combining max-width / height with 'contain-intrinsic-size: from-element'
<emilio> ... with the current proposal that's not really possible from the child iframe
<dholbert> (Even in the presence of UA stylesheet `contain:size` defaults for iframe)
<emilio> ... It'd be nice to allow doing this for the child, and I feel CSS has a lot more tools
<emilio> iank_: the initial reaction I had about css vs. attribute is that this only applies to one element (the `<html>` element)
<emilio> ... there are already some things we use the CSS parser for on attributes
<emilio> ... the min() / max() functions can't have 'auto'
<emilio> ... so we'd need separate syntax
<emilio> smfr: is this about the iframe content expressing its desired for sizing on a given range?
<emilio> iank_: yeah, so the iframe would say "size me as 500x500" but the additional layer on top would be something like...
<emilio> ... this is more interesting on the snapshotting approach where it'd read the offsetHeight/offsetWidth of the document
<emilio> ... and the additional layer would be to limit that size
<emilio> ... so not go below 100px or above 1000px
<Domenic> The additional layer on top would be something like: "if the parent is currently set to anything between 400px-600px height, then don't resize me. Otherwise, resize me to 432px".
<emilio> ... not so useful when we set a single size but it's more useful when setting multiple
<Domenic> E.g. `min-requested-height: 400px; max-requested-height: 600px; if-outside-requested-size-range: 432px;`???
<emilio> ... so you'd send a message to the parent and so on...
<emilio> smfr: seems similar to viewport meta tag / @Viewport for iframe
<emilio> smfr: it's nice if these features could work with JS disabled
<emilio> iank_: These things are only needed if we go for the one-shot behavior
<emilio> smfr: would that be default or an opt-in?
<bkardell_> are there popular libraries using some postMessage concept to negotiate this already somehow
<Domenic> But you could also do `requestedheight="432 if not in 400 to 600"` or some other new microsyntax... or even just three separate HTML attributes.
<emilio> iank_: it'd be an opt-in, you'd do a 'requested-intrinsic-size: auto'
<emilio> ... can't auto-opt-in
<Domenic> bkardell_: yes, see
<fantasai> scribe-
<emilio> ... so on the load event that'd read the scroll width/height and send it
<chrishtr> Yes there are libraries, but it requires postMessage stuff and JS on both ends, and there is also the issue of both frames having to use the same protocol
<emilio> ... so if you want to add floor/ceil to that how would that work?
<emilio> as an html attribute?
<fantasai> Domenic, I feel like it's unlikely to have "432 unless I'm between 400 and 600", seems more likely to request "make me between 400 and 600, I prefer 432"
<fantasai> scribe+
<fantasai> emilio: [missed]
<emilio> emilio: has a meta tag been considered? it may be more flexible than attributes
<fantasai> Domenic: If we did end up creating a microsyntax, might be more natural that way
<Domenic> fantasai: yes, that is exactly right, I phrased it very confusingly. Thanks.
<emilio> iank_: we'd need to find a new CSS syntax for this anyway because min()/max()/clamp() doesn't support auto, so if we go to the CSS property we'd need to invent a new syntax anyways
<emilio> iank_: so for this use-case we'd need to define a new syntax for a one-line attribute or property
<emilio> Domenic: I was thinking multiple css properties like `min-`/`max-`/`preferred-`...
<TabAtkins> scribe-
<TabAtkins> I'm fine with element-specific CSS properties when warranted, fwiw...
<emilio> ... though that may be another argument for less properties than apply to one element
<lea> Is supporting auto in min()/max()/clamp() out of the question? That would be very useful in general
<emilio> fantasai: tantek was wondering whether we'd want to implement a new variant of @Viewport for this
<emilio> iank_ and fantasai: [explain @Viewport]
<tantek> found it
<futhark> +q
<emilio> iank_: could you nest @Viewport inside @media?
<emilio> ... that could be bad
<emilio> smfr: we deprecated @Viewport because making viewport depending on CSS loading was pretty bad behavior
<tantek> point being, the problem/use-case is *very* similar to what @Viewport was trying to solve, so there's at least some syntax there that could be re-used
<astearns> ack futhark
<emilio> Domenic: You need to allow adjusting it but I agree that meta / attributes get the info to the browser as soon as possible
<emilio> futhark: you could nest @Viewport inside @media but it'd cause a circular dependencies so it was specified to resolve against the initial viewport when you collected viewport rules
<emilio> astearns: it seems there's more consensus towards expressing these sizes on HTML rather than CSS
<tantek> seems reasonable to experiment with attributes in HTML
<emilio> smfr: either attribute or meta tag right?
<emilio> astearns: yeah
<emilio> Domenic: can we read the temperature on that?
<emilio> ... seems like leaning towards meta-tag if we need a micro-syntax
<emilio> ... but I don't know how complicated that would end up being
<emilio> astearns: I expect we won't have a strong opinion on it...
<fantasai> emilio: Attributes can trigger restyling, but not if they don't trigger changes in styls
<fantasai> smfr: but you'd have to write code to detect that ...
<emilio> Domenic: can't you write rules against the meta?
<emilio> iank_: I think we can leave the attributes vs. meta as an open question for now
<TabAtkins> Due to the particulars of HTML, it's not very targetable; it shows up in the <head> but you want to style things in <body>
<TabAtkins> But that is an accidental restriction.
<emilio> RESOLVED: Use HTML mechanism (either attributes or meta) to express the intrinsic size of the child
<emilio> emilio: I'd expect contain-intrinsic-size:from-element to do stuff on other replaced elements
<emilio> ... like undoing what `contain:size` does
<emilio> astearns: putting it into an ED doesn't mean we're fully behind on it
<emilio> fantasai: we can add some placeholder-name on it
<emilio> chrishtr: what about putting from-element in an ED committing that we're not shipping it yet
<emilio> fantasai: yeah... please do from-iframe? :-)
<emilio> Domenic: what about `<object>` / `<embed>`?
<emilio> chrishtr: we can put from-element as a placeholder and bikeshed with the editors
<fantasai> Domenic, intentionally, it's bad and needs renaming
<tantek> the object element is more interesting because you're also styling the fallback content inside
<emilio> RESOLVED: Add `contain-intrinsic-size: from-element` with a note that it needs further discussion on the name
<Domenic> Not sure if I'm serious about object/embed, I kinda want those elements to die in a fire and so starving them of new features might be my preference...
<Domenic> Thanks all!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
No open projects

No branches or pull requests