Pular para o conteúdo principal
Receita número 174

Receitas · Capítulo 12 · Livros didáticos

Uma página de passatempos com as respostas invertidas

A página de passatempos de uma revista infantil: palavras cruzadas, caça-palavras, adivinha e história para ordenar, em cartões com as respostas invertidas.

Nesta página
Saída
Canvas · PDF
Postext
Testada com o Postext 1.59.0
Requer ≥ 1.59.0 · postext-pdf ≥ 1.59.0
Licença
Atualizada em 24 de out. de 2026
Código MIT · Texto CC BY 4.0
  • Amostra em inglês: ainda sem edição em português
  • Refile 210 × 280 mm
  • 2 colunas, medianiz de 7 mm
  • Nunito 10,5/15
  • Baloo 2
  • Fredoka
  • 2 páginas
  • Nível
  • Postext 1.59.0
  • Diagramado em 71 ms
  • 129 linhas de código

Em poucas palavras

A página de passatempos de uma revista infantil sobre o mar. Cada passatempo fica no seu cartão, com as respostas impressas de cabeça para baixo embaixo, e o leitor vira a revista para conferir.

O que você vai compor

A página de passatempos da Splash!, uma revista infantil sobre o mar, em duas páginas de tamanho A4 com duas colunas. Uma pintura do recife preenche o alto da primeira página, com o título sobre a água aberta. Embaixo, cada passatempo fica num cartão creme com um número coral: palavras cruzadas montadas com seis animais marinhos e suas dicas, um caça-palavras que esconde oito palavras na horizontal, na vertical, na diagonal e de trás para a frente, uma adivinha com três opções para circular, a vida de uma tartaruga para pôr em ordem, uma frase embaralhada para desvendar e filhotes de animais para ligar ao nome. Embaixo de cada passatempo, dentro do cartão, as respostas vêm de cabeça para baixo em letra cinza pequena, do jeito que as revistas de passatempos sempre as esconderam.

Esta receita responde a

  • Como faço um caça-palavras ou palavras cruzadas a partir de uma lista de palavras?
  • Como imprimo as respostas de cabeça para baixo no pé de um exercício?

A resposta curta

script.js · linhas 33–59no código completo
// placement 'inverted' sets each puzzle's key after it in a box turned 180°, inside the
// puzzle's card, so a page break never parts a puzzle from its answers. The key is made
// from the puzzle: the crossword's words by number, the ringed option, the right order.
const puzzle = {
  id: 'puzzle',
  box: 'card', // the card each puzzle sits on (a calloutStyles id)
  number: { shape: 'disc', fontFamily: DISPLAY, background: col('coral') },
  instruction: { fontFamily: TEXT, bold: false },
  options: { marker: 'circle', labels: 'none' }, // a ring to colour in, no letters
  grid: { fontFamily: LABEL, rule: col('sea'), cell: em(1.45) },
  match: { color: col('sea') },
  area: { kind: 'lines', color: col('sea') },
  answers: { color: col('coral'), fontFamily: LABEL },
  solutions: { placement: 'inverted', box: 'turned' },
  marginTop: mm(0), marginBottom: mm(0),
};
const card = { id: 'card', title: '', background: col('card'), borderRadius: mm(4),
  padding: { top: mm(3.5), right: mm(4), bottom: mm(3), left: mm(4) },
  titleStyle: { fontFamily: DISPLAY, fontSize: pt(15), fontWeight: 700, color: col('ink') },
  body: { fontFamily: TEXT, fontSize: pt(10.5), lineHeight: pt(15), color: col('ink'),
    firstLineIndent: pt(0) },
  marginTop: mm(0), marginBottom: mm(5), keepTogether: true };
const turned = { id: 'turned', title: '', backgroundEnabled: false, border: { enabled: false },
  padding: { top: pt(0), right: pt(0), bottom: pt(0), left: pt(0) },
  body: { fontFamily: LABEL, fontSize: pt(8.5), lineHeight: pt(11), color: col('muted'),
    firstLineIndent: pt(0) },
  marginTop: mm(2), marginBottom: mm(0) };

Ingredientes

Tipografia
Baloo 2, Nunito, Fredoka (SIL OFL 1.1)
Materiais
  • hatchling-600.jpg
  • reef-1600x792.jpg
  • A coral reef with a smiling sea turtle, an octopus, a clownfish, a pufferfish and a seahorse under sunbeams. (Generated With Diffusion Models, original)
  • A baby sea turtle hatching from its egg on the sand. (Generated With Diffusion Models, original)

Preparo

#1 · Cada passatempo num cartão, com as respostas viradas

O código é a resposta curta logo acima. O box do estilo de exercício nomeia um estilo de boxe, então cada passatempo vai num cartão, com o número num círculo e o título como primeira linha do enunciado. placement: 'inverted' põe as respostas depois de cada passatempo num boxe girado 180°, dentro do cartão, então passatempo e respostas nunca caem em páginas diferentes; as grades e a linha de escrita ficam dentro do espaçamento interno do cartão.

#2 · Deixe o motor montar as grades

O Markdown traz só as palavras: - OCTOPUS: Eight arms and three hearts para as palavras cruzadas, - SHELL para o caça-palavras. O motor monta as palavras cruzadas com cada palavra cruzando outra e numera os inícios na ordem de leitura. No caça-palavras, esconde as palavras nas direções que a diretiva indica (directions="across down diagonal backwards") e preenche o resto com letras das mesmas palavras. As duas grades usam uma semente fixa, então saem iguais em cada composição e em cada saída, e a edição espanhola monta a sua grade com as suas próprias palavras.

#3 · Um recife na largura das duas colunas

script.js · linhas 63–82no código completo
const BAND = 104; // mm from the top edge: the painting's height at the page's width
const opener = { enabled: true, minHeight: mm(BAND - 16 + 6), slot: { elements: [
  { kind: 'image', id: 'reef', resourceId: 'reef', decorative: true, reserve: false,
    placement: { anchor: { to: 'page', edge: 'top-left' },
      size: { width: mm(210), height: mm(BAND) } } },
  { kind: 'text', id: 'kicker', content: '{attr.kicker}', fontFamily: LABEL, fontSize: pt(11),
    fontWeight: 600, color: col('paper'), textTransform: 'uppercase', letterSpacing: pt(2),
    box: { backgroundColor: col('coral'), borderRadius: mm(2),
      padding: { top: mm(0.8), bottom: mm(0.8), left: mm(2.4), right: mm(2.2) } },
    placement: { anchor: { to: 'page', edge: 'top-left' }, offset: { x: mm(16), y: mm(14) } } },
  { kind: 'text', id: 'title', content: '{titleText}', fontFamily: DISPLAY, fontSize: pt(56),
    fontWeight: 800, lineHeight: 1, color: col('paper'),
    placement: { anchor: { to: '#kicker', edge: 'below' }, offset: { x: mm(0), y: mm(3) } } },
  { kind: 'text', id: 'sub', content: '{attr.sub}', fontFamily: TEXT, fontSize: pt(12),
    fontWeight: 700, color: col('paper'), overflow: 'wrap', align: 'left',
    box: { backgroundColor: col('ink'), borderRadius: mm(2),
      padding: { top: mm(1.5), bottom: mm(1.5), left: mm(3), right: mm(3) } },
    placement: { anchor: { to: '#title', edge: 'below' }, offset: { x: mm(0), y: mm(2) },
      size: { width: mm(110) } } },
] } };

A abertura ocupa as duas colunas (span: 'page'), então os passatempos começam embaixo da pintura em cada coluna. A imagem é recortada na proporção da faixa e ancorada à página, de modo que sangra no alto e nas laterais; a linha fina fica numa caixa escura para ser lida sobre a água.

A receita completa

Sandbox
// ═══ Postext Cookbook · Nº 174 · A puzzle page with the answers upside down ═══════
// https://postext.dev/en/cookbook/puzzle-page-upside-down-answers
// Code: MIT · Text: original (CC BY 4.0) · Pictures: generated with diffusion models
// Fonts: Baloo 2, Nunito, Fredoka (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 ('en' | 'es')
const RECIPE = 'puzzle-page-upside-down-answers';

// ─── 1 · Design ─────────────────────────────────────────────────────────────
// #region palette: reef colours: deep blue ink, coral, sea green, a sandy paper
const palette = {
  ink: '#16324a', // text: a deep sea blue
  coral: '#e8573f', // the accent: puzzle numbers, the title kicker
  sea: '#0f8b8d', // the second: crossword and word-search rules, the riddle's rings
  sun: '#ffc93c', // the turtle card's badge
  card: '#fff4e0', // the puzzle cards
  muted: '#5d7180', // answers, colophon, folio
  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: 'accent (defaults)', value: { hex: palette.coral, model: 'hex' } },
];
// #endregion
const [DISPLAY, TEXT, LABEL] = ['Baloo 2', 'Nunito', 'Fredoka'];

// #region answer: every puzzle on a card, its answers turned upside down under it
// placement 'inverted' sets each puzzle's key after it in a box turned 180°, inside the
// puzzle's card, so a page break never parts a puzzle from its answers. The key is made
// from the puzzle: the crossword's words by number, the ringed option, the right order.
const puzzle = {
  id: 'puzzle',
  box: 'card', // the card each puzzle sits on (a calloutStyles id)
  number: { shape: 'disc', fontFamily: DISPLAY, background: col('coral') },
  instruction: { fontFamily: TEXT, bold: false },
  options: { marker: 'circle', labels: 'none' }, // a ring to colour in, no letters
  grid: { fontFamily: LABEL, rule: col('sea'), cell: em(1.45) },
  match: { color: col('sea') },
  area: { kind: 'lines', color: col('sea') },
  answers: { color: col('coral'), fontFamily: LABEL },
  solutions: { placement: 'inverted', box: 'turned' },
  marginTop: mm(0), marginBottom: mm(0),
};

O script.js montado funciona como está: cole-o como script de módulo em qualquer página ou abra a receita no CodePen. Pasta da receita no GitHub ↗ (abre em uma nova aba)

Variações

#Esconda a lista de palavras

Um caça-palavras mais difícil imprime só a grade: acrescente hidden à diretiva.

-:::exercise{type=wordsearch size=9 directions="across down diagonal backwards"}
+:::exercise{type=wordsearch size=9 directions="across down diagonal backwards" hidden}

#Imprima as respostas no fim da revista

chapterEnd reúne todas as respostas no fim em vez de virar cada uma.

-  solutions: { placement: 'inverted', box: 'turned' },
+  solutions: { placement: 'chapterEnd' },

Erros comuns

  • Uma palavra das palavras cruzadas que não cruza com nenhuma outra fica de fora e gera o aviso exerciseWordUnplaced. Escolha palavras que tenham letras em comum ou acrescente uma que ligue dois grupos.
  • O cartão de um passatempo fica inteiro, então palavras cruzadas altas passam para a coluna seguinte quando não cabem: confira a edição espanhola, de palavras mais longas.

Créditos

Texto
Texto original, CC BY 4.0
Imagens
  • A coral reef with a smiling sea turtle, an octopus, a clownfish, a pufferfish and a seahorse under sunbeams. · Generated With Diffusion Models · original
  • A baby sea turtle hatching from its egg on the sand. · Generated With Diffusion Models · original
Fontes
Baloo 2 (SIL OFL 1.1) · Nunito (SIL OFL 1.1) · Fredoka (SIL OFL 1.1)
Sandbox