Responsive Containers (DataGridContainer)

Measure the grid container with ResizeObserver so the DataGrid renders at the correct size as its layout grows or shrinks.

#resize-observer#responsive-layout#container#absolute-positioning
Last reviewed: 2026-08-18
GitHub
import * as React from 'react';
import { BGrid } from 'beautiful-grid';
import type { BGridColumn, BGridDataItem } from 'beautiful-grid';
import DataGridContainer from '../components/DataGridContainer';
import { useContainerSize } from '../hooks/useContainerSize';

interface Order {
  id: string;
  customer: string;
  status: '준비 중' | '배송 중' | '완료';
  amount: number;
}

const columns: BGridColumn<Order>[] = [
  { key: 'id', label: '주문 번호', width: 120 },
  { key: 'customer', label: '고객', width: 180 },
  { key: 'status', label: '상태', width: 110, align: 'center' },
  { key: 'amount', label: '금액', width: 140, align: 'right', itemRender: ({ value }) => `${value.toLocaleString()}원` },
];

const data: BGridDataItem<Order>[] = Array.from({ length: 80 }, (_, index) => ({
  values: {
    id: `ORDER-${String(index + 1).padStart(4, '0')}`,
    customer: `고객 ${index + 1}`,
    status: ['준비 중', '배송 중', '완료'][index % 3] as Order['status'],
    amount: 18000 + index * 750,
  },
}));

export default function ContainerResizeExample() {
  const [isSidebarOpen, setIsSidebarOpen] = React.useState(true);
  const containerRef = React.useRef<HTMLDivElement>(null);
  const { width, height } = useContainerSize(containerRef);

  return (
    <div>
      <div style={{ alignItems: 'center', display: 'flex', gap: 12, marginBottom: 12 }}>
        <button
          type="button"
          onClick={() => setIsSidebarOpen(open => !open)}
          style={{ background: '#2563eb', border: 0, borderRadius: 6, color: '#fff', cursor: 'pointer', padding: '8px 12px' }}
        >
          {isSidebarOpen ? '사이드 패널 닫기' : '사이드 패널 열기'}
        </button>
        <span style={{ color: '#64748b', fontSize: 13 }}>컨테이너: {Math.round(width)} × {Math.round(height)}px</span>
      </div>

      <div
        style={{
          display: 'grid',
          gap: 12,
          gridTemplateColumns: isSidebarOpen ? 'minmax(150px, 0.35fr) minmax(0, 1fr)' : 'minmax(0, 1fr)',
          height: 440,
        }}
      >
        {isSidebarOpen && (
          <aside style={{ background: '#f1f5f9', borderRadius: 8, color: '#475569', padding: 16 }}>
            <strong style={{ display: 'block', marginBottom: 8 }}>필터 패널</strong>
            화면 폭이 줄어도 그리드는 이 영역의 정확한 크기를 다시 측정합니다.
          </aside>
        )}
        <DataGridContainer ref={containerRef} style={{ height: '100%', minWidth: 0 }}>
          <BGrid<Order> width={width} height={height} columns={columns} data={data} />
        </DataGridContainer>
      </div>
    </div>
  );
}

1. Measure the grid, not the viewport

Application layouts often change width and height at runtime because of side panels, tabs, and split views. If you give the grid an initial window size or a fixed value, it may look correct when the viewport grows but retain a stale size when the viewport shrinks, causing horizontal scrolling and layout misalignment.

useContainerSize uses ResizeObserver to observe the actual content area of the element that contains the grid. Pass the measured width and height to BGrid so it rerenders whenever the parent layout grows or shrinks.


2. Why DataGridContainer is necessary

DataGridContainer is a position: relative measurement boundary. The DataGrid root inside it is positioned with position: absolute; inset: 0. The container therefore retains its exact size in normal document flow while the grid fills the measured area completely.

In flex and grid layouts, the item that contains the grid needs min-width: 0 so it can shrink below its content’s intrinsic width. The container also needs an explicit height. DataGrid uses that height to calculate the visible row count and virtual-scroll range.


3. Setup steps

  1. Wrap the grid area in DataGridContainer and give it a height.
  2. Pass the container ref to useContainerSize.
  3. Pass the returned width and height to BGrid.
  4. If the parent uses flexbox or CSS Grid, apply minWidth: 0 or CSS min-width: 0 to the item that contains the grid.

Open and close the side panel in the live example. The grid immediately adjusts to the correct width whether the container grows or shrinks.


4. Approaches to avoid

  • Reading window.innerWidth once and using it as the grid size
  • Passing only height="100%" without giving the container a definite height
  • Leaving the default min-width: auto on a flex item so its content cannot shrink
  • Measuring an arbitrary DOM element outside the grid and sharing that size across multiple grids

The most predictable approach is for each grid to observe its own container. This remains reliable in split views, collapsible panels, and responsive layouts.