Components / Clinical

Growth chart

Percentile curves for a child's weight, length/height and head circumference, with measurements plotted on top. Hover over or tab to a point for its percentile and z-score.

Loading the WHO tables…

Fictional measurements on the WHO Child Growth Standards, © World Health Organization. Not for clinical use without your own validation.

Installation

In a project set up as in Installation, run:

bunx shadcn@4.22.1 add https://organui.com/r/growth-chart.json

Or by name: bunx shadcn@4.22.1 add @organui/growth-chart.

One file installs into your UI components directory. The chart is plain SVG drawn with your theme tokens, so it adds no charting library. It contains no growth data.

View registry item JSON

Usage

import {
  GrowthChart,
  ageInMonths,
  growthStandardsFromAnthro,
} from "@/components/ui/growth-chart"

const birth = new Date("2024-03-02")
const visits = [
  { date: new Date("2024-09-04"), kg: 7.4 },
  { date: new Date("2025-03-05"), kg: 9.1 },
]

// weightTable is the text of a weight-for-age table you host yourself.
export function WeightChart({ weightTable }: { weightTable: string }) {
  const standards = growthStandardsFromAnthro({ weight: weightTable })
  return (
    <GrowthChart
      standards={standards}
      measure="weight"
      sex="female"
      measurements={visits.map((visit) => ({
        ageMonths: ageInMonths(birth, visit.date),
        value: visit.kg,
      }))}
    />
  )
}

Set measure to weight (kilograms), length (centimetres) or head (head circumference, centimetres), and sex to female or male. Each measurement is an ageMonths and a value; use ageInMonths to convert dates the way WHO counts them. ageRange defaults to 0 to 24 months. percentiles defaults to WHO's 3rd, 15th, 50th, 85th and 97th; the outer pairs are shaded as bands. Measurements outside the range or the tables are left out.

Growth standards and their licence

The component ships no reference data, because the tables are not OrganUI's to license. You pass standards: LMS parameters by completed month for each measure and sex. length is used below 24 months and height from 24, so the WHO curve steps down by about 0.7 cm at two years, where children start being measured standing.

Where to get the tables

The WHO Child Growth Standards (birth to 5 years) are published by WHO, and its anthro package carries them as daily tables in data-raw/growthstandards (weianthro.txt, lenanthro.txt and hcanthro.txt). Host copies yourself and pass their text to growthStandardsFromAnthro, which samples them by month as WHO's monthly tables do.

The tables are © World Health Organization. The anthro package distributes them under GPL-3, and WHO's copyright policy requires its permission for commercial use of its materials. Check those terms before you use them in your product.

The CDC 2000 growth charts publish LMS files for ages 2 to 20 years by half month. Resample them to whole months and pass them as standards yourself; check CDC's terms for your use as well.

The example above fetches WHO's tables from WHO's repository at runtime, with a loader that lives on this site only. The installed component contains no data and makes no network requests.

import { GrowthChart, type GrowthStandards } from "@/components/ui/growth-chart"

// [L, M, S] for each completed month from `start`, for both sexes.
const standards: GrowthStandards = {
  head: {
    female: { start: 0, lms: headGirls },
    male: { start: 0, lms: headBoys },
  },
}

Percentiles and z-scores

import { growthZScore, zToPercentile, formatPercentile }
  from "@/components/ui/growth-chart"

const z = growthZScore(standards, "length", "male", 18, 80.1) // -0.80
formatPercentile(zToPercentile(z!)) // "21st", on the WHO standards

The file also exports the calculations the chart uses: growthLms, growthZScore, growthValueAt, zToPercentile, percentileToZ, formatPercentile and formatAge. Z-scores use the LMS method, and weight beyond ±3 SD uses WHO's restricted extrapolation, matching the WHO Anthro software.

Accessibility

Each measurement is a focusable point whose name gives its age, value and percentile, and a visually hidden table after the chart lists every measurement for screen readers. Colors come from your primary, muted-foreground, border and popover tokens.

A charting aid, not a diagnostic device. Validate it, and the reference you choose, for your own clinical use.