Overview

Displays a grid of cards KCard.

KCardGrid provides base layouts for the most common grids in our ecosystem, as well as customization or complete override of the base layouts.

Together with KCard, it ensures accessible navigation within card lists, such as announcing only their titles when using the tab key to avoid overwhelming screen reader outputs.

Grid's visual behavior is based on the window breakpoint system . KCardGrid determines how many cards per row to display based on its layout and a current window breakpoint.

KCardGrid doesn't manage inner card content. This is KCard's responsibility.

Guidelines

Also follow KCard guidelines .

Usage

Base layouts

Three base layouts are available: '1-1-1', '1-2-2', and '1-2-3'. They determine the number of cards per row for each window breakpoint level .

'1-1-1' grid

Displays a grid with 1 card per row on every screen size.

Level 0 Level 1 Level 2 Level 3 Level 4 Level 5 Level 6 Level 7
Cards per row 1 1 1 1 1 1 1 1

      <KCardGrid layout="1-1-1">
        <KCard
          v-for="i in 2"
          ...
        />
      </KCardGrid>
    

'1-2-2' grid

Displays a grid with 1 card per row on smaller screens, and 2 cards per row on medium and larger screens.

Level 0 Level 1 Level 2 Level 3 Level 4 Level 5 Level 6 Level 7
Cards per row 1 1 2 2 2 2 2 2

      <KCardGrid layout="1-2-2">
        <KCard
          v-for="i in 3"
          ...
        />
      </KCardGrid>
    

'1-2-3' grid

Displays a grid with 1 card per row on smaller screens, 2 cards per row on medium screens, and 3 cards per row on larger screens.

Level 0 Level 1 Level 2 Level 3 Level 4 Level 5 Level 6 Level 7
Cards per row 1 1 2 2 3 3 3 3

      <KCardGrid layout="1-2-3">
        <KCard
          v-for="i in 5"
          ...
        />
      </KCardGrid>
    

Layout customization

Base layouts can be customized or even completely overriden via the layoutOverride prop. layoutOverride takes an array of objects { breakpoints, cardsPerRow, columnGap, rowGap }, where:

  • breakpoints is an array of 0-7 values corresponding to the window breakpoint levels . All other attributes in the same object take effect on these breakpoints.
  • cardsPerRow overrides the number of cards per row for the specified breakpoints.
  • columnGap/rowGap overrides grid column/row gaps for the specified breakpoints.

For example:


      <KCardGrid
        layout="1-2-3"
        :layoutOverride="layoutOverride"
      >
        <KCard
          v-for="i in 6"
          ...
        />
      </KCardGrid>
    

      export default {
        ...
        data() {
          return {
            layoutOverride: [
              {
                breakpoints: [0, 1],
                columnGap: '20px',
                rowGap: '20px',
              },
              {
                breakpoints: [4, 5, 6, 7],
                cardsPerRow: 4,
              },
            ],
          };
        },
      };
    

Here, the base 1-2-3 layout is overriden partially. Column and row gaps are decreased to 20px on breakpoints 0-1, and the number of cards per row is increased to 4 on breakpoints 4-7.

Card height, content tolerance and alignment

Cards displayed in KCardGrid stretch vertically to fit their content, making a grid row height match its tallest card.

Setting height on cards is discouraged. Instead, manage height bottom-up, for example by setting height on card sections, using text truncation, or other ways to limit its inner content. Such approaches ensure content tolerance, prevent from unexpected overflows or excessive height, and keep vertical alignment of card sections consistent on a grid row. This is especially important when dealing with unknown lenghts or amounts of content displayed in cards. Consider:


      <KCardGrid ...>
        <KCard
          ...
          preserveAboveTitle
        >
          <template #aboveTitle>
            <div :style="{ height: '24px' }">...</div>
          </template>
          <template #title>
            <div :style="{ height: '52px' }">
              <KTextTruncator
                :maxLines="2"
                :text="..."
              />
            </div>
          </template>
          <template #belowTitle>
            <KTextTruncator
              :maxLines="4"
              :text="..."
            />
          </template>
          <template #footer>
            <span v-for="pill in slicedPills"> ... </span>
          </template>
        </KCard>
      </KCardGrid>
    

      export default {
        ...
        computed: {
          slicedPills() {
            return pills.slice(0, 2);
          },
        },
      };
    

Here, KCard has the following adjustments related to its visual output in the grid:

  • Height is set on its aboveTitle slot content, and its preserveAboveTitle prop keeps the slot area even without content. This results in consistent alignment of all cards' titles on a grid row.
  • Similarly, height is set on its title slot, and the title is truncated.
  • Its belowTitle slot's content is truncated.
  • The number of pills in its footer slot is limited to a reasonable amount.

KCard offers other preserve... props corresponding to its slots.

Fine-tuning responsiveness

Grid configuration can be combined with KCard's settings to further improve responsive experience. A common pattern is switching KCard's horizontal orientation to vertical for smaller screens to organize content more effectively in limited space:


      import useKResponsiveWindow from 'kolibri-design-system/lib/composables/useKResponsiveWindow';

      export default {
        setup() {
          const { windowBreakpoint } = useKResponsiveWindow();
          return { windowBreakpoint };
        },
      };
    

      <KCardGrid layout="1-2-2">
        <KCard
          v-for="i in 2"
          :orientation="windowBreakpoint < 4 ? 'vertical' : 'horizontal'"
          ...
        />
      </KCardGrid>
    

This technique also works for adjusting KCard slots content. In the following example, some metadata pills are hidden on smaller screens:


      <KCardGrid layout="1-2-2">
        <KCard
          v-for="i in 2"
          ...
        >
          <template #footer>
            <span ...>Read</span>
            <span ...>Short Activity</span>
            <template v-if="windowBreakpoint > 3">
              <span ...>Biology</span>
              <span ...>Ecology</span>
            </template>
          </template>
        </KCard>
      </KCardGrid>
    

Loading state

While data is loading, KCardGrid shows loading skeleton cards. Use the loading prop to toggle the loading state. Note that KCardGrid internal optimizations may affect how closely the visual loading experience matches the loading value:

  • The loading skeletons won't be displayed for short loading times (< 1s)
  • When the loading skeletons are displayed, they will be visible for at least 1s

Use the buttons in the example below to preview.

Number of loading skeletons

By default, the number of loading skeletons corresponds to the number of cards in a single grid row if it were full. This behavior can be overridden via the count attribute (below), however do not override it unless indicated in the designs.

Loading skeletons configuration

Use the skeletonsConfig prop to configure skeleton cards to match the expected visual output of loaded cards on all screen sizes. Preview the layout and height of cards with loaded data and adjust skeletonsConfig accordingly.

skeletonsConfig takes an array of objects { breakpoints, count, height, orientation, thumbnailDisplay, thumbnailAlign }, where:

  • breakpoints is an array of 0-7 values corresponding to the window breakpoint levels . All other attributes in the same object take effect on these breakpoints.
  • count sets the number of skeleton cards for the specified breakpoints. See Number of loading skeletons .
  • height sets the height of skeleton cards for the specified breakpoints.
  • orientation sets the orientation of skeleton cards for the specified breakpoints. Corresponds to KCard's orientation .
  • thumbnailDisplay sets the thumbnail display of skeleton cards for the specified breakpoints. Corresponds to KCard's thumbnailDisplay .
  • thumbnailAlign sets the thumbnail alignment of skeleton cards for the specified breakpoints. Corresponds to KCard's thumbnailAlign .

For easier development, enable the debug prop to display the current breakpoint in the top left corner of the grid. Use the button in the example below to preview the debug mode.


      <KCardGrid
        layout="1-2-2"
        :skeletonsConfig="skeletonsConfig"
        :loading="loading"
      >
        <KCard
          v-for="i in 3"
          :orientation="windowBreakpoint < 4 ? 'vertical' : 'horizontal'"
          thumbnailDisplay="large"
          thumbnailAlign="left"
          ...
        />
      </KCardGrid>
    

      export default {
        ...
        data() {
          return {
            skeletonsConfig: [
              {
                breakpoints: [0, 1, 2, 3, 4, 5, 6, 7],
                height: '400px',
                orientation: 'vertical',
                thumbnailDisplay: 'large',
                thumbnailAlign: 'left'
              },
              {
                breakpoints: [4, 5, 6, 7],
                height: '220px',
                orientation: 'horizontal'
              }
            ],
          };
        },
      };
    

Here, the height of loading skeleton cards is 400px with vertical orientation on breakpoints 0-3, and 220px with horizontal orientation on breakpoints 4-7. This makes skeleton cards resemble loaded cards at all breakpoints, creating a smooth transition for users during data loading. Note the bottom-up approach where we begin with a base setup for all breakpoints and gradually override on higher breakpoints. This simplifies the configuration object.

To get a sense of what skeleton layouts can be achieved, reload this page and the KCard page to preview the loading state in all examples.

Related

Props

Name Description Type Default Required
layout
Sets the base grid layout. Options: '1-1-1', '1-2-2', and '1-2-3'.
string '1-2-2'
layoutOverride
Overrides the base grid layout for chosen breakpoints levels
array null
loading
Set to true as long as data for cards are being loaded to display loading skeletons
boolean false
skeletonsConfig
Configures loading skeletons
array null
debug
Use for development only. Shows information in the grid's corner that is useful for configuring loading skeletons.
boolean false

Slots

Name Description
default
Slot for KCards