> ## Documentation Index
> Fetch the complete documentation index at: https://learn.mintlify.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Columns and cards for visual comparisons

> Use columns and cards when a table is too rigid or your comparison items need richer content than a cell can hold.

export const Quiz = ({question, answers, correctFeedback, incorrectFeedback}) => {
  const [selected, setSelected] = React.useState(null);
  const [checked, setChecked] = React.useState(false);
  const quizId = React.useId();
  const isCorrect = checked && answers[selected]?.correct;
  const reset = () => {
    setSelected(null);
    setChecked(false);
  };
  return <div className={"quiz-container" + (checked ? " quiz-checked" : "")}>
      <Badge color="green">Quiz</Badge>
      <p className="quiz-question" id={quizId + "-question"}>{question}</p>
      <div className="quiz-options" role="radiogroup" aria-labelledby={quizId + "-question"} aria-disabled={checked}>
        {answers.map((answer, i) => <label key={i} className={["quiz-option", !checked && selected === i ? "quiz-option-selected" : "", checked && answer.correct ? "quiz-option-correct" : "", checked && selected === i && !answer.correct ? "quiz-option-incorrect" : ""].filter(Boolean).join(" ")}>
            <input type="radio" name={"quiz-" + quizId} checked={selected === i} onChange={() => !checked && setSelected(i)} disabled={checked} />
            <span className="quiz-radio" />
            <span className="quiz-option-label">{answer.text}</span>
          </label>)}
      </div>
      {checked && <div className={"quiz-feedback " + (isCorrect ? "quiz-feedback-correct" : "quiz-feedback-incorrect")} role="status" aria-live="polite" aria-atomic="true">
          <span className="quiz-feedback-icon">{isCorrect ? "✓" : "✗"}</span>
          {isCorrect ? correctFeedback : incorrectFeedback}
        </div>}
      <div className="quiz-actions">
        {!checked ? <button className="quiz-btn quiz-btn-check" type="button" onClick={() => selected !== null && setChecked(true)} disabled={selected === null}>
            Check answer
          </button> : <button className="quiz-btn quiz-btn-reset" type="button" onClick={reset}>
            Try again
          </button>}
      </div>
    </div>;
};

Tables work for compact, attribute-heavy comparisons. But sometimes the items you're comparing need more than a few words per cell. They need a description, a link, or a visual cue. For these cases, `<Columns>` with `<Card>` components gives you a side-by-side layout with more room to work.

## Columns for side-by-side content

`<Columns>` arranges any children components horizontally. Organize cards into one to four columns that responsively collapse to a vertical stack on smaller screens.

```mdx Side-by-side comparison with columns theme={null}
<Columns cols={2}>
  <Card>
    **API key authentication**
    
    Simple to set up. Best for server-to-server requests where user identity doesn't matter. Not suitable for client-side code because the key would be exposed.
  </Card>
  <Card>
    **OAuth 2.0**
    
    More setup required. Required when you need to act on behalf of a user. Tokens are short-lived and scoped, which limits the damage from a token leak.
  </Card>
</Columns>
```

This layout works when you're presenting two or three alternatives that need more information than a table cell can hold, but not so much that they each need their own page.

## Cards in a comparison context

`<Card>` components add structure with a title, and optional icons, images, or links. In a comparison layout, cards let readers navigate directly to the option that applies to them.

```mdx Comparison with cards theme={null}
<Columns cols={2}>
  <Card title="API key authentication" icon="key" href="/guides/auth-api-key">
    Server-to-server requests. Simpler setup. Not for client-side use.
  </Card>
  <Card title="OAuth 2.0" icon="lock" href="/guides/auth-oauth">
    User-delegated access. Required for acting on behalf of users. More setup.
  </Card>
</Columns>
```

The link on each card means users who know which option they need can navigate directly from the comparison to the relevant guide.

## When are columns and cards the right choice?

Use columns with cards when:

* You have two to four options and each needs a short description.
* Each option links to a separate page where users can get the full details.
* The options are genuinely parallel. They are the same kind of thing, but with different tradeoffs.
* A table would be too rigid because the options don't have a neat attribute/value structure.

## Columns imply equal options

Side-by-side layouts imply the options are equally valid. If one option is strongly preferred for most users, putting them side by side can understate that.

When one option is clearly better for most cases, tell your users explicitly before showing the comparison.

```mdx Comparison with a recommendation theme={null}
For most users, API key authentication is the right choice. Use OAuth if your app needs to access resources on behalf of individual users.

<Columns cols={2}>
  <Card title="API key authentication" icon="key" href="/guides/auth-api-key">
    Server-to-server requests. Simpler setup. Not for client-side use.
  </Card>
  <Card title="OAuth 2.0" icon="lock" href="/guides/auth-oauth">
    User-delegated access. Required for acting on behalf of users. More setup.
  </Card>
</Columns>
```

<Quiz
  question="You're comparing two pricing plans with eight attributes each: storage, API calls, support level, and five more. Which component is most appropriate?"
  answers={[
{ text: "Columns with cards. One card per plan.", correct: false },
{ text: "A table. It's a multi-attribute comparison with scannable values.", correct: true },
{ text: "Tabs. Users can select their plan and read the details.", correct: false },
{ text: "Two accordion sections, one per plan.", correct: false },
]}
  correctFeedback="Right. Eight attributes across two plans is exactly what tables are for. The grid structure lets users compare attributes row by row. Cards and columns work when descriptions are narrative; a pricing feature matrix is attribute/value data."
  incorrectFeedback="Cards are for short descriptions and navigation links. They don't handle eight attributes cleanly. When you have consistent attributes across multiple items, a table lets readers scan and compare efficiently. Cards work when the comparison items need prose descriptions, not when they're attribute lists."
/>

<Check>
  Next up: [Cards as navigation](/courses/components/cards-navigation) — Use cards to guide readers to their next step.
</Check>
