Back Original

Text-based web browsers

Before I start, let me get two things out of the way:

Do text-based web browsers still matter?

Well, I won’t be the judge of that. I like them, I have them installed, and I test every project I create in them. But they are not what I use to surf the web.

Speaking of testing your creations, here’s the good news: If your project has a solid HTML foundation that you then progressively enhance with CSS and JS, you are off to a great start.

How did HTML evolve in recent years?

While CSS is the star of the show when it comes to new features, HTML ain’t stale either. If we put the long-awaited styleable selects and Apple’s take on toggle switches aside, there’s a lot readily available cross-browser.

But here’s the thing: Whenever we say cross-browser, we usually look at the big ones, never at text-based browsers. So in this article I wanna shed some light on how they handle the following recent additions.

How do text-based web browsers handle modern HTML?

When viewing a web page in a text-based browser, you essentially get plain HTML, no CSS, no JS. There is some “styling”, a result of the elements’ semantics, but don’t expect anything fancy, we are down to colors, indentation, and centered text.

It reminds me of what the browsers we are used to give us when they show unstyled HTML—well, HTML with the browser default styles, to be exact. That in turn reminds me of CSS Naked Day.

Text-based browsers work well with good old HTML. Said recent additions however are a bit more nuanced (e.g. interactive), so let’s talk about them individually.

Details

Disclosure widgets are simple interactive elements we no longer need JS for. When <details> are closed, only their <summary> is shown.

Text-based browsers have no clue what disclosure widgets are, so they always show the whole <details> content, meaning you always get the open state. This way things can get verbose, but in essence it’s okay.

Verdict: Acceptable.

Data lists

Data lists can be used to add suggested values to an input field. In my tests they have been ignored entirely, Lynx even mentions that it encountered “bad HTML”, probably because it expects <option> only in a <select> parent. At least no browser rendered the options on the screen, they simply fall back to a plain <input> field, which is better than nothing. Side note: I’ve been told data lists have accessibility issues, so …

Verdict: Whatever.

Dialogs

Yes, HTML can do modal and non-modal dialogs, and even alert dialogs, all thanks to the <dialog> element. Initially we needed JS to toggle their visibility, but with the help of the Popover API (see next chapter) we can now even get most of it done in plain HTML.

Alas, once again there is no support in text-based browsers, so you’ll end up seeing all dialog content, as if they had their open attribute set. Consequently, there’s no awareness of a form’s method="dialog" nor a submit button’s formmethod="dialog", so in both cases the form action is triggered.

Verdict: Problematic.

Popovers

The Popover API is probably my favorite new feature, but only if you stick to regular web browsers.

Given that dialogs are a type of popover, it’s no surprise that nothing works, and once again all popover content gets dumped onto the screen.

By now I think you get the idea, so I won’t even talk about the Invoker Commands API at this point.

Verdict: Most likely problematic.

Inert content areas

A modal dialog makes the rest of the page inert, so we don’t have to do it. But with the global inert attribute we can do this manually too, if we need to make certain parts of the DOM unreachable.

Sure enough, text-based browsers will happily let you access interactive elements inside an inert content area.

Verdict: Bad.

Hidden content

We’re now approaching something that is not new at all, the global hidden attribute has been supported for over a decade. It allows us to hide content in the same way as display: none, but directly in HTML.

Adding support in text-based browsers has been discussed back in the day, but got rejected, hence it was never implemented. You’ll end up seeing all content marked as hidden. This is the primary reason why I started writing this article, and what enrages me the most. If I decide to hide content in HTML instead of CSS, I must have a very good reason, thus hidden content should not be visible in any browser! Certain progressive enhancement techniques work by hiding content in HTML and then making it visible via CSS or JS. That possibility goes out the window in text-based browsers.

Verdict: Epic fail. 😠 🤬

Visually hidden content

Just kidding, there’s still no native way in HTML to hide content visually, so we continue to rely on class names like .visually-hidden or .sr-only. No matter how they are named, they need to summon quite a few of lines of CSS to get things done. Whether there should be a native way is up for debate. Personally I would welcome a one-liner to achieve this, but it should remain in the domain of CSS.

However, if we had a way in HTML, text-based browsers would display such visually hidden content anyway, that is certain.

Verdict: To be continued.

Now what? What now?

Text-based browsers and modern HTML, no success story in sight. Given the progress we see in web technologies, the gap will only widen, so much so that w3m and its friends might fall into oblivion.