Skip to main content

/ Treasa Ní Chonchúir

Logical off-screen positioning for “skip navigation” links

My home page has a skip navigation link as the very first child of the body element. This allows folks who use assistive technologies to go directly to the main content of the page, bypassing the boring site-wide header text.

To make this skipnav link available to AT users but hidden otherwise, I used some simple CSS to position it off-screen by default and reveal it when focused:

#skipnav {
    position: absolute;
    top: -2em;
}
#skipnav:focus {
    position: static;
    top: auto;
}

These days, though, I’ve got multiple language variants of my landing page. The Japanese variant uses たて (tategaki, vertical writing). (Cross-browser support for CSS writing modes is pretty good these days—not perfect, mind, but more than adequate for a simple personal website like mine.)

This is what English text looks like by default when set in writing-mode: vertical-rl. And here’s some Japanese text set vertically:

娘はエーリンです。彼女のもう一人の母親はエーリンです。私の恋人はエーリンです。これは紛らわしいかもしれません。私の娘とパートナーと私はサンフランシスコに住んでいます。私の出身はボストンです。

English and Japanese text set using writing-mode: vertical-rl.

You probably see where I’m going with this. On a page using vertical, right-to-left writing, using top: -2em to push the skipnav link off-screen doesn’t work.

Skip to main content

This is what English text looks like by default when set in writing-mode: vertical-rl. And here’s some Japanese text set vertically:

娘はエーリンです。彼女のもう一人の母親はエーリンです。私の恋人はエーリンです。これは紛らわしいかもしれません。私の娘とパートナーと私はサンフランシスコに住んでいます。私の出身はボストンです。

What top: -2em does in vertical-rl.

At first, I worked around this by adding some additional styles on just my Japanese home page:

#skipnav {
    top: auto;
    right: -2em;
}
#skipnav:focus {
    right: auto;
}

This isn’t great, though. I’d like to write a single bit of CSS that I can apply to all of my pages, regardless of their writing mode.

No problem! It’s 2024, and logical properties have been a thing for a while now. Just use inset-block-start instead of top—it’s supported in all three major browser engines.

#skipnav {
    position: absolute;
    inset-block-start: -2em;
}
#skipnav:focus {
    position: static;
    inset-block-start: auto;
}