Preblocks

Native Accordion

Source

A shadcn-style accordion built using native HTML details and summary elements with Tailwind CSS animation for better SEO and no JavaScript library required.

Is it accessible?

Yes. It uses semantic HTML elements with built-in accessibility.

Is it styled?

Yes. It comes with default styles that matches the other components’ aesthetic.

Is it animated?

Yes. It uses the new ::details-content pseudo-element for smooth animations.

Show code

export function AccordionDemo() {
  const faqs = [
    {
      question: "Is it accessible?",
      answer: "Yes. It adheres to the WAI-ARIA design pattern.",
    },
    {
      question: "Is it styled?",
      answer: "Yes. It comes with default styles that matches the other components' aesthetic.",
    },
    {
      question: "Is it animated?",
      answer: "Yes. It uses the new `::details-content` pseudo-element for smooth animations.",
    },
  ]
  return (
    <Accordion>
      {faqs.map((faq, index) => (
        <AccordionItem name="faq" key={index}>
          <AccordionTrigger>{faq.question}</AccordionTrigger>
          <AccordionContent>{faq.answer}</AccordionContent>
        </AccordionItem>
      ))}
    </Accordion>
  )
}

Installation

You can install this component using the following command with Shadcn CLI:

pnpm dlx shadcn@latest add @preblocks/native-accordion

Usage

import {
  Accordion,
  AccordionContent,
  AccordionItem,
  AccordionTrigger,
} from "@/components/ui/native-accordion"
export function AccordionDemo() {
  return (
    <Accordion>
      <AccordionItem name="item">
        <AccordionTrigger>Is it accessible?</AccordionTrigger>
        <AccordionContent>
          Yes. It adheres to the WAI-ARIA design pattern.
        </AccordionContent>
      </AccordionItem>
    </Accordion>
  )
}

Single panel

By default, the <details> HTML element allows multiple panels to be open at the same time. If you want to limit the accordion to only one panel open at a time, You can add the same name attribute to the AccordionItem, I also recommend using an array and map to generate AccordionItem. 1

Control default open panel

You can control the default open panel by adding the open attribute to the AccordionItem. If you add the same name attribute to the AccordionItem, only the first panel will be opened. 2

Is it accessible?

Yes. It adheres to the WAI-ARIA design pattern.

Is it styled?

Yes. It comes with default styles that matches the other components’ aesthetic.

Show code

export function AccordionDemo() {
  return (
    <Accordion>
      <AccordionItem name="item" open>
        <AccordionTrigger>Is it accessible?</AccordionTrigger>
        <AccordionContent>
          Yes. It adheres to the WAI-ARIA design pattern.
        </AccordionContent>
      </AccordionItem>
      <AccordionItem name="item" open>
        <AccordionTrigger>Is it styled?</AccordionTrigger>
        <AccordionContent>
          Yes. It comes with default styles that matches the other components&apos; aesthetic.
        </AccordionContent>
      </AccordionItem>
    </Accordion>
  )
}

Comparing with Radix / shadcn

This component offers significant advantages in terms of SEO, accessibility, and reduced JavaScript dependency compared to Radix UI and shadcn/ui’s Accordion. However, animation features rely on newer browser support.

FeatureNative HTML AccordionRadix / shadcn
JavaScript DependencyNone (native HTML elements)JavaScript library (Radix UI)
DOM RenderingContent always rendered in DOM, hidden by CSSContent often not rendered until expanded
SEO BenefitsSemantic tags, all content in initial DOM for crawlersContent may not be in initial DOM
In-page SearchCan automatically expand when hidden content is found 3Hidden content may not be searchable or auto-expandable
AccessibilityInherently accessible due to native elementsRelies on WAI-ARIA implementation
Animation SupportRelies on newer browser features (::details-content)Generally well-supported across browsers
Browser CompatibilityCore functionality works everywhere; animations require modern browsersBroad browser support for all features

Compatibility

This component leverages the ::details-content pseudo-element for smooth transition animations. Please note that this pseudo-element was introduced in Chrome 131 (released November 2024), meaning animations will not be visible in unsupported browsers. However, the component will still function correctly. You can check browser compatibility on MDN.

Additionally, details-content: support is available starting from Tailwind CSS v4.1.

See also


Footnotes

  1. MDN - <details> name attribute, support since Chrome 120 (released December 2023)

  2. MDN - <details> open attribute

  3. See this blog post, only available on Chromium-based browsers.