[HN Gopher] Tree views in CSS
       ___________________________________________________________________
        
       Tree views in CSS
        
       Author : divbzero
       Score  : 319 points
       Date   : 2022-11-19 05:31 UTC (17 hours ago)
        
 (HTM) web link (iamkate.com)
 (TXT) w3m dump (iamkate.com)
        
       | alserio wrote:
       | Are summary-details ok to use yet? Last time I've checked,
       | ammittedly some time ago, browsers had bugs and quirks around
       | them.
        
         | its-summertime wrote:
         | any issues should be easily enough to polyfill
        
           | alserio wrote:
           | Css rendering issues weren't
        
         | chrismorgan wrote:
         | * 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.)
         | 
         | Other than that, it's all pretty solid now.
        
           | alserio wrote:
           | Thank you!
        
       | madeofpalk wrote:
       | I did something similar a while back in Github Issues markdown to
       | show stats for files in the codebase that
       | https://github.com/grafana/grafana/issues/46451#issuecomment...
       | 
       | Used nested details/summary, but not ul/li - It can be quite
       | tricky to use the right level of whitespace to get GFM to render
       | what you intended.
        
       | Existenceblinks wrote:
       | 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.
        
         | equalsione wrote:
         | Would you consider using d3.js? I've been able to get great
         | performance for large deeply nested trees using d3. It depends
         | on your use case of course.
        
           | Existenceblinks wrote:
           | It's 278.58kB(.min), I'm not sure how good its tree shaking
           | is. I pick every js dependency seriously. Generally libs <
           | 7kB gzip for each.
        
       | mg wrote:
       | It can actually be simplified further by skipping the <ul> and
       | <li> elements and only using <details> elements:
       | 
       | https://twitter.com/marekgibney/status/1593950777739218947
        
         | 411111111111111 wrote:
         | doesn't that make the desired styling impractical unless you
         | replace them with divs? I dont think that would simplify it
         | unless i'm mistaken
        
           | mg wrote:
           | Do you mean the lines and the round buttons in the article?
        
             | 411111111111111 wrote:
             | yes, that styling was what the article was mostly about
             | after all.
             | 
             | The pure html was <10% of the article, the remaining 90+%
             | were about the styling
        
               | mg wrote:
               | The styling is done via borders and ::before and ::after
               | content applied to the nodes. Why would you not be able
               | to do that with <details> elements?
               | 
               | Here is a fiddle with the first step (borders on the
               | left) applied:
               | 
               | https://jsfiddle.net/qvb3udj6/
        
               | kamranjon wrote:
               | 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.
        
               | mg wrote:
               | I would be interested to try that out.
               | 
               | I just went through the whole first page of Google
               | results for "screen reader simulator" and none worked
               | without installing extra software.
               | 
               | Is there a website, where you can test how a given piece
               | of html is interpreted by screen readers?
        
               | asadotzler wrote:
               | 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.)
        
               | kamranjon wrote:
               | Here is a good summary:
               | https://accessibility.princeton.edu/how/content/lists
               | 
               | WAVE is a great browser extension to have for frontend
               | developers: http://wave.webaim.org/extension/
               | 
               | It helps you identify aspects of your design that might
               | not be accessible.
        
       | kosasbest wrote:
       | > 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_.
        
         | chrismorgan wrote:
         | It's worth noting here that it's _HTML_ that's doing the actual
         | heavy lifting here, rather than CSS--the CSS is just making it
         | look prettier.
         | 
         | Something like the venerable checkbox hack is a case of CSS
         | providing the functionality. That's imperfect.
         | 
         | <details> is _HTML_ providing the functionality. That's the
         | ideal.
        
         | krono wrote:
         | 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.
        
           | BeFlatXIII wrote:
           | 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?
        
             | bobthepanda wrote:
             | 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.
        
             | krono wrote:
             | 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.
        
           | chrismorgan wrote:
           | 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.
        
         | Waterluvian wrote:
         | 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.
        
       | pastinaaak wrote:
       | Is there a good JS part, a tree manager that comes close to a
       | standard component? I`ve been looking for one the last few days.
       | The closest i've found: https://www.naiveui.com/en-US/os-
       | theme/components/tree
       | 
       | Probably with html5 draggable and the amount of variation that it
       | is hard to make a standard component.
        
         | soylentgraham wrote:
         | 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
        
       | _HMCB_ wrote:
       | Best post this week on HN. Love it.
        
       | xjlin0 wrote:
       | That's so cool! Where can I find more similar topics on JS-free
       | implementation of "tree", "fixed table header", etc? Thanks!
        
         | ssttoo wrote:
         | Several examples in this article:
         | https://calendar.perfplanet.com/2020/html-and-css-techniques...
        
       | deergomoo wrote:
       | 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.
        
         | marcosdumay wrote:
         | On this case, the functionality is there right on the HTML, and
         | the CSS is just customizing the appearance to make it look like
         | a desktop widget.
         | 
         | This is not an issue of lack of HTML support. In fact, this is
         | exactly what CSS is for.
        
         | mhitza wrote:
         | 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.
        
           | eurasiantiger wrote:
           | 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?
           | 
           | I really hope RSS is coming back in force.
        
         | Bilal_io wrote:
         | Perhaps the the Open UI unitiative is a good place to create a
         | proposal.
         | 
         | https://open-ui.org
        
       | thrwawy74 wrote:
       | 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 :)
       | 
       | (Thank you for showing us this!)
        
         | jeroenhd wrote:
         | 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.
        
       | chrismorgan wrote:
       | 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:                 <ul class="tree">
       | <li>           <a href>Giant planets</a>           <details open>
       | <summary>Expand</summary>             <ul>               <li>
       | <a href>Gas giants</a>                 <details>
       | <summary>Expand</summary>                   <ul>
       | <li><a href>Jupiter</a></li>                     <li><a
       | href>Saturn</a></li>                   </ul>
       | </details>               </li>               <li>
       | <a href>Ice giants</a>                 <details>
       | <summary>Expand</summary>                   <ul>
       | <li><a href>Uranus</a></li>                     <li><a
       | href>Neptune</a></li>                   </ul>
       | </details>               </li>             </ul>
       | </details>         </li>       </ul>
       | 
       | 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.
        
       | amadeuspagel wrote:
       | Also seems useful for comment trees.
        
         | DoctorOW wrote:
         | 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.
        
       | dmix wrote:
       | > margin-left : calc(var(--radius) - var(--spacing));
       | 
       | Can you use calc in modern browsers these days without
       | transpilers?
        
         | sphars wrote:
         | Yes, all major browsers support calc() and have for a while now
         | 
         | https://caniuse.com/calc
         | 
         | https://developer.mozilla.org/en-US/docs/Web/CSS/calc
        
       | c-smile wrote:
       | For what it's worth...
       | 
       | In Sciter you can simply define tree view as <select
       | type="tree">:                  <select type="tree" treelines>
       | <option>                <caption>Giant planets</caption>
       | <option>                   <caption>Gas giants</caption>
       | <option>Jupiter</option>
       | <option>Saturn</option>                 </option>
       | <option>                   <caption>Ice giants</caption>
       | <option>Uranus</option>
       | <option>Neptune</option>                 </option>
       | </option>         </select>
       | 
       | And you will get: https://sciter.com/wp-
       | content/uploads/2022/11/select-tree.pn...
       | 
       | Tree view is quite popular in desktop UI, so I've decided to add
       | it as built-in.
       | 
       | And needless to say, that rendering of a tree is just one part -
       | it should also be keyboard navigation and other a18y things.
       | 
       | As of tree lines themselves:                 :scope[treelines]
       | option > option        {         display: list-item;
       | list-style-type: tree-line; // <<<< Sciter's CSS++          list-
       | marker-size:1px;         list-marker-color:#ccc;         list-
       | marker-style:solid;             }
        
       | martyalain wrote:
       | Cool Kate and thank you for this smart code. You could have a
       | look to your code rewritten in my small lambdaway project :
       | http://lambdaway.free.fr/lambdawalks/?view=viewing_trees
        
         | martyalain wrote:
         | {{tree}           {li           {details open
         | {summary Giant planets}            {ul             {li
         | {details close               {summary Gas giants}
         | {ul {li Jupiter}                   {li Saturn}             }}}
         | {li              {details close               {summary Ice
         | giants}               {ul {li Uranus}                   {li
         | Neptune}             }}}         }}}}
        
       | decasia wrote:
       | 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?"
        
         | timeon wrote:
         | 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.
        
           | hakre wrote:
           | I love that :hover trick, a well placed tag in back and the
           | mouse does not leave the "opened" (active) content that
           | easily. There is also :focus.
        
             | layer8 wrote:
             | 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.
        
               | hakre wrote:
               | 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.
        
         | pjmlp wrote:
         | Versus the native GUIs approach of here is a control for doing
         | what you want, and here is a clean architecture to design you
         | own controls.
        
           | mananaysiempre wrote:
           | 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.
        
       | franciscop wrote:
       | I made another totally different kind of "tree view" in CSS a
       | while back, in this case to see some kind of JSON-html tree into
       | a tree:
       | 
       | https://francisco.io/demo/tree/
       | 
       | 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!)
        
       | [deleted]
        
       | greggman3 wrote:
       | I recently used details and summary for a tree view in react and
       | ran into this bug
       | 
       | https://stackoverflow.com/questions/74313572/what-does-this-...
       | 
       | Just passing on info if you decide to use details in react
        
         | piskerpan wrote:
         | 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.
        
       | oever wrote:
       | 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.
       | 
       | https://sol.vandenoever.info/
        
         | hirenj wrote:
         | Wow, this is a really nice little tool! I usually end up
         | manually traversing Wiki entries to get to this info, so it's a
         | great shortcut!
        
       | refset wrote:
       | Very neat! Any ideas how to add correct vertical line heights
       | with multi-line / variable-height items? e.g. the vertical line
       | next to "Jupiter" here is too short
       | https://gist.github.com/refset/c6f3ac05cacc12d547b4bc96bbeac...
        
         | jkcxn wrote:
         | This one works with variable height, you can pull some css from
         | it https://codepen.io/khoama/pen/AoPeMM
        
           | refset wrote:
           | 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 :)
        
       ___________________________________________________________________
       (page generated 2022-11-19 23:01 UTC)