by Audrey M. Roy Greenfeld | Thu, Feb 6, 2025
I make a lightweight vanilla InlineNav FT with FastHTML, using the HTML nav element and as minimal styling as I can get away with.
from fastcore.utils import * from fasthtml.common import * from fasthtml.jupyter import *
This generates an HTML nav element:
Nav()
Within a nav element, screen readers handle lists best.
nv = Nav( Ul( Li(A("audrey.feldroy.com", href="https://audrey.feldroy.com/")), Li(A("Source", href="https://github.com/audreyfeldroy/audrey.feldroy.com")) )) nv
show(nv)
I often see Jeremy and Isaac simply overriding the existing FTs. I tried that at first, but it didn't feel right to me. Maybe in the future I'll switch to that pattern. Here I'll name them differently.
Mainly I didn't want to have style="display:inline"
twice.
def InLi(*c): return Li(*c, style="display:inline")
Then it felt natural to do one for the parent Ul, but not really necessary. Rather, it felt awkward not to give it a partner element.
def InUl(*c): return Ul(*c, style="list-style:none")
But now it feels awkward to not have an inline version of the main nav element. Hmm.
nv = Nav( InUl( InLi(A("audrey.feldroy.com", href="https://audrey.feldroy.com/")), InLi(A("Source", href="https://github.com/audreyfeldroy/audrey.feldroy.com")) ) ) show(nv)
I guess I could do it this way:
nv = Nav( Ul( InLi(A("audrey.feldroy.com", href="https://audrey.feldroy.com/")), InLi(A("Source", href="https://github.com/audreyfeldroy/audrey.feldroy.com")), style="list-style:none" ) ) show(nv)
Or maybe this way:
def InlineNav(): return Ul( InLi(A("audrey.feldroy.com", href="https://audrey.feldroy.com/")), InLi(A("Source", href="https://github.com/audreyfeldroy/audrey.feldroy.com")), style="list-style:none" ) nv = InlineNav() show(nv)
Let's refactor to pull out the parts that matter:
navlinks = L( ("audrey.feldroy.com", "https://audrey.feldroy.com/"), ("GitHub repo for this site", "https://github.com/audreyfeldroy/audrey.feldroy.com") )
def InLi(linktuple): txt, href = linktuple return Li(A(txt, href=href), style="display:inline")
navlinks.map(InLi)
def InlineNav(navlinks): return Nav(Ul( *navlinks.map(InLi), style="list-style:none" )) nv = InlineNav(navlinks) show(nv)
To follow accessibility best practices, including making this useful to screen readers:
aria-label
on Nav
role="navigation"
(redundant with <nav>
but helps old assistive tech)def InLi(linktuple): txt, href = linktuple return Li(A(txt, href=href), style="display:inline;margin-right:1em")
def InlineNav(navlinks): return Nav( Ul( *navlinks.map(InLi), style="list-style:none;padding-left:0" ), aria_label="Main navigation", role="navigation" ) nv = InlineNav(navlinks) show(nv)