Skip to content

home.capabilities: cards have inconsistent heights across tabs #3945

Closed

Description

@PierreBrisorgueil

Symptom

In the capabilities section (The Trawl Pipeline on trawl.me, same on other projects), each tab's card renders at a different height. Switching tabs makes the container "jump" as the card shrinks or grows to fit the active item.

Root cause

src/modules/home/components/home.capabilities.component.vue wraps each tab in a <v-window-item> → <v-card>. <v-window> does not lock its height to the tallest child — it shrinks to fit the currently active item.

Each tab has a different description length, so the text column (v-col md="6") has a different height per tab. The image column uses <v-img aspect-ratio="16/9"> which fixes image height, but the row's total height is max(text, image) and varies tab-by-tab.

Net effect:

  • Short text + image → row = image height
  • Long text + image → row = text height
  • v-window height = active item height → visible jump on tab change

Proposed fix

Use a CSS grid stack inside <v-window> so all items overlay in a single grid cell, and the grid naturally takes the height of the tallest child. Zero JS, responds correctly to breakpoint changes, no magic min-height.

<!-- template -->
<div class="capabilities-stack">
  <div
    v-for="(item, index) in setup.items"
    :key="item.id"
    class="capabilities-stack__item"
    :class="{ 'capabilities-stack__item--active': activeIndex === index }"
  >
    <v-card ...> ... </v-card>
  </div>
</div>

<style scoped>
.capabilities-stack {
  display: grid;
}
.capabilities-stack__item {
  grid-area: 1 / 1;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.25s ease;
}
.capabilities-stack__item--active {
  opacity: 1;
  visibility: visible;
}
</style>

All items are rendered (same as current eager behavior), but stacked in the same grid cell. The grid cell sizes to the tallest item, so the container height is stable across tab changes and every card renders at the same size.

Alternatives considered

  1. Hard-coded min-height on v-card — works but is a magic number, doesn't adapt to content length changes per project.
  2. ResizeObserver measuring all v-window-item and applying max to v-window.minHeight — works but adds JS and has a first-paint flash before measurement.

The CSS grid stack is preferred: zero JS, zero magic number, correct by construction.

Acceptance

  • All cards in the capabilities section render at the same height
  • No vertical jump when switching tabs
  • Fade transition between items preserved
  • defaultActiveId + hash deep-linking still work
  • Keyboard navigation (ArrowLeft/Right) still works
  • No regression on mobile (single column stacking)

Repro

  1. Open https://trawl.me
  2. Scroll to "The Trawl Pipeline" section
  3. Click through the 4 tabs — container height jumps between tabs

Activity

  1. added a commit that references this issue on Apr 10, 2026
    efafbe5
  2. added a commit that references this issue on Apr 10, 2026
    3fa094b
  3. added a commit that references this issue on May 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions