javascriptcssvue.jsquasar-framework

How to add scroll only for one template


I'm new in frontend and just have started to learn Vue + Quasar Framework. So, I have a table and want to fix my table name and scroll is only available in my table items.

<template>
    <q-table
      virtual-scroll
      class="fit"
      :style="'overflow: hidden;'"
    >
      <template v-slot:top >
        <div>Fruits</div>
        <q-space />
        <q-btn icon="search"/>
      </template>

      <template v-slot:fruit="props">
        <div class="q-pa-xs col-xs-12 col-sm-6 col-md-4">
            // my items cards
        </div>
      </template>

      
    </q-table>
 

</template>
<style>
.fit

  .q-table__top,
  .q-table__bottom,
  thead tr:first-child th
    /* bg color is important for th; just specify one */

  thead tr th
    position: sticky
    z-index: 1
  thead tr:first-child th
    top: 0
  /* this is when the loading indicator appears */
  &.q-table--loading thead tr:last-child th
    top: 48px
</style>


Solution

  • The rendered table elements are not designed/organized the same way in grid mode as in row mode. Inspecting the DOM in the browser shows q-table in row mode has a standard table with header and body

    <div
      class="q-table__container q-table--horizontal-separator column no-wrap q-table__card q-table--no-wrap my-sticky-header-table"
    >
      <div class="q-table__top relative-position row items-center">...</div>
      <div
        class="q-table__middle q-virtual-scroll q-virtual-scroll--vertical scroll"
      >
        <table class="q-table">
          <!-- table header -->
          <thead>
            <tr>
              <th class="text-left sortable">...</th>
              <th class="text-center sortable">...</th>
              <th class="text-right sortable">...</th>
              <th class="text-right">Carbs (g)</th>
            </tr>
          </thead>
          <!-- table content -->
          <tbody class="q-virtual-scroll__padding">...</tbody>
          <tbody class="q-virtual-scroll__content" tabindex="-1">...</tbody>
          <tbody class="q-virtual-scroll__padding">...</tbody>
        </table>
      </div>
    </div>
    

    Which is why a sticky header row requires position: sticky; top: 0; applied to the <th> elements

      thead tr th
        position: sticky
        z-index: 1
      thead tr:first-child th
        top: 0
    

    In grid mode, there is no <table> used to organize the grid elements

    <div
      class="q-table__container q-table--horizontal-separator column no-wrap q-table--grid q-table--no-wrap my-sticky-header-table"
    >
      <div class="q-table__top relative-position row items-center">...</div>
      <div class="q-table__middle">
        <table class="q-table">
          <!-- table header -->
          <thead>
            <tr>
              <th class="text-left sortable">...</th>
              <th class="text-center sortable">...</th>
              <th class="text-right sortable">...</th>
              <th class="text-right">Carbs (g)</th>
            </tr>
          </thead>
        </table>
      </div>
      <!-- grid content -->
      <div class="q-table__grid-content row">
        <div class="q-table__grid-item col-xs-12 col-sm-6 col-md-4 col-lg-3">...</div>
        <div class="q-table__grid-item col-xs-12 col-sm-6 col-md-4 col-lg-3">...</div>
        <div class="q-table__grid-item col-xs-12 col-sm-6 col-md-4 col-lg-3">...</div>
        <div class="q-table__grid-item col-xs-12 col-sm-6 col-md-4 col-lg-3">...</div>
        ...
      </div>
    </div>
    

    You see there is a <table> but it only contains the header information. The grid content is completely separate. Because of that, you don't need to sticky anything. Just give the grid content a height and overflow: auto which will add a scrollbar to the grid and the table header information will remain positioned on top.

    .q-table__grid-content
      height: 310px
      overflow: auto
    

    working sandbox example