--- title: "How to hide decorative anchor" date: 2021-10-16 lang: en categories: [ blog, how-to ] tags: [ heading, anchor, accessibility, decorative] translationKey: "hide-anchor" --- As you might have noticed, I recently have some changes to the website design. The changes are mostly for accessibility and readability: the text is now bigger so it's easier to read and select. I also color visited links, so people can spend less time knowing they've read a link (haha who wants people to spend less time on their site I must be crazy right?). One of the changes it the heading anchor with a decorative "#" to make visual readers recognize the heading levels easier. However, if this would probably be announced as "hash" by screen readers, which wouldn't make sense. In this post, I'd show how I ended up with the current one. ## Simple heading anchor Heading anchor can simply be done by wrapping the content inside the anchor element, ``, which refers to the ID of the heading: ```html

Foo

``` This is very simple, and it works perfectly fine. However, I also would like to have a fancy visual cue in front of the heading some website use a chain link, but I prefer to use a simple character instead of an image. The hash symbol makes sense for me, since I mostly use Markdown. I use heading level minus 1 hashes for this (since heading level one is not used within a post). Using `::before` pseudo-element, this is rather simple: ```css h2::before { content: '# '; } h3::before { content: '## '; } ... ``` Unfortunately, this leads to an accessibility problem as stated at the beginning of this post: screen readers (inconsistently) announces this as "hash". Multiply that with the level of heading and imagine the nuisance. There are several proposals to solve this, which is discussed in following sections. ## Alternative text for pseudo-element I've read from some StackOverflow answers[^0] that you can add alternative text for pseudo-element by doing this: ```css h2::before { content: '# '; content: '# ' / ''; } ``` I don't know which browser supports this; it looks like bad syntax. The answer itself said this is non-standard. And I'd tell you this is not supported by Firefox, at least. ## Using aria-hidden content and visually hidden description So, I found a [blog post][hidden] whose content is similar to this one. It is likewise a long post, but in short the method is instead of using a pseudo-element, you can use aria-hidden decorative element with a visually hidden text. It looks like this: ```html

Section titled Foo Foo

``` [hidden]: https://nicolas-hoizey.com/articles/2021/02/25/accessible-anchor-links-with-markdown-it-and-eleventy/ This method is also used by [HTMHell][hell] and [MDN][mdn]'s social icons (though, HTMHell call the class `u-hidden` and use `sr-only` in their instruction). Here is how MDN styles the visually hidden class: ```css .visually-hidden { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute !important; width: 1px; } ``` This, however, looks bad if you read my posts from a RSS reader, as a RSS reader may not support all HTML tag and doesn't have the CSS for the visually hidden element at all. The heading appears as "# Section titled Foo Foo", which is rather hideous, if you ask me. [hell]: https://www.htmhell.dev/20-close-buttons/ [mdn]: https://developer.mozilla.org/ ## Current solution It is a rather simple combination of the previous approach and my original approach: use aria-hidden decorative icon, and use `::before` pseudo-element to avoid it rendering in the RSS feed. HTML: ```html

Foo

``` CSS: ```css h2 .decorative::before { content: '# '; } ``` I have only tested this on Firefox with orca as screen reader, though I expect it to do well on others as well. [^0]: one of a rather less reliable source of knowledge, yet commonly used by many people