Graphical placeholder for "variables"

This is a TikZ based solution working for math and text.

teaser

Usage

Use \fib{<text/math>} to create a fill in box. Use the starred version to show the solution of a single box or \fibhideanswerfalse to show all solutions. With \tikzset{fill in/.style={<box style>}} or \tikzset{<underline/bracket> style/.style={<drawing style>}} the style can be changed globally or with \fib[underlined box]{<text/math> for a single box.

Examples

A \fib{short} example with math $1 + 2^{\fib{2}} = \fib{5} = \sqrt{25}$.

colored box 1

colored box with answers

colored box 2

framed box

underlined box

dotted underlined box

underbracked box

colored underbracket box

underoverbracked box

beamer class

One can use the following to have one slide with the empty boxes and the next one with the solutions on it.

\begin{frame}{Beamer example}
   \only<2->{\fibhideanswerfalse}
   A \fib{short} example with math $1 + 2^{\fib{2}} = \fib{5} = \sqrt{25}$.
\end{frame}

Or use the following to show the answers step by step.

\begin{frame}{Beamer example}
   A \fib<2->{short} example with math $1 + 2^{\fib<3->{2}} = \fib<4->{5} = \sqrt{25}$.
\end{frame}

Code

There’s also a german explanation in my blog: TeX-Beispiel der Monats: Lückentexte.

\documentclass[fleqn]{article}
%\documentclass{beamer}

\usepackage{xparse}
\usepackage{tikz}
   \usetikzlibrary{calc}
\usepackage{mathtools}

\makeatletter
\newlength\fib@width
\def\fib@widthfactor{1.75}
\newif\iffibhideanswer
\fibhideanswertrue
\tikzset{
   every fill in box/.style={
     inner xsep=0pt,
     minimum height=3ex,
     align=center,
     font={\sffamily\slshape},
   },
   colored box/.style={
      every fill in box,
      fill=yellow!50!white,
   },
   framed box/.style={
      every fill in box,
      draw,
   },
   underline style/.style={},
   underlined box/.style={
      every fill in box,
      append after command={%
         \pgfextra{\begin{pgfinterruptpath}
            \draw [underline style] (\tikzlastnode.south west)
                  -- (\tikzlastnode.south east);
         \end{pgfinterruptpath}}
      },
   },
   bracket style/.style={},
   underbracked box/.style={
      every fill in box,
      append after command={%
         \pgfextra{\begin{pgfinterruptpath}
            \draw [bracket style] ($(\tikzlastnode.south west)+(0,2pt)$)
                  |- (\tikzlastnode.south)
                  -| ($(\tikzlastnode.south east)+(0,2pt)$);
         \end{pgfinterruptpath}}
      },
   },
   underoverbracked box/.style={
      every fill in box,
      append after command={%
         \pgfextra{\begin{pgfinterruptpath}
            \draw [bracket style] ($(\tikzlastnode.north west)-(0,2pt)$)
                  |- (\tikzlastnode.north)
                  -| ($(\tikzlastnode.north east)-(0,2pt)$);
            \draw [bracket style] ($(\tikzlastnode.south west)+(0,2pt)$)
                  |- (\tikzlastnode.south)
                  -| ($(\tikzlastnode.south east)+(0,2pt)$);
         \end{pgfinterruptpath}}
      },
   },
   fill in/.style={
      colored box,
   },
}
\NewDocumentCommand { \fib@hide } { m } {%
   \iffibhideanswer
      \phantom{#1}%
   \else
      #1%
   \fi
}
\NewDocumentCommand { \fib@makebox }{ m }{%
   \settowidth{\fib@width}{\tikz\node[fill in]{#1};}%
   \begin{tikzpicture}[baseline=(fill in node.base)]
      \node (fill in node) [text width=\fib@widthfactor*\fib@width,fill in] {%
         \fib@hide{#1}%
      };
   \end{tikzpicture}%
}
\NewDocumentCommand { \fib } { s d{<}{>} o m }{{%
   \IfBooleanT{#1}{\fibhideanswerfalse}%
   \IfValueT{#2}{\only<#2>{\fibhideanswerfalse}}%
   \IfValueT{#3}{\tikzset{fill in/.style={#3}}}%
   \ifmmode
      \mathchoice
         {\fib@makebox{$\displaystyle#4$}}
         {\fib@makebox{$\textstyle#4$}}
         {\fib@makebox{$\scriptstyle#4$}}
         {\fib@makebox{$\scriptscriptstyle#4$}}
   \else
      \fib@makebox{#4}%
   \fi
   \IfValueT{#2}{}%
}}
\makeatother

\begin{document}
% STYLE SETTING EXAMPLES
%\tikzset{colored box/.append style={fill=black!15}}
%\tikzset{fill in/.style={framed box}}
%\tikzset{fill in/.style={underlined box}}
%\tikzset{underline style/.style={densely dotted,thick}}
%\tikzset{fill in/.style={underbracked box}}
%\tikzset{fill in/.style={underoverbracked box}}
%\tikzset{bracket style/.style={gray,thick}}
%\fibhideanswerfalse


% ARTICLE/BOOK EXAMPLES
A \fib{short} example with math $1 + 2^{\fib{2}} = \fib{5} = \sqrt{25}$.

\vspace{2cm}
In \fib{text} mode and math $1 + 3 = \fib{4} = \fib{\frac{8}{2}}$
\begin{equation}
   1 + 3 = \fib{4} = \fib{\frac{8}{2}}
\end{equation}
\begin{equation}
   (a + b)^2 = \fib{a^2 + 2ab + b^2}
\end{equation}
\begin{equation}
   \begin{pmatrix}
      1 \\ 2 \\ 3
   \end{pmatrix}
   \times
   \begin{pmatrix}
      4 \\ 5 \\ 6
   \end{pmatrix}
   =
   \fib{\begin{pmatrix}
      -3 \\ 6 \\ -3
   \end{pmatrix}}
\end{equation}
With an asterisk, i.e. \verb+\fib*+, the \fib*{solution} is always visible.
The optional argument can be used to change \fib*[underlined box]{styles} locally.


% BEAMER EXAMPLES
%\begin{frame}{Beamer example 1}
%   \only<2->{\fibhideanswerfalse}
%   A \fib{short} example with math $1 + 2^{\fib{2}} = \fib{5} =
%   \sqrt{25}$.
%\end{frame}
%\begin{frame}{Beamer example 2}
%   A \fib<2->{short} example with math $1 + 2^{\fib<3->{2}} =
%   \fib<4->{5} = \sqrt{25}$.
%\end{frame}

\end{document}

Implementation overview

For the implementation we need tikz (with the calc library) and xparse to implement the fill in boxes. I load mathtools for the {pmatrix} example …

\usepackage{xparse}
\usepackage{tikz}
   \usetikzlibrary{calc}
\usepackage{mathtools}

Next step is to make @ available for internal command names.

\makeatletter

Then I define a new width, which will measure the width of the box, a factor to stretching the natural width (hand writing needs more space than printing) and an switch to show or hide the solutions (default: hide):

\newlength\fib@width
\def\fib@widthfactor{1.75}
\newif\iffibhideanswer
\fibhideanswertrue

Now I can define some TikZ styles. The every fill in box defines some basics …

\tikzset{
   every fill in box/.style={
     inner xsep=0pt,
     minimum height=3ex,
     align=center,
     font={\sffamily\slshape},
   },

… and the next styles define various appearances for the fill in boxes.

   ...

The last style, is a dummy that can be used to change the style easily.

   fill in/.style={
      colored box,
   },
}

Now I need a helper macro that either hides or shows the solution …

\NewDocumentCommand { \fib@hide } ...

… and one to print the box with the desired style:

\NewDocumentCommand { \fib@makebox } ...

Now I got everything to define \fib (“fill in box”). It will have a starred version to always print the solution, an optional argument to change the style locally and the mandatory argument taking the content of the fill in box. Depending on the star (stored as bool in #1) the solution hiding is set to false. If theres an optional argument (\IfValueT{#2}) the style is redefined. Then it must be testest if the macro is in math mode (\ifmmode = true) or in text mode (\ifmmode = false). If the macro is inside math the current style must be checked and handled with \mathchoice.

\NewDocumentCommand { \fib } ...

Last thing to do is to deactivate the @:

\makeatother

With an optional argument

\documentclass[preview,border=12pt]{standalone}
\usepackage{mathtools}


\newcommand\ph[2][1em]{%
    \raisebox{-.5\height}{\rule{.5pt}{3pt}\rule{#1}{.5pt}\rule{.5pt}{3pt}}%
    \hspace{-.5\dimexpr#1+1pt\relax}\clap{#2}\hspace{.5\dimexpr#1+1pt\relax}}

\begin{document}
$1+\ph{}=3$, find $\ph[2em]{}$. Answer $\ph[3em]{2}$.
\end{document}

enter image description here


(very) light-weight method:

\documentclass{article}
\newcommand{\ph}{\texttt{\char32 }}

\begin{document}
$1+\ph=3$, find $\ph$.
\end{document}

placeholder

I felt bad about not having used \textvisiblespace. And here comes something funny, in OT1 encoding, \textvisiblespace is actually done using rules:

\OT1\textvisiblespace ->\mbox {\kern .06em\vrule \@height .3ex}%
                          \vbox {\hrule \@ width .3em}\hbox {\vrule \@height .3ex}

But in T1 encoding, it is the same as \char32 as used above.

\documentclass{article}
\newcommand{\ph}{\texttt{\textvisiblespace}}

\begin{document}

% \showoutput

$\texttt{\char32}\neq\textvisiblespace$ in encoding OT1.

{\usefont{T1}{cmtt}{m}{n}\char32}${}={}${\usefont{T1}{cmtt}{m}{n}\textvisiblespace}
in encoding T1.

\end{document}

placeholder2