card-16-paper-grid-poster
shape-05-text-selection
Sélection de texte à poignées
Accentuer UN mot dans une phrase en imitant la sélection de texte d'un téléphone — bandeau translucide, barre verticale à chaque bout, pastille en haut à gauche et en bas à droite — pour que l'accent se lise comme un geste du lecteur et non comme un surligneur de bureau.
shapesocialwebslide860×200px10 benchmarks
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
Un seul mot ou groupe court à faire ressortir dans une chute de post social ou de page. L'accent est plus vivant qu'un `<mark>` et plus sobre qu'un aplat : il suggère que quelqu'un vient de poser le doigt sur ce mot.
Éviter quand
La sélection porterait sur plus d'une ligne (le bandeau perd sa lecture de sélection et écrase la hiérarchie), le mot est en fin de phrase avec sa ponctuation (le point doit rester HORS du span, sinon la poignée le mange), ou la même carte porte déjà un aplat d'accent — deux accents dans une zone se neutralisent.
Notes
Le placement des poignées a été tenté TROIS fois en JavaScript le 25/08/2026 — `getClientRects()`, puis le dernier rect de la dernière ligne, puis `getBoundingClientRect()` — et les trois ont posé la barre droite SUR la dernière lettre : les rects d'un inline ne coïncident pas avec le bord du fond réellement peint (padding + `box-decoration-break: clone`), et l'écart de ~26 px ne se voyait dans aucune mesure. La seule construction juste est celle-ci : le span devient le repère (`position: relative`), les poignées sont ses enfants absolus, et le décalage vaut EXACTEMENT l'épaisseur de barre — donc elles restent collées quelle que soit l'échelle. Corollaire de composition : la ponctuation finale reste hors du span, sinon la poignée droite la recouvre. L'asymétrie des pastilles (haut-gauche / bas-droite) n'est pas décorative : c'est elle qui fait reconnaître une sélection système plutôt qu'un surlignage — les mettre toutes deux en haut casse la lecture sans casser aucune mesure.
Mots-clés
Benchmarks — la géométrie, en assertions vérifiables
Rejouables par node bin/check.mjs shape-05-text-selection : le pattern se prouve, il ne se croit pas.
| assertion | mesure | attendu |
|---|---|---|
| BARRES COLLÉES : le bord droit de la poignée gauche touche le bord gauche du bandeau | Math.abs(box('.vl-text-selection__h--a').right - box('.vl-text-selection__sel').left) | ≤ 0.6 |
| BARRES COLLÉES : le bord gauche de la poignée droite touche le bord droit du bandeau | Math.abs(box('.vl-text-selection__h--b').left - box('.vl-text-selection__sel').right) | ≤ 0.6 |
| la barre court sur TOUTE la hauteur du bandeau | box('.vl-text-selection__h--a').h / box('.vl-text-selection__sel').h | 1 ± 0.02 |
| pastille = 5 × l'épaisseur de barre | parseFloat(cs('.vl-text-selection','--ts-dot')) / parseFloat(cs('.vl-text-selection','--ts-bar')) | 5 ± 0.35 |
| ASYMÉTRIE : la pastille gauche est en haut, à demi-diamètre au-dessus du bandeau | Math.abs(parseFloat(cs('.vl-text-selection__h--a','--ts-dot')) / 2 + parseFloat(getComputedStyle($('.vl-text-selection__h--a'),'::before').top)) | ≤ 1.2 |
| LE BANDEAU EST TRANSLUCIDE — un aplat plein cesserait de se lire comme une sélection | (function(){var p=cs('.vl-text-selection__sel','backgroundColor').replace(/[^0-9.,]/g,'').split(',');return p.length===4?parseFloat(p[3]):1;})() | 0.25 → 0.75 |
| le bandeau survit à un passage à la ligne : ses décorations sont clonées | cs('.vl-text-selection__sel','boxDecorationBreak') === 'clone' || cs('.vl-text-selection__sel','-webkit-box-decoration-break') === 'clone' ? 1 : 0 | 1 |
| les poignées ne sont PAS placées par un script : elles sont en position absolue dans le span | cs('.vl-text-selection__h--a','position') === 'absolute' && cs('.vl-text-selection__sel','position') === 'relative' ? 1 : 0 | 1 |
| contraste de la phrase porteuse ≥ 4,5 | contrast('.vl-text-selection__p') | ≥ 4.5 |
| aucun débordement du fragment | overflow('.vl-text-selection') | ≤ 0 |
Le code
patterns/shape-05-text-selection.html
Télécharger<!-- shape-05-text-selection — fragment autonome. Couleurs via --vl-* uniquement, aucune valeur en dur. -->
<div class="vl-text-selection" lang="fr">
<p class="vl-text-selection__p">Reste à bâtir <span class="vl-text-selection__sel"><i class="vl-text-selection__h vl-text-selection__h--a"></i>l'architecture<i class="vl-text-selection__h vl-text-selection__h--b"></i></span> qui les met au travail.</p>
</div>
<style>
.vl-text-selection {
--ts-bar: var(--vl-handle-bar, 6px);
--ts-dot: var(--vl-handle-dot, 30px);
width: 860px;
box-sizing: border-box;
font-family: Inter, system-ui, -apple-system, "Segoe UI", sans-serif;
background-color: var(--vl-bg);
color: var(--vl-ink);
}
.vl-text-selection__p {
margin: 0;
font-weight: 800; font-size: 76px; line-height: 1.24; letter-spacing: -1.4px;
}
/* Le bandeau : `box-decoration-break: clone` pour qu'un passage à la ligne garde ses deux bouts. */
.vl-text-selection__sel {
position: relative;
margin-right: 10px;
padding: .04em .10em;
border-radius: 4px;
background-color: var(--vl-select);
-webkit-box-decoration-break: clone;
box-decoration-break: clone;
}
/* Les poignées sont ANCRÉES AU SPAN — jamais placées par un script qui mesure des rects : les
rects d'un inline ne coïncident pas avec le bord du fond peint, et la barre se pose alors SUR
la dernière lettre. Collées : la barre occupe exactement sa largeur hors du bandeau. */
.vl-text-selection__h {
position: absolute; top: 0; height: 100%;
width: var(--ts-bar);
background: var(--vl-handle);
border-radius: 1px;
}
.vl-text-selection__h--a { left: calc(var(--ts-bar) * -1); }
.vl-text-selection__h--b { right: calc(var(--ts-bar) * -1); }
.vl-text-selection__h--a::before,
.vl-text-selection__h--b::after {
content: ''; position: absolute;
left: calc((var(--ts-dot) - var(--ts-bar)) / -2);
width: var(--ts-dot); height: var(--ts-dot);
border-radius: 50%;
background: var(--vl-handle);
}
/* L'ASYMÉTRIE EST LA SIGNATURE : pastille en HAUT à gauche, en BAS à droite — c'est ce que fait
un système d'exploitation, et c'est ce qui distingue une sélection d'un simple surlignage. */
.vl-text-selection__h--a::before { top: calc(var(--ts-dot) / -2); }
.vl-text-selection__h--b::after { bottom: calc(var(--ts-dot) / -2); }
</style>
systems/ref-24-finengy-paper-selection.json
Télécharger:root {
--vl-bg: #F6F5F1;
--vl-ink: #142A4E;
--vl-grid: rgba(20,42,78,0.16);
--vl-grid-step: 27px;
--vl-glow: rgba(255,255,255,0.5);
--vl-accent: #FDC300;
--vl-select: rgba(253,195,0,0.55);
--vl-handle: #142A4E;
--vl-select-alt: rgba(124,138,255,0.42);
--vl-handle-alt: #2C4BE8;
--vl-handle-bar: 6px;
--vl-handle-dot: 30px;
--vl-margin-x: 40px;
--vl-margin-top: 52px;
--vl-footer: 196px;
}
les métadonnées — patterns/shape-05-text-selection.json (télécharger)
{
"name": "Sélection de texte à poignées",
"family": "shape",
"ref": "ref-24-finengy-paper-selection",
"intent": "Accentuer UN mot dans une phrase en imitant la sélection de texte d'un téléphone — bandeau translucide, barre verticale à chaque bout, pastille en haut à gauche et en bas à droite — pour que l'accent se lise comme un geste du lecteur et non comme un surligneur de bureau.",
"when_to_use": "Un seul mot ou groupe court à faire ressortir dans une chute de post social ou de page. L'accent est plus vivant qu'un `<mark>` et plus sobre qu'un aplat : il suggère que quelqu'un vient de poser le doigt sur ce mot.",
"avoid_when": "La sélection porterait sur plus d'une ligne (le bandeau perd sa lecture de sélection et écrase la hiérarchie), le mot est en fin de phrase avec sa ponctuation (le point doit rester HORS du span, sinon la poignée le mange), ou la même carte porte déjà un aplat d'accent — deux accents dans une zone se neutralisent.",
"media": [
"social",
"web",
"slide"
],
"tags": [
"selection",
"surlignage",
"highlight",
"marqueur",
"poignee",
"handle",
"mobile",
"telephone",
"ios",
"accent",
"mot",
"inline",
"texte",
"bandeau",
"translucide",
"geste"
],
"vars": [
{
"name": "--vl-select",
"role": "aplat du bandeau — TRANSLUCIDE : c'est ce qui le fait lire comme une sélection et non comme un fond",
"default": "rgba(253,195,0,0.55)"
},
{
"name": "--vl-handle",
"role": "barres et pastilles — pleines, dans l'encre, jamais dans la couleur du bandeau",
"default": "#142A4E"
},
{
"name": "--vl-handle-bar",
"role": "épaisseur de la barre verticale ; c'est elle qui fixe le décalage hors du bandeau",
"default": "6px"
},
{
"name": "--vl-handle-dot",
"role": "diamètre de la pastille — 5 × l'épaisseur de barre",
"default": "30px"
},
{
"name": "--vl-bg",
"role": "sol sous le texte, contre lequel le contraste se mesure",
"default": "#F6F5F1"
},
{
"name": "--vl-ink",
"role": "encre de la phrase porteuse",
"default": "#142A4E"
}
],
"slots": [
"phrase",
"mot-selectionne"
],
"geometry": {
"root": ".vl-text-selection",
"frame": [
860,
200
],
"ratios": {
"dot_over_bar": 5,
"bar_over_fontsize": 0.079,
"pad_x_over_fontsize": 0.1
},
"type_px": {
"phrase": 76
},
"pad_ratio": {
"top": 0,
"x": 0,
"bottom": 0
}
},
"benchmarks": [
{
"name": "BARRES COLLÉES : le bord droit de la poignée gauche touche le bord gauche du bandeau",
"measure": "Math.abs(box('.vl-text-selection__h--a').right - box('.vl-text-selection__sel').left)",
"max": 0.6
},
{
"name": "BARRES COLLÉES : le bord gauche de la poignée droite touche le bord droit du bandeau",
"measure": "Math.abs(box('.vl-text-selection__h--b').left - box('.vl-text-selection__sel').right)",
"max": 0.6
},
{
"name": "la barre court sur TOUTE la hauteur du bandeau",
"measure": "box('.vl-text-selection__h--a').h / box('.vl-text-selection__sel').h",
"expect": 1,
"tol": 0.02
},
{
"name": "pastille = 5 × l'épaisseur de barre",
"measure": "parseFloat(cs('.vl-text-selection','--ts-dot')) / parseFloat(cs('.vl-text-selection','--ts-bar'))",
"expect": 5,
"tol": 0.35
},
{
"name": "ASYMÉTRIE : la pastille gauche est en haut, à demi-diamètre au-dessus du bandeau",
"measure": "Math.abs(parseFloat(cs('.vl-text-selection__h--a','--ts-dot')) / 2 + parseFloat(getComputedStyle($('.vl-text-selection__h--a'),'::before').top))",
"max": 1.2
},
{
"name": "LE BANDEAU EST TRANSLUCIDE — un aplat plein cesserait de se lire comme une sélection",
"measure": "(function(){var p=cs('.vl-text-selection__sel','backgroundColor').replace(/[^0-9.,]/g,'').split(',');return p.length===4?parseFloat(p[3]):1;})()",
"min": 0.25,
"max": 0.75
},
{
"name": "le bandeau survit à un passage à la ligne : ses décorations sont clonées",
"measure": "cs('.vl-text-selection__sel','boxDecorationBreak') === 'clone' || cs('.vl-text-selection__sel','-webkit-box-decoration-break') === 'clone' ? 1 : 0",
"expect": 1
},
{
"name": "les poignées ne sont PAS placées par un script : elles sont en position absolue dans le span",
"measure": "cs('.vl-text-selection__h--a','position') === 'absolute' && cs('.vl-text-selection__sel','position') === 'relative' ? 1 : 0",
"expect": 1
},
{
"name": "contraste de la phrase porteuse ≥ 4,5",
"measure": "contrast('.vl-text-selection__p')",
"min": 4.5
},
{
"name": "aucun débordement du fragment",
"measure": "overflow('.vl-text-selection')",
"max": 0
}
],
"notes": "Le placement des poignées a été tenté TROIS fois en JavaScript le 25/08/2026 — `getClientRects()`, puis le dernier rect de la dernière ligne, puis `getBoundingClientRect()` — et les trois ont posé la barre droite SUR la dernière lettre : les rects d'un inline ne coïncident pas avec le bord du fond réellement peint (padding + `box-decoration-break: clone`), et l'écart de ~26 px ne se voyait dans aucune mesure. La seule construction juste est celle-ci : le span devient le repère (`position: relative`), les poignées sont ses enfants absolus, et le décalage vaut EXACTEMENT l'épaisseur de barre — donc elles restent collées quelle que soit l'échelle. Corollaire de composition : la ponctuation finale reste hors du span, sinon la poignée droite la recouvre. L'asymétrie des pastilles (haut-gauche / bas-droite) n'est pas décorative : c'est elle qui fait reconnaître une sélection système plutôt qu'un surlignage — les mettre toutes deux en haut casse la lecture sans casser aucune mesure.",
"id": "shape-05-text-selection"
}
À côté
shape-02-teardrop-quadrant
Carré arrondi à un seul coin droit
shape-03-stadium-track
Rail stadium à enfant emboîté
shape-04-asterisk-mark
Astérisque de marque, six branches
shape-notched-corner