Web Components On Fire
This custom element slots a series of site navigation links into two different Shadow DOM structures based
on the browser’s width. If the width is above a given breakpoint, it just shows the links in a row which can be styled
with ::part(navbar)
. Once the window narrows and it crosses the given breakpoint it shows a hamburger menu
and slots the links into a drawer (::part(drawer)
) that slides in from the right side.
The drawer would preferably been built using the <dialog>
element, which conveniently moves itself to
the document’s “top layer,” painting it on top of everything else on the page (with no need for the ever-increasing
z-index
value). Unfortunately, we wanted to have the menu’s hamburger icon morph into a close icon with a
fancy pants animation and this proved impossible with the <dialog>
element. Our approach relies on a
simple position: fixed
element instead.
The menu sets a state
attribute on itself to allow users to style the menu’s light DOM content
according to whether it is slotted into the drawer or the static navbar. Of course, this would be a perfect use for
CustomStateSet
which lets us use selectors like :state(drawer)
, but alas as of writing in June
2024, the browser support is still lacking. As always, MDN has the best information. This
state
attribute is not used for anything internally and is merely a convenience for the user for styling
their content. That’s a good thing because as an attribute it can be changed arbitrarily by other code (although this
has no effect on the element itself).