Skip to content

Canvas: Widgets have no Height

The second example is an attempt to build a simple flexbox layout and show that here you should use canvas and not a widget component.

The layout should have an area with a fixed height and another area below that takes up the remaining height.

What are we learning here?

  • The container of a Widget component do not an explicit height

We will create again a new HTML template, a new widget component and a new application:

src/demo/apps/canvas-vs-widget-layout/content.html

1
2
3
4
5
6
7
<h2>JS Widget Unusable (No Height)</h2>
<div class="h-100 d-flex flex-column">
   <div class="p-2 flex-grow-0 border border-success">A small header</div>
   <div class="p-2 flex-grow-1 border border-success">
      A bigger section which should take all the rest of the space
   </div>
</div>

src/demo/apps/canvas-vs-widget-layout/content.js

1
2
3
4
5
6
7
8
import { Widget } from "@codecoupler/cc-ui";
import template from "./content.html";
export default class extends Widget {
   async start() {
      this.element.css("padding", "20px");
      this.element.html(template);
   }
}

src/demo/apps/canvas-vs-widget-layout/index.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import { Application } from "@codecoupler/cc-ui";
import ChildComponent from "./content.js";
export default class extends Application {
   static defaults = {
      "@codecoupler": {
         panel: {
            panelSize: "640 400",
            headerTitle: "Test Canvas Features"
         }
      }
   };
   async start() {
      await this.stage.load(ChildComponent);
   }
}

We will load the in our system.js file (just replacing again):

src/system.js

1
2
3
4
5
6
7
import { Component } from "@codecoupler/cc-ui";
import TestApp from "./demo/apps/canvas-vs-widget-layout";
export default class extends Component {
  async boot() {
    await this.stage.load(TestApp);
  }
}

If you look into the HTML structure you would expect a layout like this:

┌─────────────────────────┐
│┌───────────────────────┐│
││ A small section       ││
│├───────────────────────┤│
││                       ││
││ A bigger section      ││
││ which should take all ││
││ the rest of the space ││
││                       ││
│└───────────────────────┘│
└─────────────────────────┘

But you get this:

┌─────────────────────────┐
│┌───────────────────────┐│
││ A small section       ││
│├───────────────────────┤│
││ A small section       ││
│└───────────────────────┘│
│                         │
│                         │
│                         │
│                         │
└─────────────────────────┘

This is because the parent element of the widget component has been stretched to full height, but with the property min-height:100%. The height is set to auto. And there is a good reason for that. E.g. if you want to scroll the content or use other libraries that rely on the height of the element automatically adjusting to the content of the widget.

There are some workarounds for this but the most important point is: A Widget is not the right component to create full height and width layout structures. For this case you should use the Canvas component.

Nevertheless, we don't want to deprive you of the possible workarounds for the problem from the second example:

  • Set the parent element to height:100%. For example with: this.element.css({ height: "100%" });
  • Replace the parent element with the root element of the template (which property height is already set to 100%) using this.replaceElement(template); instead of this.element.html(template);