Lattice Grid Buy a licence

demo D132

prefers-reduced-motion

Every animation the grid drops when the viewer asks for less

@media (prefers-reduced-motion: reduce)

Building…
Loading a live grid…

The configuration

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@toclocoinc/lattice-grid@1.27.0/lattice-grid.min.css">
<style>
  #grid > div { height: 540px; }
</style>
<div id="grid"></div>

<script type="module">
  import * as Vue from 'https://esm.sh/vue@3';
  import { createGrid } from 'https://cdn.jsdelivr.net/npm/@toclocoinc/lattice-grid@1.27.0/lattice-grid.esm.min.js';
  import createLatticeGrid from 'https://cdn.jsdelivr.net/npm/@toclocoinc/lattice-grid@1.27.0/modules/vue.esm.min.js';

  const LatticeGrid = createLatticeGrid({ vue: Vue, createGrid });

  // True when the viewer has asked their operating system for less motion.
  const reducedMotionNow = () =>
    typeof matchMedia === 'function' && matchMedia('(prefers-reduced-motion: reduce)').matches;

  Vue.createApp({
    components: { LatticeGrid },
    data() {
      return {
        config: {
          rowKey: 'id',
          autoHeight: true,
          columns: [
            { field: 'part', title: 'What moves', layout: { width: 210, pin: 'start' } },
            { field: 'selector', title: 'Selector', layout: { width: 300 } },
            { field: 'normally', title: 'Normally', layout: { width: 280 }, cell: { wrap: true } },
            { field: 'reduced', title: 'Under reduce', layout: { flex: 1, min: 260 }, cell: { wrap: true } },
            {
              id: 'now',
              title: 'Right now',
              layout: { width: 150 },
              // Reads the viewer's OS setting, which is not part of the row, so it is
              // marked impure and is never stored as though it were data.
              sort: false,
              filter: false,
              value: {
                pure: false,
                deps: '*',
                compute: (_deps, ctx) => {
                  if (!ctx?.data?.covered) return 'still plays';
                  return reducedMotionNow() ? 'dropped' : 'plays';
                },
              },
              cell: {
                decoration: 'pill',
                variant: { map: { dropped: 'success', plays: 'info', 'still plays': 'neutral' } },
              },
            },
          ],
          rows,  // one row per motion the stylesheet defines, with a covered flag
        },
      };
    },
    template: '<lattice-grid v-bind="config" />',
  }).mount('#grid');
</script>

Respecting prefers-reduced-motion in a data grid

Reduced motion support means the grid checks the operating system’s motion preference and drops non-essential animation when the viewer has asked for it. Lattice Grid does this automatically through the @media (prefers-reduced-motion: reduce) query rather than a grid-level flag, so row reordering, column resize easing, sort transitions and the hover shimmer on active cells all switch to instant state changes the moment the setting is on, with no configuration needed in the page that hosts the grid. A developer reaches for this when the grid sits inside a product that already honours the preference elsewhere, or when a user has reported nausea or disorientation from scrolling and reflow animation, which is the documented effect the media query exists to prevent under WCAG 2.3.3. Vestibular disorders are the usual driver behind the operating-system setting, and a JavaScript data grid that ignores it forces those users to either tolerate the motion or avoid the page. Because the check runs at the CSS layer rather than in per-interaction JavaScript, there is no extra render cost when the preference is off: the animation rules do not apply, and the grid’s virtual scrolling continues to recycle rows at the same rate regardless of which state the media query is in.

Does Lattice Grid support prefers-reduced-motion?

Yes. The grid listens for the @media (prefers-reduced-motion: reduce) query and removes transition and easing effects on row moves, resizes, sorts and hover states when it matches, without a separate configuration option. Turning on reduced motion at the operating-system level is enough; no grid-specific setting is required to make the change take effect.