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).