Trying out spicy sections on here

This week I had some fun with <spicy-sections> , an experimental custom element that turns a bunch of headings and content into tabs. Or collapsibles. Or some combination of affordances, based on conditions you set.


Introduced in Brian Kardell’s post Tabs in HTML?, the <spicy-sections> element is a concept from some folks in the Open UI Community Group. In this CG, we analyse UI components that are common in design systems and on the web. The goal is to find out which ones might be suitable additions to the platform, the HTML spec and browsers.

All design systems teams could come up with their own tabs and figure out semantics, accessibility, security and behaviours. But what if some (or all) of those things could be built into HTML, with browsers implementing smart defaults? A bit like the video element… as a developer you only need to feed it a video and some subtitles, and boom, your users can enjoy video. Maybe your specific website needs the play button to be pink or trigger confetti, but generally, there are quite a lot of websites where the default is just right.

The nice thing about platform defaults is also that it can be optimised for the platform that renders it: a select on iOS is different than a select on Microsoft Edge. They work well on these respective platforms. Yes, everyone would like more control over styling of selects, and Open UI is looking at that too (and yay, accent-color is a thing soon). But can we know which styles a given user needs as well as the platform can?

Why spicy sections?

Tabs are among the most frequently requested components. They are also tricky. Some of the considerations:

  • meaning: tabs in your browser manage windows, tabs in a webpage manage, eh, sections? These are quite distinct.
  • accessibility: with ARIA, there are at least two ways to do tabs (eg activate on focus or not?), and in some user tests I saw, users prefers ARIA-less tabs
  • what about disabled tabs and user dismissable ones?
  • overflow: what if not all tabs fit on the screen? scrollbars?

(The Tabs Research from Open UI CG has many more tab engineering considerations)

The overflow issue begs the question: does content displayed in tabs always belong in tabs, or might there be better controls in some situations? Maybe on small screens we need to get rid of the tabs and use collapsibles? (Maybe we need to ‘uncontrol’ them in specific cases, like print?)

This makes all the more sense if you consider tabs in web pages are really just a different way to display sections and their headings. Headings are tables of contents, after all. “Spicy sections”, then, would be a web platform feature that lets you display sections in different ways: linear, as is the default way to display sections now, as tabs or as collapsibles. You pick which based on constraints, and media queries are the way the spicy-sections demo defines those constraints.

Yes, <spicy-sections> is a demo, the element exists to explore ideas and start the conversation. Brian encourages you to share your thoughts:

Play with it. Build something useful. Ask questions, show us your uses, give us feedback about what you like or don’t. This will help us shape good and successful approaches and inform actual proposals.

As Brian says in his post: it is critical that web developers see these proposals way before they exist in browsers. So if you happen to be a front-end developer reading this… consider if you like this experiment, share your thoughts or questions, don’t feel shy to open a GitHub issue.

Four sections, but spicier

On this website I have a fairly boring page that lists some stuff I do as a freelancer: services. Each service has a h2 and a bit of content. I decided to use this for testing the spicy-sections element IRL.

To get it to work, I included SpicySections.js, a JavaScript class that defines a custom element. The element looks in your CSS for a definition of when you want which affordances. I went for this configuration:

  • collapsibles when max-width: 50em (my mobile state) matches
  • tabs when min-width: 70em matches
  • otherwise, just the headings and content as they are

I could set this in my CSS, using:

spicy-sections {
    [screen and (max-width: 50em) ] collapse |
    [screen and (min-width: 70em) ] tab-bar;

I rewrote my markup to have the following expected structure:

  <h2>Name of heading</h2>
    content be here
  … repeat the h2 and div for more sections

(also works with other headings; h1, h3, etc)

Note: this isn’t final syntax, it could be something else entirely, suggestions are welcomed.

Some overrides

After I had ensured my markup had the right shape, I included the SpiceSections JavaScript and I set my constraints in CSS, it worked very much as advertised. There were two things I tweaked.

Vertical tabs

With spicy-sections, you’re using headings as tab names. It seems my page has quite long headings. Horizontally, I didn’t have sufficient space, so I wanted mine to go vertical instead.

I got this to work by adding an extra affordance to the web component class, some code to set aria-orientation to vertical and a bit of CSS to make it work visually. I set white-space to normal and made spicy-sections a flex container in the row direction, for easy same height columns.

I could have done this all in CSS, except for aria-orientation, but I am unsure about the benefit of the attribute here: arrow keys for both orientations are supported by default.

Overriding a margin

In my website’s CSS, I have this line (don’t judge 😬):

*::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;

It somehow overwrote the right margin on the arrows that spicy-sections throws in for the collapsed view. No biggie, with CSS’s excellent cascading functionality this was easy to fix.


I have also put some spicy-sections inside my spicy-sections: I have some ‘examples’ listed on the side on larger screens, it made sense to me to show them collapsed on smaller screens. This can be done with a combination of spicy-sections:

  <h2>A section</h2>
      <h3>Oh my, I am nested!</h3>

and this CSS:

.spicy-services-examples {
  [screen and (max-width: 50em) ] collapse;

So basically, I only list one affordance and it only applies to “small screens”, or what that means on this site.


This is all a long winded way to say: I quite like the idea of conditionally changing the appearance of sections. I think it makes sense on the web, because our sites and apps are viewed on so many different screen types and sizes (screen spanning, anyone?). Horizontal tabs are probably not always the best affordance, other affordances make sense in some situations, so a mechanism to switch between them is useful.

The way the experimental component works happens to be very styleable. When I was implementing it on my site, I felt I could make everything look exactly the way I wanted it to look. The tabs are just h2 elements and you can do whatever you want to them, using the styling language we all know and love: CSS.

Reusing media query-like syntax for defining when to use which affordances is helpful. Folks who build responsive websites will be used to them already.

There are also some uncertainties that came to my mind:

  • will people get it? Wrapping some content into a spicy-sections sections element fits well into the way I think about content on the web, I think about markup a lot, it matters to me. I fear it could feel weird to others, especially designers and developers who aren’t very concerned with markup, or who don’t see headings as tables of contents
  • is this easy to author in a CMS? In theory this would work well with any CMS content, it could be used with CMSes that exist today, because the markup that is required is “just” headings and content. There may be some trickery required to wrap the content underneath each heading into a div, and the set of sections into the right element, but that should be minor.
  • are there other affordances that are not in the current proposal? Maybe something that automatically generated a table of contents kind of thing, like GitHub does for READMEs?
  • could it confuse users that semantics and accessibility meta data (roles, states) can change based on constraints?

Wrapping up

Thanks for reading this write-up! If you like, please play with Brian’s demo on Codepen, perhaps use spicy-sections somewhere and give feedback if you have any.

Comments, likes & shares

No webmentions about this post yet! (Or I've broken my implementation)