# How to stop a tikz matrix from jumping about in beamer

I have a series of slides/transitions showing one matrix where I insert some gaps between columns and circle numbers and at one point add an extra row at the bottom. I would like the matrix to stay in the same place vertically and for all the elements (which are boxed) to stay in the same place when all I do is circle a number or add a row at the bottom of the matrix (see example for what this means exactly). Basically, I would like it to stop jumping around as much as possible. How can I do this?

Here is a rather long example which shows the problem:

\documentclass{beamer}
\usepackage{tikz}
\usetikzlibrary{arrows.meta, calc, matrix}
\newcommand\Circle[1]{%
\tikz[baseline=(char.base)]\node[circle,draw,inner sep=2pt] (char) {#1};}

\begin{document}

\begin{frame}[fragile]
\frametitle{title}
\begin{center}
\begin{tikzpicture}
\matrix (m) [matrix of nodes,
nodes={draw, minimum size=8mm},
column sep=3mm,
row sep=2mm,
row 1/.style={nodes={draw=none}}]
{
0 & 1 & 2 & 3 & 4   \\[-3mm]
6 & 2 & 4 & 4 & 5   \\
8 & 4 & 5 & 6 & 6   \\
7 & 5 & 2 & 7 & 5   \\
6 & 5 & 1 & 6 & 5   \\
5 & 9 & 0 & 2 & 4   \\
};
\end{tikzpicture}
\end{center}

\begin{itemize}
\item A line of text
\end{itemize}
\end{frame}

\begin{frame}[fragile]
\frametitle{title}
\begin{center}
\begin{tikzpicture}
\matrix (m) [matrix of nodes,
nodes={draw, minimum size=8mm},
column sep=3mm,
row sep=2mm,
row 1/.style={nodes={draw=none}}]
{
0 & 1 & 2 & 3 & 4   \\[-3mm]
6 & 2 & 4 & 4 & 5   \\
\Circle{8} & 4 & \Circle{5} & 6 & \Circle{6}   \\
7 & 5 & 2 & \Circle{7} & 5   \\
6 & 5 & 1 & 6 & 5   \\
5 & \Circle{9} & 0 & 2 & 4   \\
&   &   &   &     \\
\hline \\
8 & 9 & 5 & 7 & 6   \\
};
\end{tikzpicture}
\end{center}

\begin{itemize}
\item Some text
\end{itemize}
\end{frame}

\begin{frame}[fragile]
\frametitle{title}
\begin{center}
\begin{tikzpicture}
\matrix (m) [matrix of nodes,
nodes={draw, minimum size=8mm},
column sep=3mm,
row sep=2mm,
row 1/.style={nodes={draw=none}}]
{
0 & 1 &[5mm] 2 &[5mm] 3 & 4   \\[-3mm]
6 & 2 & 4 & 4 & 5   \\
8 & 4 & \Circle{5} & 6 & 6   \\
7 & 5 & 2 & 7 & 5   \\
6 & 5 & 1 & 6 & 5   \\
5 & 9 & 0 & 2 & 4   \\
&   &   &   &     \\
\hline \\
8 & 9 & 5 & 7 & 6   \\
};
\end{tikzpicture}
\end{center}

\end{frame}

\begin{frame}[fragile]
\frametitle{title}
\begin{center}
\begin{tikzpicture}
\matrix (m) [matrix of nodes,
nodes={draw, minimum size=8mm},
column sep=3mm,
row sep=2mm,
row 1/.style={nodes={draw=none}}]
{
0 & 1 &[5mm] 2 & 3 & 4   \\[-3mm]
6 & 2 & 4 & 4 & 5   \\
8 & 4 & 5 & 6 & 6   \\
7 & 5 & 2 & 7 & 5   \\
6 & 5 & 1 & 6 & 5   \\
5 & 9 & 0 & 2 & 4   \\
&   &   &   &     \\
\hline \\
8 & 9 & 5 & 7 & 6   \\
};
\end{tikzpicture}
\end{center}
\end{frame}

\begin{frame}[fragile]
\frametitle{title}
\begin{center}
\begin{tikzpicture}
\matrix (m) [matrix of nodes,
nodes={draw, minimum size=8mm},
column sep=3mm,
row sep=2mm,
row 1/.style={nodes={draw=none}}]
{
0 & 1 & 2  &[5mm] 3 &[5mm]  4   \\[-3mm]
6 & 2 & 4 & 4 & 5   \\
8 & 4 & 5 & 6 & 6   \\
7 & 5 & 2 & 7 & 5   \\
6 & 5 & 1 & 6 & 5   \\
5 & 9 & 0 & 2 & 4   \\
&   &   &   &     \\
\hline \\
8 & 9 & 5 & 7 & 6   \\
};
\end{tikzpicture}
\end{center}
\end{frame}

\begin{frame}[fragile]
\frametitle{title}
\begin{overlayarea}{\linewidth}{\textheight}
\begin{center}
\begin{tikzpicture}
\matrix (m) [matrix of nodes,
nodes={draw, minimum size=8mm},
column sep=3mm,
row sep=2mm,
row 1/.style={nodes={draw=none}}]
{
0 & 1 & 2  &[5mm] 3 &[5mm]  4   \\[-3mm]
6 & 2 & 4 & 4 & 5   \\
8 & 4 & 5 & 6 & 6   \\
7 & 5 & 2 & \Circle{7} & 5   \\
6 & 5 & 1 & 6 & 5   \\
5 & 9 & 0 & 2 & 4   \\
&   &   &   &     \\
\hline \\
8 & 9 & 5 & 7 & 6   \\
};
\end{tikzpicture}
\end{center}
\pause
\begin{itemize}
\item More text
\end{itemize}
\end{overlayarea}
\end{frame}
\end{document}

• Your approach nests tikzpictures. This is to be avoided. I compiled your code and see what it does, but fail to understand what you mean by "I move columns of a matrix from left to right". As far as I can see the matrix gets largely preserved but only some gaps and circles appear. Could you please explain what you mean by that statement? – Schrödinger's cat Feb 1 at 18:28
• Typically, if tikzpictures are moving around it is because the bounding box changes. You need to use a common (larger) bounding box for all the tikzpictures. See tex.stackexchange.com/questions/490497/… – John Kormylo Feb 1 at 18:34
• @Schrödinger'scat That is exactly what I meant. Sorry it was unclear. – Arlo Feb 1 at 18:39
• @JohnKormylo When I circle a number it also increases the size of the surrounding box, which is fine but also seems to cause some jumping about. – Arlo Feb 1 at 18:43
• Instead of putting a circle IN the matrix, overlay it. Each cell has a node name which can be used to locate it after the matrix is complete. – John Kormylo Feb 1 at 18:48

I'd draw the matrix just once and use overlay-beamer-styles to add the changes. Your \Circled command nests tikzpictures, I replaced it by a circled style and a variation circled on which adds the circle only on some specific overlays. E.g.

|[circled on=<{2,6,7}>]| 7


circles the 7 node only on overlays 2, 6 and 7. I also added one example how you can use the alt key to change the column sep of specific columns on certain overlays,

alt=<2>{column 2/.style={column sep=7mm},column 3/.style={column sep=7mm}}{},


but I did not have the passion to implement all of them.

\documentclass{beamer}
\usepackage{tikz}
\usetikzlibrary{arrows.meta, calc, matrix,overlay-beamer-styles}
\tikzset{circled/.style={path picture={
\draw let \p1=($(path picture bounding box.north east)-(path picture bounding box.south west)$),\n1={min(\x1,\y1)/2.2} in
(path picture bounding box.center) circle[radius=\n1];}},
circled on/.style={alt=#1{circled}{}}}
\begin{document}
\begin{frame}[fragile,t]
\frametitle{title}
\centering
\begin{tikzpicture}
\matrix (m) [matrix of nodes,
nodes={draw, minimum size=8mm},
column sep=3mm,
alt=<2>{column 2/.style={column sep=7mm},column 3/.style={column sep=7mm}}{},
% you need to add the other variations of the column seps here
row sep=2mm,
row 7/.style={visible on=<4-5>},
row 1/.style={nodes={draw=none}}] (mat)
{
0 & 1 & 2 & 3 & 4   \\[-3mm]
6 & 2 & 4 & 4 & 5   \\
|[circled on=<2>]| 8 & 4 &  |[circled on=<{2,3}>]| 5 & 6 &  |[circled on=<2>]| 6   \\
7 & 5 & 2 & |[circled on=<{2,6,7}>]| 7 & 5   \\
6 & 5 & 1 & 6 & 5   \\
5 & |[circled on=<2>]| 9 & 0 & 2 & 4   \\[2mm]
8 & 9 & 5 & 7 & 6   \\
};
\path (mat-6-1.south) -- (mat-7-1.north) coordinate[midway](aux);
\draw[visible on=<{4,5}>] (mat.west|-aux) -- (mat.east|-aux);
\end{tikzpicture}

\only<1>{\begin{itemize}
\item A line of text
\end{itemize}}
\only<2>{\begin{itemize}
\item Some text
\end{itemize}}
\only<7>{\begin{itemize}
\item More text
\end{itemize}}
\end{frame}
\end{document}


As you see, no more jumps and much shorter code (and, even though you may not necessarily see it this way, most importantly no more nested tikzpictures).

ADDENDUM: Added an extra row that is only visible on certain overlays, and separated by a line. The visibility is controlled by

row 7/.style={visible on=<4-5>},


and

\draw[visible on=<{4,5}>] (mat.west|-aux) -- (mat.east|-aux);


respectively.

• This is almost miraculously better than my code! I can't upvote as my reputation is too low. – Arlo Feb 1 at 19:14
• How can add the horizontal line and the extra row (as in my example code) using your very nice new solution? Currently I just add an \hline, a blank row and an extra row but this needs to be shown only for some overlays now without making it jump around. – Arlo Feb 1 at 19:46
• @Arlo I added horizontal lines. Please note that \hline sort of works by accident, so I use a more robust way. – Schrödinger's cat Feb 1 at 20:31
• Thanks but in my case I am adding an extra row below the existing matrix with a horizontal line in between. I tried using \only{} for the extra row but that failed completely. – Arlo Feb 1 at 21:52
• @Arlo I added the code for this. – Schrödinger's cat Feb 1 at 22:09