En bref
Un cahier d’activités pour des enfants de huit ans sur les animaux vertébrés. Les questions et leurs réponses sont écrites dans le texte ; un seul style décide de l’aspect de chaque activité sur la page.
Ce que vous allez composer
L’unité 5 d’un cahier d’activités de sciences de CE2, au format A4 : Animals with backbones, les animaux vertébrés. L’ouverture pose l’unité dans un bandeau vert au-dessus d’une peinture de mare ; viennent ensuite onze activités, chacune avec son numéro dans une pastille verte et un pictogramme de crayon, de bulle ou de binôme. Une banque de mots dans un encadré teinté à bord tireté, des phrases à cocher T ou F, des animaux à relier à leur groupe par un trait, des mots à entourer dans une phrase puis dans un court texte, les étapes de la vie d’une grenouille à numéroter, des mots mêlés, des animaux à classer, une question ouverte sur des lignes et une autre sur quadrillage. Une édition espagnole imprime la même unité comme la composent les écoles d’Espagne, avec V et F et une con flechas. Trois peintures générées avec un modèle de diffusion l’illustrent.
Cette recette répond à
- Comment composer une page de cahier d'activités : numéros en pastille, banque de mots, vrai ou faux, relie ?
- Comment mettre des pictogrammes (écris, parle, à deux) à côté du numéro d'un exercice ?
- Comment construire une fiche d’exercices : lignes à remplir, cases de réponse, banques de mots, listes de contrôle ?
La réponse courte
// The Markdown says what each activity asks (:::exercise, [[answers]], - A -> B, - [x]);
// this style says how a Spanish workbook prints it: the number in a disc of the unit
// colour, the instruction in bold, blanks on a line, V/F boxes at the line's end, dots to
// join, the bank in a tinted box, squared paper for writing and the activity icons.
const icon = (id, alt) => ({ resourceId: `icon-${id}`, alt, size: 1.05 });
const actividad = {
id: 'actividad',
number: { shape: 'disc', background: col('unit'), color: col('paper'),
fontFamily: DISPLAY, fontSize: em(1.05), fontWeight: 800 },
instruction: { bold: true, color: col('ink') },
options: { marker: 'circle' },
blank: { look: 'line', color: col('ink'), weight: pt(0.75), extra: em(2) },
trueFalse: { look: 'boxes' }, // V F in Spanish, T F in English: the language's own words
match: { look: 'dots', gap: em(7), dotSize: em(0.42), color: col('unit') },
bank: { box: 'banco', order: 'alpha', separator: ' ' },
area: { kind: 'lines', spacing: mm(9), color: col('rule'), weight: pt(0.6) },
grid: { cell: mm(9.5), fontFamily: DISPLAY, fontSize: pt(13), rule: col('rule'),
color: col('ink') },
icons: {
escribe: icon('write', t({ es: 'Escribe', en: 'Write' })),
oral: icon('oral', t({ es: 'Actividad oral', en: 'Speaking' })),
pareja: icon('pair', t({ es: 'En pareja', en: 'In pairs' })),
},
marginTop: mm(7), marginBottom: mm(2), itemSpacing: em(0.8),
};
// The same activity written on squared paper (cuadrícula): `style="cuadricula"`.
const cuadricula = { id: 'cuadricula', extends: 'actividad',
area: { kind: 'grid', spacing: mm(5), weight: pt(0.4) } };
Ingrédients
- Fonctionnalités
- Styles d'exerciceTextes à trous et banques de motsRelier et classerExercicesChoix et vrai ou fauxMarquer des motsRemettre dans l'ordreMots mêlés et mots croisésQuestions ouvertes et zones d'écritureOuvertures composéesAttributs de titreEncadrésPalette de couleurs sémantiqueMarges en miroirTitres courants selon le rôle de la pagePages sur un canvasExport PDFFigures et tableaux comme ressourcesTypes de ressource personnalisés
- Utilise aussi
- Encadrés qui se coupent ou restent entiersCorrigésDes figures exactement iciStyles de paragraphePolices intégrées au PDF
- Typographie
- Atkinson Hyperlegible Next, Grandstander (SIL OFL 1.1)
- Ressources
charca-1088.jpgciclo-1088.jpgnina-720.jpg- Animals at a pond: a frog, a kingfisher, a trout, a turtle and a rabbit. (Generated With Diffusion Models, original)
- Five stages of a frog's life, in a jumbled order. (Generated With Diffusion Models, original)
- A girl with a magnifying glass watching a sparrow and a lizard on a wall. (Generated With Diffusion Models, original)
Préparation
#1 · Écrire les activités dans le Markdown, leur donner un style une seule fois
// The Markdown says what each activity asks (:::exercise, [[answers]], - A -> B, - [x]);
// this style says how a Spanish workbook prints it: the number in a disc of the unit
// colour, the instruction in bold, blanks on a line, V/F boxes at the line's end, dots to
// join, the bank in a tinted box, squared paper for writing and the activity icons.
const icon = (id, alt) => ({ resourceId: `icon-${id}`, alt, size: 1.05 });
const actividad = {
id: 'actividad',
number: { shape: 'disc', background: col('unit'), color: col('paper'),
fontFamily: DISPLAY, fontSize: em(1.05), fontWeight: 800 },
instruction: { bold: true, color: col('ink') },
options: { marker: 'circle' },
blank: { look: 'line', color: col('ink'), weight: pt(0.75), extra: em(2) },
trueFalse: { look: 'boxes' }, // V F in Spanish, T F in English: the language's own words
match: { look: 'dots', gap: em(7), dotSize: em(0.42), color: col('unit') },
bank: { box: 'banco', order: 'alpha', separator: ' ' },
area: { kind: 'lines', spacing: mm(9), color: col('rule'), weight: pt(0.6) },
grid: { cell: mm(9.5), fontFamily: DISPLAY, fontSize: pt(13), rule: col('rule'),
color: col('ink') },
icons: {
escribe: icon('write', t({ es: 'Escribe', en: 'Write' })),
oral: icon('oral', t({ es: 'Actividad oral', en: 'Speaking' })),
pareja: icon('pair', t({ es: 'En pareja', en: 'In pairs' })),
},
marginTop: mm(7), marginBottom: mm(2), itemSpacing: em(0.8),
};
// The same activity written on squared paper (cuadrícula): `style="cuadricula"`.
const cuadricula = { id: 'cuadricula', extends: 'actividad',
area: { kind: 'grid', spacing: mm(5), weight: pt(0.4) } };
Chaque activité est un bloc :::exercise. Ce que lit l’élève et ce qui compte comme juste se trouvent dans le texte : [[hair]] est un trou dont la réponse est hair, - [x] une affirmation vraie, - Dolphin -> Mammal une paire, [[pelo | (plumas)]] un choix dont le bon mot est entre parenthèses. Le style ne porte que l’aspect : les onze activités partagent actividad, et un second style, cuadricula, le reprend par extends pour remplacer les lignes par du quadrillage. Le moteur les numérote, mélange avec une graine la colonne de droite des paires et les éléments à remettre dans l’ordre, donne à chaque trou la largeur de la réponse la plus longue pour qu’aucun ne trahisse la sienne, et imprime T et F en anglais, V et F en espagnol, sans un mot dans la configuration.
#2 · Donner aux activités leurs pictogrammes
const disc = (body) => '<svg xmlns="http://www.w3.org/2000/svg" width="240" height="240" '
+ `viewBox="0 0 24 24"><circle cx="12" cy="12" r="12" fill="${palette.unit}"/>`
+ `<g fill="none" stroke="#fff" stroke-width="1.7" stroke-linecap="round" `
+ `stroke-linejoin="round">${body}</g></svg>`;
const ICONS = {
write: disc('<path d="M7 17l1-4 7.5-7.5 3 3L11 16l-4 1z"/><path d="M14 7l3 3"/>'),
oral: disc('<path d="M6 7.5h12v7.5H11l-3.5 3v-3H6z"/><path d="M9.5 11.2h.01M12 11.2h.01M14.5'
+ ' 11.2h.01" stroke-width="2.2"/>'),
pair: disc('<circle cx="9" cy="9" r="2.3"/><circle cx="15.3" cy="9.6" r="2"/>'
+ '<path d="M4.8 17.5c.4-2.8 2.1-4.3 4.2-4.3s3.8 1.5 4.2 4.3M13.6 13.9c.6-.3 1.1-.4 1.7-.4'
+ ' 1.9 0 3.3 1.3 3.7 3.8"/>'),
};
Un pictogramme de exerciseStyles[].icons désigne une image du livre, et :::exercise{icon="oral pareja"} place les images après le numéro, dans l’ordre où elles sont écrites ; la synthèse vocale les lit par leur alt. Ce sont des signes en aplat dessinés dans le code sur une pastille de la couleur de l’unité : ils restent nets dans le PDF et changent avec la palette. Un cahier d’activités imprime aussi un crayon à côté des activités où l’on écrit ; les pictogrammes de parole et de binôme signalent la dernière, qui n’a pas de zone d’écriture (area="none").
#3 · Ouvrir l’unité sur un bandeau et une peinture
const at = (to, edge, x = 0, y = 0, size) => ({ anchor: { to, edge },
offset: { x: mm(x), y: mm(y) }, ...(size && { size }) });
const PIC = 75; // mm: the painting's height (it is 176 × 75 mm, 2.35:1)
const opener = { enabled: true, minHeight: mm(20 + PIC + 4), slot: { elements: [
{ kind: 'box', id: 'band', style: { backgroundColor: col('unit'), borderRadius: mm(4) },
placement: at('container', 'top-left', 0, 0, { width: mm(176), height: mm(18) }) },
{ kind: 'text', id: 'unit', content: '{attr.unidad}', fontFamily: DISPLAY, fontSize: pt(11),
fontWeight: 800, color: col('unit'), align: 'center', verticalAlign: 'middle',
textTransform: 'uppercase', letterSpacing: pt(1.4), lineHeight: 1.1,
box: { backgroundColor: col('paper'), borderRadius: mm(4) },
placement: at('container', 'top-left', 4, 4, { width: mm(30), height: mm(10) }) },
{ kind: 'text', id: 'title', content: '{titleText}', fontFamily: DISPLAY, fontSize: pt(27),
fontWeight: 800, color: col('paper'), align: 'left', lineHeight: 1,
placement: at('container', 'top-left', 40, 4.4, { width: mm(132) }) },
{ kind: 'image', id: 'picture', resourceId: '{attr.pic}', decorative: true,
placement: at('container', 'top-left', 0, 22, { width: mm(176), height: mm(PIC) }) },
] } };
Le titre de niveau 1 de l’unité dessine le bandeau, la pastille du numéro et le titre à partir de ses attributs (unidad="Unit 5" pic="charca"), puis la peinture sous le bandeau, en 176 × 75 mm. Les images des activités utilisent un type de ressource sans légende ni numéro (dibujo), comme dans un cahier imprimé. Le texte se lit sans peine à cet âge : Atkinson Hyperlegible Next en 12 pt sur 17 pt, sans césure, en drapeau.
La recette complète
// ═══ Postext Cookbook · Nº 168 · Primary workbook unit of activities ═══════════
// https://postext.dev/en/cookbook/primary-workbook-activities
// Code: MIT · Text: original (CC BY 4.0) · Pictures: generated with diffusion models
// Fonts: Atkinson Hyperlegible Next, Grandstander (SIL OFL 1.1) · Needs postext ≥ 1.59.0
import {
buildDocumentWithFonts, renderPageToCanvas, registerResourceImage,
} from 'https://esm.sh/postext';
import { renderToPdf, decompressWoff2 } from 'https://esm.sh/postext-pdf';
const LANG = 'en'; // @lang: the language of the sample document ('es' | 'en')
const RECIPE = 'primary-workbook-activities';
// ─── 1 · Design ─────────────────────────────────────────────────────────────
// #region palette: one unit colour (green for this unit), a pale tint of it, a sun yellow
const palette = {
ink: '#1f2b27', // text: a green-tinted near-black
unit: '#2b7a3d', // the unit's colour: discs, band, folio, dots to join
deep: '#1d5a2b', // the bank's words and the kicker on white
tint: '#e6f2e2', // the reminder box, the bank
sun: '#f2b330', // the reminder's stripe
rule: '#9cc3a2', // writing lines, the squared paper
muted: '#5c6b64', // running heads, colophon
paper: '#ffffff',
};
const col = (id) => ({ hex: palette[id], model: 'hex', paletteId: id });
const colorPalette = [
...Object.entries(palette).map(([id, hex]) => ({ id, name: id, value: { hex, model: 'hex' } })),
{ id: 'main-color', name: 'unit (defaults)', value: { hex: palette.unit, model: 'hex' } },
];
// #endregion
const [TEXT, DISPLAY] = ['Atkinson Hyperlegible Next', 'Grandstander'];
// #region answer: the workbook's activity style, one for every kind of exercise
// The Markdown says what each activity asks (:::exercise, [[answers]], - A -> B, - [x]);
// this style says how a Spanish workbook prints it: the number in a disc of the unit
// colour, the instruction in bold, blanks on a line, V/F boxes at the line's end, dots to
// join, the bank in a tinted box, squared paper for writing and the activity icons.
const icon = (id, alt) => ({ resourceId: `icon-${id}`, alt, size: 1.05 });
const actividad = {
id: 'actividad',
number: { shape: 'disc', background: col('unit'), color: col('paper'),
fontFamily: DISPLAY, fontSize: em(1.05), fontWeight: 800 },
instruction: { bold: true, color: col('ink') },
options: { marker: 'circle' },
blank: { look: 'line', color: col('ink'), weight: pt(0.75), extra: em(2) },
trueFalse: { look: 'boxes' }, // V F in Spanish, T F in English: the language's own words
match: { look: 'dots', gap: em(7), dotSize: em(0.42), color: col('unit') },
bank: { box: 'banco', order: 'alpha', separator: ' ' },
Le script.js composé s’exécute tel quel : collez-le dans le script de module de n’importe quelle page, ou ouvrez la recette sur CodePen. Dossier de la recette sur GitHub ↗ (s’ouvre dans un nouvel onglet)
Variantes
#Imprimer les réponses pour l’enseignant
Le même Markdown donne le livre du maître : tous les trous remplis, les cases vraies cochées et les bons mots entourés en magenta.
exerciseStyles: [actividad, cuadricula],
+ exercises: { edition: 'teacher' },#Numéroter les activités dans des carrés
Un carré arrondi de la couleur de l’unité donne le style maison d’un autre éditeur.
- number: { shape: 'disc', background: col('unit'), color: col('paper'),
+ number: { shape: 'rounded', background: col('unit'), color: col('paper'),Erreurs fréquentes
- Les mots à entourer dans un texte suivi gardent un peu d’espace de chaque côté pour le cercle : un mot placé juste avant une virgule ou un point s’en détache légèrement.
Crédits
- Recette
- Ignacio Ferro
- Texte
- Texte original, CC BY 4.0
- Images
- Animals at a pond: a frog, a kingfisher, a trout, a turtle and a rabbit. · Generated With Diffusion Models · original
- Five stages of a frog's life, in a jumbled order. · Generated With Diffusion Models · original
- A girl with a magnifying glass watching a sparrow and a lizard on a wall. · Generated With Diffusion Models · original
- Polices
- Atkinson Hyperlegible Next (SIL OFL 1.1) · Grandstander (SIL OFL 1.1)
Modifier ce texte ↗ (s’ouvre dans un nouvel onglet)Dossier de la recette sur GitHub ↗ (s’ouvre dans un nouvel onglet)


