You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Quasar实现单列标题高度变化时所有列卡片同步下移

解决Jeopardy游戏列标题换行后卡片对齐问题

我用Vue3 + Quasar 2.11.6开发Jeopardy游戏,布局是q-cards组成的网格,每列顶部是可编辑的q-input作为主题标题。现在遇到的问题是:当某列标题文本过长换行时,只有该列的卡片会向下偏移,其他列的卡片位置保持不变。我需要所有列的卡片都同步下移,对齐到高度最高的列标题下方的位置。

当前代码:

<template>
  <div v-for="category in categories" :key=category.id class="column no-wrap">
    <div class="row flex justify-center text-h4">
      <q-input borderless type="textarea" autogrow v-model="category.title" :input-style="{ fontSize: '35px', width: '270px', lineHeight: '35px'}"/>
    </div>
    <div v-for="question in category.questions" :key="question.id" class="row no-wrap">
      <q-card class="bg-teal-3 q-ma-sm">
      </q-card>
    </div>
  </div>
</template>

解决方案1:使用Quasar Grid组件(推荐)

Quasar的q-grid组件原生支持行列对齐,能自动让同一行的所有元素高度匹配,完美解决卡片偏移问题。

修改后的模板代码:

<template>
  <!-- 外层网格容器,列数等于分类数量,设置列间距 -->
  <q-grid :cols="categories.length" :col-gap="16" class="q-pa-md">
    <!-- 标题行:每个分类标题占一个网格项 -->
    <q-grid-item 
      v-for="category in categories" 
      :key="category.id" 
      class="flex justify-center"
    >
      <q-input 
        borderless 
        type="textarea" 
        autogrow 
        v-model="category.title" 
        :input-style="{ fontSize: '35px', width: '270px', lineHeight: '35px'}"
      />
    </q-grid-item>

    <!-- 问题行:按最大问题数循环,每行的每个分类对应一个卡片 -->
    <template 
      v-for="(_, rowIndex) in maxQuestionCount" 
      :key="rowIndex"
    >
      <q-grid-item 
        v-for="category in categories" 
        :key="`${category.id}-${rowIndex}`" 
        class="flex justify-center"
      >
        <q-card class="bg-teal-3 q-ma-sm" style="width: 270px; height: 120px;">
          <!-- 卡片内容区域 -->
        </q-card>
      </q-grid-item>
    </template>
  </q-grid>
</template>

<script setup>
import { computed } from 'vue';

// 假设categories是你的分类数据源
const categories = /* 你的分类数据 */;

// 计算所有分类中最大的问题数量,确保行数覆盖所有分类
const maxQuestionCount = computed(() => {
  return Math.max(...categories.map(cat => cat.questions.length), 0);
});
</script>
  • 核心逻辑:q-grid会将同一行的所有网格项高度统一为该行最高元素的高度,无论哪个标题换行变高,整行高度都会自适应,后续问题行自然对齐。

解决方案2:CSS Grid自定义布局

如果更倾向原生CSS方案,用CSS Grid也能实现相同效果:

<template>
  <div class="jeopardy-grid" :style="{ '--cols': categories.length }">
    <!-- 标题行 -->
    <div 
      v-for="category in categories" 
      :key="category.id" 
      class="category-title"
    >
      <q-input 
        borderless 
        type="textarea" 
        autogrow 
        v-model="category.title" 
        :input-style="{ fontSize: '35px', width: '270px', lineHeight: '35px'}"
      />
    </div>

    <!-- 问题行 -->
    <template 
      v-for="(_, rowIndex) in maxQuestionCount" 
      :key="rowIndex"
    >
      <div 
        v-for="category in categories" 
        :key="`${category.id}-${rowIndex}`" 
        class="question-card"
      >
        <q-card class="bg-teal-3 q-ma-sm" style="width: 270px; height: 120px;">
          <!-- 卡片内容区域 -->
        </q-card>
      </div>
    </template>
  </div>
</template>

<script setup>
import { computed } from 'vue';

const categories = /* 你的分类数据 */;

const maxQuestionCount = computed(() => {
  return Math.max(...categories.map(cat => cat.questions.length), 0);
});
</script>

<style scoped>
.jeopardy-grid {
  display: grid;
  /* 根据分类数量动态设置列数 */
  grid-template-columns: repeat(var(--cols), 1fr);
  gap: 16px;
  padding: 24px;
}

.category-title {
  display: flex;
  justify-content: center;
}

.question-card {
  display: flex;
  justify-content: center;
}
</style>
  • 核心逻辑:外层容器通过CSS Grid划分行列,所有标题和卡片按行列顺序排列,同一行的元素自动继承行高,实现全局对齐。

原代码问题分析

原代码中每个分类是独立的column容器,各容器内部的标题和卡片仅在自身垂直流中排列,容器之间没有行对齐约束。因此某列标题高度变化时,只会影响自身容器内的卡片位置,其他列不受影响。而网格布局将整个页面划分为统一的行列结构,强制同一行的元素高度一致,从根本上解决了对齐问题。

内容的提问来源于stack exchange,提问作者Frederik Kliemt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 01:07:55