Tailwind Accessible & Responsive Components: Menus, Accordions, and Modals... Oh my?

I know there are a lot of people who use Tailwind in combination with Sage.

What do you typically use for accessible and responsive components? I’m coming from Foundation where a lot of that functionality is baked in.

I’m typically building larger sites, so I need multi-level navigation that plays well on desktop and mobile, along with the usual suspects as far as components go.

I much appreciate anyone that can help me out. I’m excited to dive into Tailwind.

Gotta code it yourself.

However, if you’re going to use sage, I recommend this for the menu: https://github.com/Log1x/acf-composer

And for components that are already made, I recommend investing(essentially if you say a project will cost £5000, just add £300 so the client pays for it) into this: https://tailwindui.com/

That’s all really.

1 Like

Also use AlpineJS, it’s pretty straight forward.

1 Like

Thanks much for the resources. ACF Composer looks interesting. Tailwind UI looks good, but unfortunately I’m not really a Vue or React programmer.

I have a recommendation which probably won’t be all that popular here, but by only importing the parts you use, you can slim Bootstrap 5 down considerably. And it does have a lot of the utility classes that Tailwind has. The component menus, accordions & modals in Bootstrap have all the ARIA attributes you’re looking for and are well tested.

I usually only use the layout grid, collapse, modals, and a handful of other features. Removing large unnecessary CSS & JS like the carousel (I will use swiper.js if needed).

I like the approach of Tailwind, but I always need some JS components, especially modals. So, for at least this point in time, importing only what I need from Bootstrap works well. Some day when I have time (ha!) I may move to Tailwind, but I would need to find some other way of approaching JS components. Alpine.js looks promising, but again, I haven’t had the time to approach it yet.

1 Like

There are some good accessible components and markup patterns here:

I highly recommend digging into how this stuff works as well. Modals are very complex (e.g. they need focus traps/gaurds, keyboard navigation, etc.), so it makes sense to reach for a pre-built thing, but other components are fairly simple.

This might seem like Tailwind heresy (it’s not), but I think that when it comes to accessibility it’s best to break out of the utility class philosophy and write styles that are bound to the state of the component (i.e. aria- attributes). I say that as someone who has heavily used and promoted Tailwind, and who has used utility CSS approaches much longer than Tailwind has been around (see Tachyons, Basscss).

Typically, Tailwind users (myself included) write code like this:

/* This is simplified and partial: don’t use this snippet as a menu tutorial. */
menuButton.addEventListener('click', event => {
  menuButton.setAttribute('aria-expanded', true);

This might seem perfectly fine and logical to do, but this can be dangerous. Why? The styles are changing only as an effect of the interaction and not as an effect of the component’s state. Let me explain that a bit more. When an interaction happens in this scenario, there are two independent effects: the element’s accessible state is updated and the element’s visual state is updated. Yes, these might happen synchronously, but that means every time you change one you have to change the other or else it breaks. You, your stakeholders, and most of your users probably aren’t using a screen reader so it’ll be easy to think, “this looks right so it must be accessible.” Instead, change styles as an effect of state. Let the styling break as an effect of broken accessibility.

<!-- You can still use Tailwind for your base styles. -->
<button data-my-menu-button aria-expanded="false" class="bg-blue-9000 text-white p-2 rounded ...">
[data-my-menu-button][aria-expanded="false"] {
  /* styles related to this state. */

[data-my-menu-button][aria-expanded="true"] {
  /* styles related to this state. */

This way if some dev comes along and does something that breaks the accessibility, you will know because visually it won’t look correct as well. This way your great intentions of making these websites accessible aren’t set up for failure as they are maintained by people with or without the same intentions.

Adrian Roselli has a great article about this if you are interested or if I didn’t explain this well. I’m not saying don’t use Tailwind. Rather, don’t limit yourself to just using the utility class names and maybe leverage @apply. Remember, Tailwind is utility first and not always. Keep that in mind and I think you’ll do great!

1 Like

This dialog/modal looks great too:

Although the posts are a bit old now, I’ve used this site as an amazing resource in the past when building accessible interactive components: https://inclusive-components.design/ It provides very detailed breakdowns of why they’re built the way they are, as well as the code necessary.

1 Like

Thanks much for the input!

@christianmagill Vue or React has nothing to do with it. This is mainly PHP.

TailwindCSS isn’t for Vue or React, but its a CSS library/framework you can implement in any of your project.

The only reason you would want to look at React, is to see how they create components, because thats would you would be doingin Sage anyway, except that sage has limited resources - the concept is what you need here, so looking at React would be beneficial on seeing how compoents work.

This topic was automatically closed after 42 days. New replies are no longer allowed.