This is very clever, and it’s nice that it’s fully accessible and requires no JS.
However, looking at that final CSS just makes me wish that we added new interface elements to HTML far more often. Folks run rings around themselves to implement things that have been in any desktop UI toolkit worth its salt since the 90s.
There are so many ARIA guidelines on implementing alerts, modals, comboboxes and anything in between. Yet most don't have any equivalent presentational or functional counterparts in the existing browsers. Writing this comment, just as I'm writing an accessible combobox in a project where I'm not using any frontend framework and minimal JavaScript.
Let’s extend this thought a bit deeper. Why are we consuming different brands of fixed-form content through bespoke interfaces? Why is there no standard for navigation of any type of content?
They are really bad at first impressions. Do they not think about their own code? Literally the first thing I see when I visit the page is a misused <blockquote>
> The blockquote element represents a section that is quoted from another source.
— the W3 blocquote specification
Their copy isn’t quoted from another source, it’s a janky admonition writers of Markdown use when their tools, Markdown, don’t support the semantics they mean. <blockquote> does not mean “put this in a box”.
Click the navigation and the first things you see are links to GitHub and Discord, two very not open platforms—which should go against the philosophy of the project if they want open standards.
> A tree view (collapsible list) can be created using only HTML and CSS, without the need for JavaScript
A bit tangential, but so much more should be done in CSS rather than resorting to JavaScript. One gripe I've always had are hamburger menus that fail to work with JS disabled. Most of my browsing is done with Safari on iOS and I've disabled JS on that browser since 1) I enjoy the privacy benefits 2) popup modals and other distractions are non-existent.
You can code a hamburger menu that opens when you click on it, without JS. Yes, CSS is not just for styling it can also be used for functionality.
99% of users don’t make a fuss about javascript and the developers know. It would probably be wrong to get so distracted by satisfying a tiny sliver of user base (the pickiest sliver?) with a disproportionate share of work.
Which is a shame because there’s something very elegant about using CSS. It’s usually much more performant.
The majority of those CSS "hacks" are not at all accessible, however. You'd get to browse the web without JavaScript, and millions of others would not be able to browse the web at all.
This is what’s often (OK, almost always) missed with such JavaScriptless components: progressive enhancement with JavaScript, so that it works without JavaScript, and works better with just a little JavaScript. Most of the traditional CSS hacks can be made just as good as the JavaScript version designed with accessibility in mind without too much effort. Most of the time it’s just managing some ARIA attributes and no more. Occasionally you might add an extra supporting element or slightly restructure an existing one.
Is that a problem with the browsers not providing functionality that should be standard or is it a problem of custom components that need the JS for the dev to specify how they work?
Not entirely sure if I fully understand your question.
To clarify, these CSS hacks often use checkbox inputs for isomorphic state management and that is simply incompatible with the semantics those elements are designed and expected to represent.
ECMAScript is a browser standard and was specifically invented for adding interactivity like toggling a hamburger menu. Yes it's also used for less savoury business but that's not the end-user's fault and shouldn't be made into their problem.
> To clarify, these CSS hacks often use checkbox inputs for isomorphic state management and that is simply incompatible with the semantics those elements are designed and expected to represent.
The one mentioned in the article, does not use checkboxes.
browsers do provide that functionality, just with JS.
CSS is not designed, to be something you're supposed to write Doom in even though you can. It hasn't been really updated with the purpose of 'obviate javascript' because the browsers don't really want to do that.
It was a fork of a much earlier project but I improved it a lot IIRC; unfortunately I lost the original source and now chances of finding it are very small (unless someone here knows it!)
This summer I made a website to show the closest common ancestors of arbitrary species. The hardest part was to get the tree to look nice. It's still not perfect. A naive approach gives a very wide tree.
My app has some huge tree (CRUD-able). Say 20k-30k nodes (sweet spots for being usable without virtualizaion). And Chrome perf sucks real bad for "Recalculate Style" phrase" the `.tree ul li::before{content:''}` is going to be ruining perf. Meanwhile firefox is wicked fast for overall perf for lots of dom nodes.
Thank you! I guess the trick with this suggestion is to move the vertical line to directly beneath the text such that it doesn't need to be taller...which is probably a good enough workaround, even if not exactly what I was hoping for :)
You’re complicating the two elements; They are interactive without javascript. Your answer is listening to native “open” change event, then reading this value and setting it back to the attribute via JSX. If the event happens at the wrong time, you’re possibly reading the previous value (closed) and setting it back to the details element.
I’d either avoid details in your case or see how others are using it.
I am not, as I need to state of the details to be settable. That's the whole mo of react, that all UI state is under your control and has a single source of truth. For example you want a tree of files, give the user a search function, and want to expand/collapse any subtreee that contains/does not contain a result.
Details is a collapsable building block. that's it.
This is not what is typically called a tree view: this is collapsible nested lists. The differences are important, and very fiddly to reconcile.
The key difference is that in a tree view, every node is focusable and has an action associated with activating it (which for parent nodes might be expanding/collapsing, but need not be), whereas with collapsible nested lists, only parent nodes are focusable, and their action is reserved and limited to expanding and collapsing. (You could make leaf nodes focusable and give them actions—e.g. make each one a link—but you can’t give parent nodes any other action, which is a fundamental limitation.)
Here’s what tree views are: https://w3c.github.io/aria-practices/#TreeView. This describes the functionality and interaction modes (including all the expected keyboard behaviours), with examples.
One important secondary difference: the article said that “the standard keyboard interaction is supported automatically”, and this is true for collapsible nested lists, but false for a tree view. In the former, each parent node is separately focusable, and you expect to use Tab/Shift+Tab to navigate between parent nodes; but tree views are composite widgets that manage focus, only appearing once in the tab order and using other keys (like the arrow keys) to manipulate focus within.
Is it possible to implement a true tree view with <details>? Mostly, yes, but there are limitations and difficulties.
If you’re OK with parent nodes’ only action being to toggle expansion, it’s not particularly hard; do it largely as shown in this article, making each leaf node focusable, and add some (nicely optional) JavaScript to get the keyboard interactions right and give the right ARIA attributes. The ARIA Authoring Practices document already linked will guide you through approximately all of the considerations. (If you haven’t worked with this document before, please do read the “Read Me First” section first.) In fact, I strongly recommend this general approach: make something that functions with only the HTML, then enhance it with JavaScript.
If you want parent nodes to have actions, parent nodes’ actions will need to be moved out of the <summary>. You’ll end up with something like this:
Focus and accessibility management will become a little more complicated, but it’s still workable. But styling will be at least somewhat painful because of the DOM structures and the order of things. You’ll probably want to use details::before for the marker. Grid and `details { display: contents }` might help with layout, though absolute positioning is probably the pragmatic approach (and test cross-browser before doing anything like `details { display: contents }`, the two features can have surprising interactions). Also in the absence of JavaScript, it’s not going to be possible to get the expected interaction order: you would want the focus order to be expand/collapse button, then the node itself, then children, but those first two will necessarily be transposed. Still, it’ll be better than it not working at all.
I love the hacker thought process of "Is there an HTML element that can hide and show content right out of the box (without js), and now can we borrow it to implement a completely different data structure that wasn't obviously part of its design?"
In old days (around the time when Yahoo switched from table design to css layout) people were hacking this with :hover. But mouse had to stay in the 'opened' content.
Except that native menus don’t really work like that. They have a nontrivial interplay between hovering and mousedown/mouseup that you can’t replicate with just CSS. Not to speak of the missing keyboard functionality.
Native menus? When I need native menus, I use a GUI toolkit, you might have put too much of your concerns into my words.
When I do "native" Menus in HTML I use lists und you can skip to navigation on top if you like but content comes first. And yes, the site works natively in a textmode browser.
The native GUI approach seems to struggle with extending the behaviour of stock controls, Win32 most of all. Granted, this is a very fuzzy problem that’s much more difficult than it seems (how do you shouls a CJK-style IME interact with a formatted-alphanumerics input?), and HTML+CSS doesn’t really do better, but it’s also a problem people have, and I don’t think native toolkits have a convincing approach. So I’m not ready to declare UI toolkits solved.
I made one specifically for viewing & editing json. Has draggable reordering with rough rules, auto-editable-values, copes with live updates whilst user is using it and other bits and bobs. Maybe along the lines of what youre looking for?
https://github.com/NewChromantics/WebComponent_TreeView
• IE and EdgeHTML never supported <details>, so until comparatively recently you had to polyfill it. Now, you need not worry about this, because you should actively not support IE or old Edge.
• WebKit still doesn’t use ::marker on summary. If you’re hiding the disclosure marker, you can’t just use `summary { display: block }` or `summary::marker { display: none; }`, and must remember to `::-webkit-details-marker { display: none }` as well. And if you want to change it, you can’t just change its list-style-type or manipulate ::marker, but must clobber the whole thing and use ::before or similar.
(Aside: if you don’t use a Mac, Epiphany is a good WebKit-based alternative to Safari on other platforms that will exhibit most of the same behaviours and quirks as Safari.)
I like this a lot. I wish sidebery (firefox extension for vertical tabs) had a style like this. It's all I've ever wanted from vertical tabs but no one seems to get this right. If I could do it myself...
Here's to hoping I can figure out how to make a react component of it :)
The addon Tree Style Tabs has the option of adding your own CSS to style the tree view. I don't know the the HTML that renders the tabs is built up, but I'm confident that it's possible to replicate this style with some CSS tweaks.
IIRC there was a Reddit alternative frontend that tried this to avoid using any JS and counterintuitively performance was awful. I think because this is somewhat obscure it's less optimized by browser vendors than DOM manipulation via JS.
I think probably the more concerning thing here is that you're removing the semantic value of HTML, in general I think you want to use the element that best suits your content. Lists make it easier for crawlers and screen readers to understand your website.
Use Narrator, Window's built in screen reader, or, even better, install NVDA. It's free and open source. It's also the majority screen reader on Windows. (If you're on a Mac, you've got VoiceOver built in.)
However, looking at that final CSS just makes me wish that we added new interface elements to HTML far more often. Folks run rings around themselves to implement things that have been in any desktop UI toolkit worth its salt since the 90s.