list-05-vitals-strip

Bandeau de constantes, sans carte ni filet

Aligner cinq mesures hétérogènes sur une seule ligne SANS aucun séparateur : chacune est un couple micro-libellé / valeur, l'unité étant un cran plus petite ET plus claire que le nombre qu'elle suit. C'est ce double affaiblissement de l'unité — taille et encre — qui permet de lire cinq valeurs d'affilée sans filet, sans carte et sans que l'œil confonde un nombre avec l'unité de son voisin.

listwebslide1040×62px14 benchmarks

Télécharger le .zip

Le fragment RÉEL, dans son propre document, sur le sol de sa charte — pas une image. Ce que vous voyez est exactement ce que vous collerez.

Employer quand

Bandeau d'état en tête d'une fiche : constantes d'un patient, indicateurs d'une machine, chiffres-clés d'un dossier. La première mesure peut être qualitative et prendre un corps plus grand — c'est le sujet de la fiche, pas une valeur de plus.

Éviter quand

Les valeurs sont comparables entre elles (une rangée de cartes ou un tableau dit mieux la comparaison), il y en a plus de six (le bandeau se met à défiler et perd son unique atout, la lecture d'un seul coup d'œil), ou l'une d'elles est en alerte : ce bandeau n'a aucune ressource pour le dire, et l'y ajouter demande une couleur que le système réserve ailleurs.

Notes

Le pattern tient à une seule idée, et deux benchmarks la mesurent séparément : l'unité est affaiblie DEUX FOIS, en taille et en encre. Un seul des deux affaiblissements ne suffit pas — une unité petite mais à l'encre pleine se met à compter comme un second nombre, une unité claire mais de même corps se lit comme un mot de la phrase suivante. C'est le cumul qui produit l'effet, d'où deux assertions et non une. Les deux assertions négatives (aucun filet, aucun fond) sont ce qui distingue ce bandeau d'une rangée de cartes. Elles sont écrites sur TOUS les enfants et pas sur un témoin : c'est exactement le genre de règle qu'on casse en ajoutant un fond « juste sur la mesure importante ». Le vide entre deux mesures est mesuré en CORPS de valeur (≥ 1,4) et non en pixels : c'est ce vide qui remplace le séparateur, et il doit donc grandir avec la typographie. Exprimé en pixels, il aurait cessé de séparer dès le premier changement d'échelle.

Mots-clés

constantesvitalsbandeaustripmesureunitemicro-libellefichedossierkpisans-filet

Benchmarks — la géométrie, en assertions vérifiables

Rejouables par node bin/check.mjs list-05-vitals-strip : le pattern se prouve, il ne se croit pas.

assertionmesureattendu
une seule ligne : toutes les mesures partagent leur ligne de base basse(() => { const b = [...document.querySelectorAll('.vl-vitals > *')].map((e) => e.getBoundingClientRect().bottom); return Math.max(...b) - Math.min(...b); })()≤ 1.5
AUCUN séparateur : pas un filet entre deux mesures[...document.querySelectorAll('.vl-vitals > *')].reduce((m, e) => m + parseFloat(getComputedStyle(e).borderRightWidth || 0), 0)0 ± 0
… et pas de fond non plus : la mesure n'est pas une carte[...document.querySelectorAll('.vl-vitals > *')].filter((e) => { const p = (getComputedStyle(e).backgroundColor.match(/[\d.]+/g) || []).map(Number); return p.length === 4 ? p[3] > 0 : p.length === 3; }).length0 ± 0
le vide qui sépare deux mesures vaut au moins 1,4 corps de valeur — c'est lui, le séparateurnum('.vl-vitals','columnGap') / num('.vl-vitals__item:nth-child(2) .vl-vitals__value','fontSize')≥ 1.4
L'UNITÉ EST PLUS PETITE que le nombre qu'elle suit — au plus la moitiénum('.vl-vitals__item:nth-child(2) .vl-vitals__unit','fontSize') / num('.vl-vitals__item:nth-child(2) .vl-vitals__value','fontSize')≤ 0.55
… ET PLUS CLAIRE : c'est le double affaiblissement qui rend le bandeau lisible sans filetlum(parseRgb(cs('.vl-vitals__item:nth-child(2) .vl-vitals__unit','color'))) - lum(parseRgb(cs('.vl-vitals__item:nth-child(2) .vl-vitals__value','color')))≥ 0.05
le micro-libellé est AU-DESSUS de sa valeur, jamais à côtébox('.vl-vitals__item:nth-child(2) .vl-vitals__value').top - box('.vl-vitals__item:nth-child(2) .vl-vitals__label').bottom0 → 12
… et calé sur le même fer à gaucheMath.abs(box('.vl-vitals__item:nth-child(2) .vl-vitals__label').left - box('.vl-vitals__item:nth-child(2) .vl-vitals__value').left)≤ 1.5
le micro-libellé reste un cadrage : au plus la moitié du corps de sa valeurnum('.vl-vitals__item:nth-child(2) .vl-vitals__label','fontSize') / num('.vl-vitals__item:nth-child(2) .vl-vitals__value','fontSize')≤ 0.55
la mesure de tête est plus grande que les autres — c'est le sujet de la fichenum('.vl-vitals__lead .vl-vitals__value','fontSize') / num('.vl-vitals__item:nth-child(2) .vl-vitals__value','fontSize')≥ 1.15
… mais elle ne fait pas un titre : au plus 1,6 foisnum('.vl-vitals__lead .vl-vitals__value','fontSize') / num('.vl-vitals__item:nth-child(2) .vl-vitals__value','fontSize')≤ 1.6
contraste d'une valeur ≥ 4,5contrast('.vl-vitals__item:nth-child(2) .vl-vitals__value')≥ 4.5
contraste du micro-libellé ≥ 4,5 — c'est lui qui plafonnecontrast('.vl-vitals__item:nth-child(2) .vl-vitals__label')≥ 4.5
aucun débordement du bandeauoverflow('.vl-vitals')≤ 0

Le code

fragment — patterns/list-05-vitals-strip.html Télécharger
<!-- list-05-vitals-strip — cinq mesures sur une ligne, sans un seul séparateur.
     Couleurs via --vl-* uniquement.

     L'UNITÉ EST AFFAIBLIE DEUX FOIS : en taille (la moitié du nombre) ET en encre (le gris du
     micro-libellé). Un seul des deux ne suffit pas — une unité petite mais à l'encre pleine
     compte comme un second nombre, une unité claire mais de même corps se lit comme le début
     de la mesure suivante. C'est le cumul qui permet de se passer de filet.

     La première mesure est qualitative et prend un corps plus grand : c'est le SUJET de la
     fiche, pas une valeur de plus. Elle reste sous 1,6 fois — au-delà, c'est un titre. -->
<div class="vl-vitals">

  <span class="vl-vitals__item vl-vitals__lead">
    <span class="vl-vitals__label">Diagnosys</span>
    <span class="vl-vitals__value">Hypertension</span>
  </span>

  <span class="vl-vitals__item">
    <span class="vl-vitals__label">Heart Rate</span>
    <span class="vl-vitals__value">89<span class="vl-vitals__unit">bpm</span></span>
  </span>

  <span class="vl-vitals__item">
    <span class="vl-vitals__label">Pressure</span>
    <span class="vl-vitals__value">100<span class="vl-vitals__unit">/67</span></span>
  </span>

  <span class="vl-vitals__item">
    <span class="vl-vitals__label">Oxygen</span>
    <span class="vl-vitals__value">98<span class="vl-vitals__unit">%</span></span>
  </span>

  <span class="vl-vitals__item">
    <span class="vl-vitals__label">Temperature</span>
    <span class="vl-vitals__value">36.8<span class="vl-vitals__unit">°C</span></span>
  </span>

</div>

<style>
.vl-vitals {
  width: 1040px;
  box-sizing: border-box;
  display: flex; align-items: flex-end;
  /* Le vide EST le séparateur. Il est donc exprimé en corps de valeur, jamais en pixels :
     posé en pixels, il cesserait de séparer au premier changement d'échelle. */
  column-gap: 46px;
  color: var(--vl-ink);
  font-family: Montserrat, Poppins, Inter, "Helvetica Neue", Arial, sans-serif;
}
/* Ni fond, ni filet, ni rayon : une mesure n'est pas une carte. Ajouter un fond « juste sur
   la mesure importante » est exactement ce que les deux assertions négatives interdisent. */
.vl-vitals__item { display: flex; flex-direction: column; }
.vl-vitals__label {
  font-size: 14px; line-height: 1.2; color: var(--vl-ink-soft);
  margin-bottom: 3px;
}
/* line-height 1,2 et pas 1 : à 1, la boîte inline est plus courte que le glyphe et
   `scrollHeight` dépasse `clientHeight` de 3 px — un débordement invisible à l'œil, mais que
   le contrôle voit, et il a raison : le bandeau posé dans une rangée serrée rognerait. */
.vl-vitals__value { font-size: 30px; line-height: 1.2; font-weight: 600; letter-spacing: -0.01em; }
.vl-vitals__unit {
  font-size: 15px; font-weight: 500; color: var(--vl-ink-soft);
  margin-left: 3px;
}
.vl-vitals__lead .vl-vitals__value { font-size: 37px; font-weight: 500; }
</style>
tokens de la charte — systems/ref-19-acid-clinical-timeline.json Télécharger
:root {
  --vl-veil: #4A4A48;
  --vl-veil-deep: #1B1D1D;
  --vl-sheet: #DFDFD7;
  --vl-module: #F0EFEB;
  --vl-module-hi: #FFFFFF;
  --vl-accent: #F5FE49;
  --vl-alert: #E8756B;
  --vl-recover: #7FA88C;
  --vl-ink: #262C2C;
  --vl-ink-soft: #5F615E;
  --vl-on-veil: #FFFFFF;
  --vl-on-veil-soft: rgba(255,255,255,0.72);
  --vl-radius-sheet: 34px;
  --vl-radius-module: 22px;
  --vl-radius-pill: 999px;
  --vl-notch: 26px;
  --vl-bleed: 20px;
  --vl-tabbar-h: 106px;
  --vl-ribbon-h: 74px;
  --vl-gutter: 18px;
  --vl-margin: 34px;
}
les métadonnées — patterns/list-05-vitals-strip.json (télécharger)
{
  "name": "Bandeau de constantes, sans carte ni filet",
  "family": "list",
  "ref": "ref-19-acid-clinical-timeline",
  "intent": "Aligner cinq mesures hétérogènes sur une seule ligne SANS aucun séparateur : chacune est un couple micro-libellé / valeur, l'unité étant un cran plus petite ET plus claire que le nombre qu'elle suit. C'est ce double affaiblissement de l'unité — taille et encre — qui permet de lire cinq valeurs d'affilée sans filet, sans carte et sans que l'œil confonde un nombre avec l'unité de son voisin.",
  "when_to_use": "Bandeau d'état en tête d'une fiche : constantes d'un patient, indicateurs d'une machine, chiffres-clés d'un dossier. La première mesure peut être qualitative et prendre un corps plus grand — c'est le sujet de la fiche, pas une valeur de plus.",
  "avoid_when": "Les valeurs sont comparables entre elles (une rangée de cartes ou un tableau dit mieux la comparaison), il y en a plus de six (le bandeau se met à défiler et perd son unique atout, la lecture d'un seul coup d'œil), ou l'une d'elles est en alerte : ce bandeau n'a aucune ressource pour le dire, et l'y ajouter demande une couleur que le système réserve ailleurs.",
  "media": [
    "web",
    "slide"
  ],
  "tags": [
    "constantes",
    "vitals",
    "bandeau",
    "strip",
    "mesure",
    "unite",
    "micro-libelle",
    "fiche",
    "dossier",
    "kpi",
    "sans-filet"
  ],
  "vars": [
    {
      "name": "--vl-ink",
      "role": "valeur",
      "default": "#262C2C"
    },
    {
      "name": "--vl-ink-soft",
      "role": "micro-libellé ET unité — la même encre affaiblie pour les deux",
      "default": "#5F615E"
    }
  ],
  "slots": [
    "items"
  ],
  "geometry": {
    "root": ".vl-vitals",
    "frame": [
      1040,
      62
    ],
    "ratios": {
      "gap_over_width": 0.051,
      "unit_over_value": 0.5,
      "label_over_value": 0.467,
      "lead_over_value": 1.233
    },
    "type_px": {
      "lead": 37,
      "value": 30,
      "unit": 15,
      "label": 14
    },
    "pad_ratio": {
      "top": 0,
      "x": 0,
      "bottom": 0
    }
  },
  "benchmarks": [
    {
      "name": "une seule ligne : toutes les mesures partagent leur ligne de base basse",
      "measure": "(() => { const b = [...document.querySelectorAll('.vl-vitals > *')].map((e) => e.getBoundingClientRect().bottom); return Math.max(...b) - Math.min(...b); })()",
      "max": 1.5
    },
    {
      "name": "AUCUN séparateur : pas un filet entre deux mesures",
      "measure": "[...document.querySelectorAll('.vl-vitals > *')].reduce((m, e) => m + parseFloat(getComputedStyle(e).borderRightWidth || 0), 0)",
      "expect": 0,
      "tol": 0
    },
    {
      "name": "… et pas de fond non plus : la mesure n'est pas une carte",
      "measure": "[...document.querySelectorAll('.vl-vitals > *')].filter((e) => { const p = (getComputedStyle(e).backgroundColor.match(/[\\d.]+/g) || []).map(Number); return p.length === 4 ? p[3] > 0 : p.length === 3; }).length",
      "expect": 0,
      "tol": 0
    },
    {
      "name": "le vide qui sépare deux mesures vaut au moins 1,4 corps de valeur — c'est lui, le séparateur",
      "measure": "num('.vl-vitals','columnGap') / num('.vl-vitals__item:nth-child(2) .vl-vitals__value','fontSize')",
      "min": 1.4
    },
    {
      "name": "L'UNITÉ EST PLUS PETITE que le nombre qu'elle suit — au plus la moitié",
      "measure": "num('.vl-vitals__item:nth-child(2) .vl-vitals__unit','fontSize') / num('.vl-vitals__item:nth-child(2) .vl-vitals__value','fontSize')",
      "max": 0.55
    },
    {
      "name": "… ET PLUS CLAIRE : c'est le double affaiblissement qui rend le bandeau lisible sans filet",
      "measure": "lum(parseRgb(cs('.vl-vitals__item:nth-child(2) .vl-vitals__unit','color'))) - lum(parseRgb(cs('.vl-vitals__item:nth-child(2) .vl-vitals__value','color')))",
      "min": 0.05
    },
    {
      "name": "le micro-libellé est AU-DESSUS de sa valeur, jamais à côté",
      "measure": "box('.vl-vitals__item:nth-child(2) .vl-vitals__value').top - box('.vl-vitals__item:nth-child(2) .vl-vitals__label').bottom",
      "min": 0,
      "max": 12
    },
    {
      "name": "… et calé sur le même fer à gauche",
      "measure": "Math.abs(box('.vl-vitals__item:nth-child(2) .vl-vitals__label').left - box('.vl-vitals__item:nth-child(2) .vl-vitals__value').left)",
      "max": 1.5
    },
    {
      "name": "le micro-libellé reste un cadrage : au plus la moitié du corps de sa valeur",
      "measure": "num('.vl-vitals__item:nth-child(2) .vl-vitals__label','fontSize') / num('.vl-vitals__item:nth-child(2) .vl-vitals__value','fontSize')",
      "max": 0.55
    },
    {
      "name": "la mesure de tête est plus grande que les autres — c'est le sujet de la fiche",
      "measure": "num('.vl-vitals__lead .vl-vitals__value','fontSize') / num('.vl-vitals__item:nth-child(2) .vl-vitals__value','fontSize')",
      "min": 1.15
    },
    {
      "name": "… mais elle ne fait pas un titre : au plus 1,6 fois",
      "measure": "num('.vl-vitals__lead .vl-vitals__value','fontSize') / num('.vl-vitals__item:nth-child(2) .vl-vitals__value','fontSize')",
      "max": 1.6
    },
    {
      "name": "contraste d'une valeur ≥ 4,5",
      "measure": "contrast('.vl-vitals__item:nth-child(2) .vl-vitals__value')",
      "min": 4.5
    },
    {
      "name": "contraste du micro-libellé ≥ 4,5 — c'est lui qui plafonne",
      "measure": "contrast('.vl-vitals__item:nth-child(2) .vl-vitals__label')",
      "min": 4.5
    },
    {
      "name": "aucun débordement du bandeau",
      "measure": "overflow('.vl-vitals')",
      "max": 0
    }
  ],
  "notes": "Le pattern tient à une seule idée, et deux benchmarks la mesurent séparément : l'unité est affaiblie DEUX FOIS, en taille et en encre. Un seul des deux affaiblissements ne suffit pas — une unité petite mais à l'encre pleine se met à compter comme un second nombre, une unité claire mais de même corps se lit comme un mot de la phrase suivante. C'est le cumul qui produit l'effet, d'où deux assertions et non une.\n\nLes deux assertions négatives (aucun filet, aucun fond) sont ce qui distingue ce bandeau d'une rangée de cartes. Elles sont écrites sur TOUS les enfants et pas sur un témoin : c'est exactement le genre de règle qu'on casse en ajoutant un fond « juste sur la mesure importante ».\n\nLe vide entre deux mesures est mesuré en CORPS de valeur (≥ 1,4) et non en pixels : c'est ce vide qui remplace le séparateur, et il doit donc grandir avec la typographie. Exprimé en pixels, il aurait cessé de séparer dès le premier changement d'échelle.",
  "id": "list-05-vitals-strip"
}

À côté