Say I have a custom element. It consists of two parts, a button to open and toggle a menu and the menu itself. I want to position the menu directly below the button (position: absolute
), but the button's height can be different depending on the theme. How do I find out the button's height before the first render?
Simplified example:
import { render, html } from 'lit-html';
class Dropdown extends HTMLElement {
constructor() {
super();
this.root = this.attachShadow({ mode: "open" });
this.update();
}
get template() {
return html`
<style>
button {
height: 30px;
}
#dropdown-wrapper {
position: relative;
display: inline-block;
}
#dropdown-menu {
position: absolute;
top: ${dynamicButtonHeight}px;
left: 0;
}
</style>
<div id="dropdown-wrapper">
<button type="button">Dropdown</button>
<div id="dropdown-menu">
<slot></slot>
</div>
</div>
`;
}
update() {
render(this.template, this.root, { eventContext: this });
}
}
As you can see in the example, I want to know the button's height on the initial render and fill the dynamicButtonHeight
variable somehow. In this example, it's 30px, but this could be any number really. The same applies for the width, in case I want to align the menu to the right.
I know that I could render the markup initially and get a reference to the button using this.root.querySelector("button").offsetHeight
and re-render afterwards. Although this would be efficient thanks to lit-html, I feel like this is dirty and breaks in certain use cases.
Any other ideas?
How do I find out the button's height before the first render?
You can't because the rendering engine sets the height
There is another potential issue
Any CSS change can re-render your button
The (not so new) ResizeObserver notifies you of those changes
so inside a connectedCallback() you could do:
this.observer = new ResizeObserver(entries=>{
// check whether you need to (re)set stuff here
});
this.observer.observe(this)
Note (this had me baffled the first 15 minutes) that the element you inject in the page immediatly triggers the ResizeObserver
ResizeObserver has been in Chrome for some years now. All evergreen browsers now support it.