Skip to content
Contact me

All building blocks

Sandbox

The flip card

A flip card shows a question on the front and its answer on the back, but a plain CSS rotation leaves the hidden side readable by screen readers. Here, the closed details hides the back, and visibility: hidden removes the front once the card is flipped.

Built with
details and summary
Browsers
Chrome 105+, Firefox 121+, Safari 15.4+
JavaScript
None

Demo

Turn JavaScript off: the card still flips.

Question

What is the capital of Australia?

Hint

It is not the country's largest city.

See the answer

Answer

Canberra. Sydney and Melbourne both wanted the title, so the capital was built between them.

Anatomy

  1. article The card container, named by its heading.
  2. Front The side visible at first: the label, the question and the hint.
  3. details Keeps the open or closed state of the card.
  4. summary The button that flips the card. Its label does not change: its collapsed or expanded state says which side is showing.
  5. Back The content of the details, shown on top of the front when it opens.

HTML code

HTML
<article class="card" aria-labelledby="card-title">
  <!-- Front: the side visible on load -->
  <div class="card__front">
    <h3 id="card-title">What is the capital of Australia?</h3>
    <p>Hint…</p>
  </div>
  <details class="card__details">
    <!-- Trigger: the button that flips the card -->
    <summary>See the answer</summary>
    <!-- Back: hidden, and absent for screen readers,
         until the card is flipped -->
    <div class="card__back">
      <p>Answer…</p>
    </div>
  </details>
</article>
CSS
/* The back covers the front when the card is flipped */
.card {
  position: relative;
}

.card summary {
  position: absolute;
  left: 22px;
  bottom: 22px;
  z-index: 2;
}

.card__back {
  position: absolute;
  inset: 0;
}

/* The hidden front also leaves the accessibility tree */
.card:has(details[open]) .card__front {
  visibility: hidden;
}

@media (prefers-reduced-motion: no-preference) {
  details[open] .card__back {
    animation: flip 0.35s ease-out;
  }

  @keyframes flip {
    from {
      transform: perspective(900px) rotateY(-80deg);
      opacity: 0.4;
    }

    to {
      transform: none;
      opacity: 1;
    }
  }
}

Usage

Use it for

  • Showing a question and its answer, a problem and its solution, or a before and after, when each side makes sense on its own.
  • Short texts, of similar length on both sides.

Avoid it for

  • Flipping the card on hover: impossible with a keyboard or on a touch screen.
  • Hiding a side with opacity: 0 or a rotation alone. It is still read by screen readers and reachable with the keyboard.
  • Making the whole card clickable: the summary must stay the only trigger.
  • A deadline hidden on the back: anyone who does not flip the card misses it.

Accessibility

ARIA roles and attributes

The card has a single ARIA attribute, aria-labelledby. The button and the hidden side come from HTML and CSS.

AttributeElementDescription
aria-labelledby="card-title"articlePoints to the card heading: the screen reader gets an article named "What is the capital of Australia?".
id="card-title"h3The target of aria-labelledby. Hidden with the front when the card is flipped, the heading still names the card.
Button role (implicit)summaryThe browser exposes it as a button, with its collapsed or expanded state. VoiceOver announces it as a "disclosure triangle". No aria-expanded to add.
opendetailsSet by the browser when you flip the card, removed when you turn it back to the front. Without open, the back is neither read nor reachable.
visibility: hiddendiv class="card__front"Once the card is flipped, the front leaves the accessibility tree: the screen reader no longer reads it.

Keyboard navigation

KeyAction
TabReaches the "See the answer" button
Enter or SpaceFlips the card, or turns it back to the front. Focus stays on the button
Tab on the flipped cardLeaves the card: the back holds no link or button

Tab order

  1. The "See the answer" button. It is the only stop: the front and the back are read with the screen reader's arrow keys.

With a screen reader

Example in Chrome with VoiceOver in English. The wording changes from one screen reader to another.

ActionAnnouncement
Tab to the button"See the answer, collapsed, disclosure triangle"
Enter"See the answer, expanded"
Next item (VO + →)"Answer", then the text on the back

Related RGAA criteria

The RGAA is the French accessibility standard. Its 106 criteria test WCAG 2.1 level AA.

Criterion 10.7: On each web page, for each element that receives focus, is the focus visible?
Focus stays visible on the button, whichever side is showing.
Criterion 10.8: On each web page, are hidden contents meant to be ignored by assistive technologies?
The hidden side is ignored by assistive technologies. The back becomes readable when you activate the button, placed just before it in the code.

Other references

Beyond the APG

New featureWhat it addsBrowsersIn the demo
details nameOnly one flipped card at a time, with no script: flipping a card closes the others.Chrome 120+, Firefox 130+, Safari 17.2+Variation
::details-contentAnimates the arrival of the back in CSS, with no @keyframes on a child block.Chrome 131+, Firefox 143+, Safari 18.4+No

Variations

Label that follows the side

"See the answer" becomes "Back to the question" when the card opens, with 2 span elements shown in turn in CSS. Clearer for people who see the screen, but the screen reader then announces "Back to the problem, expanded", 2 pieces of information that contradict each other to the ear.

Question

What is the capital of Australia?

Hint

It is not the country's largest city.

See the answerBack to the question

Answer

Canberra. Sydney and Melbourne both wanted the title, so the capital was built between them.

Code
<!-- HTML -->
<summary>
  <span class="when-closed">See the answer</span>
  <span class="when-open">Back to the question</span>
</summary>

/* CSS */
.when-open,
details[open] .when-closed {
  display: none;
}

details[open] .when-open {
  display: inline;
}

One card open at a time

In a grid of cards, the same name attribute on each details closes the previous card when you flip another one. Every browser has supported it since September 2024 (Firefox 130).

Question

What is the capital of Australia?

Hint

It is not the country's largest city.

See the answer

Answer

Canberra. Sydney and Melbourne both wanted the title, so the capital was built between them.

Question

How many hearts does an octopus have?

Hint

More than one.

See the answer

Answer

Three: two pump blood to the gills, the third to the rest of the body.

Code
<details name="cards">…</details>
<details name="cards">…</details>