[proposal] Same-document same-context windows, declaratively via HTML <window> element

#1

There could be some use cases that become simple to achieve if we could have browser windows that rendered as part of the same document with the same JS context.

F.e., imagine the following opens a new window:

<body><!-- this renders in the parent window -->
  <div>Take a look at the content in the window.</div>
  <window opened width="800" height="600">
    <!-- this renders in a child window that pops open -->
    <div>I am content in another window, but in the same DOM and JS context.</div>
  </window>
</body>

Then in the same context, we can easily work with it:

const d = document.querySelector('window > div')
d.innerHTML = 'I am in another window and my content was edited from the parent window context.'

Not only would multi-window applications become super simple to orchestrate…

… It would also solve the complexity of rendering Custom Elements across windows (see this StackOverflow question).

It is (or at least seems) very difficult to make multi-window applications using the same (or subsets of) the custom elements that are in the parent Window.

With this feature, we can do the following with Custom Elements:

<script>
  class MyEL extends HTMLElement { /* ... */ }
  customElements.define('my-element', MyEL)
</script>
<body>
  <!-- my-el works in the parent window -->
  <my-el>Take a look at the content in the window.</my-el>
  <window opened width="800" height="600">
    <!-- my-el also works in the child window -->
    <my-el></my-el>
  </window>
</body>

Because we’re using the same DOM, note that CSS styling also applies in the child window.

With the current API (using window.open) styles need to be manually copied over or linked in the child window. Custom Elements need to be re-defined in the child window, event needs to be wired up via postMessage, etc. It’s a lot of pain and easy to do it wrong and leaves a big surface area for bugs to infest.

The new <window> feature would solve all of that. F.e., here’s a complete example, including CSS:

<style>
  my-el { background: pink }
</style>
<script>
  class MyEL extends HTMLElement { /* ... */ }
  customElements.define('my-element', MyEL)
</script>
<body>
  <!-- my-el works in the parent window, has a pink background -->
  <my-el>Take a look at the content in the window.</my-el>
  <window opened width="800" height="600">
    <!-- my-el also works in the child window, also has a pink background -->
    <my-el>I am content in another window, but in the same DOM and JS context.</my-el>
  </window>
</body>
#2

This would allow even more awesome things to be possible, f.e. imagine ShadowDOM distribution, where a component can distribute children into another window:

<!-- windowable-sidebar-layout has a <window> element in its shadow root -->
<windowable-sidebar-layout windowed>
  <menu slot="header">...</menu>
  <main slot="main">...</main>
  <aside slot="sidebar">...</aside>
</windowable-sidebar-layout>

which would distribute the <aside> element into the child window. To tell the web component to render the sidebar back in the main window, the user would just remove the windowed attribute.

#3

Basically, <window>s would open OS windows that are simply just render targets for the HTML engine. Portions from the main window’s DOM are simply painted inside the child window, nothing more. There’s no new DOM or JS context anywhere, there’s no new origin, it’s all the same context as far as user code goes.

#4

Oh! And events would be simple! You could click on an element, and catch the bubbling event anywhere in the main window’s DOM. It’d make multi-window apps super easy!

Example:

<style>
  my-el { background: pink }
</style>

<script>
  class MyEL extends HTMLElement { /* ... */ }
  customElements.define('my-element', MyEL)
</script>

<body>
  <!-- my-el works in the parent window, has a pink background -->
  <my-el>Take a look at the content in the window.</my-el>
  <window opened width="800" height="600">
    <!-- my-el also works in the child window, also has a pink background -->
    <my-el id="foo">I am content in another window, but in the same DOM and JS context.</my-el>
  </window>
</body>

<script>
  // do something when the user clicks on the element in the window!
  const el = document.querySelector('#foo')
  el.addEventListener('click', () => {
    console.log('user clicked inside the window')
  })
</script>

And also, clicking anywhere in the window:

  const win = document.querySelector('#foo')
  win.addEventListener('click', () => {
    console.log('user clicked on the window')
  })

and bubbling:

  document.addEventListener('click', e => {
    if (e.target.id === 'foo') {
      console.log('user clicked inside the window')
    }
  })
#5

I have mixed feelings. I can see the power this brings, but the window element does seem slightly strange. A few questions:

  1. What would happen when the window is closed? Is the element removed from the DOM?
  2. What happens when you add the window element to the DOM, but the browser has popups disabled?
#6

The opened state becomes false. Similar to checked on input elements. Note the opened attribute in the examples.

When the window gets closed, it renders relative to it’s location in the DOM (perhaps a window element is styled with display:content by default).

This leads to concepts like “windowable widgets” that can be popped out into windows, and popped back in, on demand.

It’s going to handle exactly the same as it does with window.open, which may be specific to each browser.

In Chrome, it opens in a new tab unless you specify width and height. Chrome has heuristics for detecting spammy ads. At worse, the blocked pop-up icon will appear in the address bar.

But because the window uses the same DOM and JS Context, that already eliminates a whole class of spam which opens windows with other origins.

In Chrome, a user can disable the pop-up blocking for a specific site if Chrome heuristics are wrong.

PWAs will be more trusted. If a user finds a PWA misbehaving, the user can uninstall it.

Etc

Browsers would have new rules specifically for windows opened from <window>s. F.e., maybe

  • A maximum of 10 can be opened at once, or something
  • When switching to another main window (or tab), perhaps all <window> windows of the previous main window are hidden
  • etc

Yeaaaas.

Imagine for example a tool panel, like those in well-known apps such as Photoshop or Gimp or Blender, and imagine individual sections in the tool bars can be popped into separate windows, dragged between windows, etc.

Gimp has a single-window mode and a multi-window mode that you can toggle, where panels pop in or out of the main window.

These sorts of things would super easy to achieve with this <window> feature.

#7

I updated my above reply, in case you’re reading email or already read it.

#8

By the way, this is somewhat possible to do with React components.

With React, we can use a “portal” (React.createPortal) to render to any arbitrary element, even one from another window.

The thing is, this works well when

  • not also using custom elements, because they then need to be defined in the child window
  • using a CSS-in-JS styling system which applies all styles via style attributes, that way we don’t need to think about how to copy styles over.
  • Using React components that do not rely on event bubbling (because they stop at the window boundary).

But this still involves opening the window manually, and also spins up a new context, and event bubbling would require more hacking, 3rd party libs like jQuery won’t simply work, etc. It’s just plain difficult.

#9

Could you describe the use cases?

What are the advantages of Gimp’s multi-window mode? Could you share a screenshot?

#10

Here’s a video showing Gimp going from multi-window mode to single-window mode: https://www.youtube.com/watch?v=bsZYBMvSNhw.

The use cases of multi-window applications are already discussed in many other places besides here. This thread is about how to make implementation of multi-window apps easier for HTML developers (regardless what for).

Linux Tomboy is an example of a highly-multi-window app:

The reasons for wanting to make multi-window applications aren’t so relevant, I’m only suggesting that there can be an easy way of doing it.

#11

@simevidas Another example is gmail, it can pop chats out into separate windows:

Obviously there’s ways to make it work with current APIs, but something like what I’m suggesting would make it super easy.

#12

I think that describing the use cases is the most important part of a proposal. I’m trying to understand why a web app would need multiple windows.

#13

Not why does a “web app” need windows (they already do by the way). Why does any app need windows.

This simply makes a feature easier to achieve. All the use cases of apps with multiple windows are already in place, and it’d be great to be able to achieve it easily with web tech. (f.e. publishing desktop apps with Electron)

#14

I still don’t understand why a web app wold need multiple windows. If you can explain that, I would appreciate it. Otherwise, I won’t be able to contribute to this discussion anymore.

#15

Hello @simevidas, I posted an example screenshot, above, of a well-known web app with multiple windows.

At work, we are making our 3D editor’s UI panels pop out into separate windows. It’s a web app, written with React and Three.js. It can run in the web, or in Electron as a standalone application.

Making multi-window desktop applications is a valid desire in general, and some devs might choose to make a desktop application using web tech because that generally makes the process easier (except the windowing part can be tricky).

Having an same-document windowing feature would make the dev experience much simpler for certain cases (like popping widgets out into separate windows).

Here are a couple more example use cases:

#16

The way I look at is not “why a web app would need multiple windows”, but “why any app would need multiple windows”. The latter is a question that is already backed by many examples of real-world applications.

Here is my co-worker, with many windows across only a few applications. Multi-windowing is a first-class citizen in his workflow:

The following is a screenshot of a multi-window flow in Gimp (even with multi-window UI turned off). All of Gimp’s dialogs are made with custom windows. In the screenshot, a custom window is opened for saving a file, then a third window is opened for tweaking output parameters before performing the save:

My examples show the generic multi-window need that application developers have, not specific to web technology. Web tech is only one technology, of many, that can be chosen for making applications with. Some technologies have better windowing abilities.

I’m simply suggesting an improvement for existing and valid desires that application developers have, when they choose to make applications with web technology.

#17

@simevidas Here’s some other benefits that multi-windowing can have:

  • A developer who only knows basic HTML and CSS can already make fully-working forms with inputs. Now if they want to stick the forms in a separate window (for whatever reason the application needs windows), they can’t. A simple <window> element could solve the problem.
    • I’ve worked with web designers (HTML/CSS developers with ability to copy/paste jQuery) in design agencies that would simply give up making multi-window applications with the current JS APIs.
  • accessibility: screen readers, search engines, and other devices can easily understand what is happening by reading the HTML/DOM. Content is still reachable even if rendered in another window.

Multi-windowing is already a feature of web applications and applications in general. The goal I have with my suggestion is simply to make the existing possibilities easier to achieve.

#18

Ah, multi monitor. Now I get it. (I only use a laptop, and I never open multiple windows of the same app side by side, so I didn’t think of the possibility of there being multiple monitors.)

From looking at your images, I can see two different scenarios:

  • multiple windows of the same app open on different screens
  • multiple smaller windows of the same app open on the same screen

Regarding the latter scenario, is there really a need for those windows to be actual windows? Can’t they just be elements on the same web page that are styled like windows and have window-like behavior?

#19

In that case, my co-worker (for example) can’t use his OS-level window management.

But it depends on the app needs. A one-time prompt, blocking the underlying app, might make sense in a modal dialog. On the other hand, a UI component that is frequently visited in a separate window could be a different case.

A more complicated example can be a 3D design studio, with many tools. A designer might have multiple monitors, and will want to arrange all the tools in the arrangement that satisfies their workflow. Imagine tools as complicated as Blender or Cinema 4D (which is sort of the type of stuff we’re making, but for a specific industry, and not yet as complicated).