Automatically fit the graphics in the remaining space of a Beamer slide
One way is to define a new command which takes as arguments the frame content before the image, the file name of the image and, optionally, any frame content following the image. So that these can be specified in their natural order, I use xparse
's \NewDocumentCommand
to define
\fitimage{<content before>}{<image file name>}[<content after>]
This command calculates the total height of a paragraph box containing the first and third arguments (\fitotherht
). It then calculates an appropriate maximum height for the image (\fitimageht
) by subtracting this from \textheight
and making a few adjustments to allow room for the vertical spacing at the head and foot of the frame, and for some space between the different clusters of content within the frame.
Code:
\documentclass{beamer}
\usepackage[pangram]{blindtext}
\usetheme{Pittsburgh}
\usepackage{xparse,calc}
\newlength\fitimageht
\newlength\fitotherht
\newsavebox\fitimagebox
\NewDocumentCommand \fitimage { m m O {} }{%
\sbox\fitimagebox{%
\parbox{\textwidth}{%
#1\par
#3
}%
}%
\settototalheight{\fitotherht}{%
\usebox\fitimagebox
}%
\setlength\fitimageht{\textheight}%
\addtolength\fitimageht{-\fitotherht-\topskip-\footskip-3\baselineskip}%
#1\par
\centering
\includegraphics[width=\textwidth,height=\fitimageht,keepaspectratio]{#2}\par
#3}
\begin{document}
\begin{frame}
\fitimage{%
\frametitle{Something}
\blindenumerate[2]
}{2000px-If-then-else-control-flow-graph}
\end{frame}
\begin{frame}
\fitimage{%
\frametitle{Something}
\blindenumerate[2]%
}{2000px-If-then-else-control-flow-graph}[%
\blinddescription[2]
]
\end{frame}
\begin{frame}
\fitimage{%
\frametitle{Something}
\blindenumerate[6]%
}{2000px-If-then-else-control-flow-graph}[%
\blinddescription[2]
]
\end{frame}
\end{document}
It is important that all frame content be included within the arguments to the command. So this won't work with overly fragile content. (I imagine verbatim code would not work, for example.) But for ordinary text, frame title etc., it seems to do a reasonable job. If the spacing I've chosen is not to your taste, you can easily adjust the value of \fitimageht
by subtracting more or less as applicable.
This does not result in any bad boxes, according to the log file.
Following code shows an alternative solution using tcolorbox
package and its space to
option.
space to = macro
saves (after several compilations: two or more) into macro
the difference between box contents natural height and box forced height. This difference can be used to fix the graphic height filling, this way, all the available space.
As a fixed height is needed for this kind of tcolorboxes and I don't know how to automatically compute it, I've used height=.8\textheight
.
Then a declaration like
\begin{tcolorbox}[enhanced,height=.8\textheight, space to=\myspace]
...
{\par\centering\includegraphics[height=\myspace]{example-image}\par}
\end{tcolorbox}
will build a tcolorbox with height .8\textheight
and the available vertical space will be stored in \myspace
which is used to fix graphics size.
Following code shows some examples with default tcolorboxes
and some more with a blankest
style which creates a box like regular text:
\documentclass{beamer}
\usepackage[pangram]{blindtext}
\usetheme{Pittsburgh}
\usepackage[most]{tcolorbox}
\newtcolorbox{myfitbox}[1][]{
enhanced,
height=.8\textheight,
space to=\myspace,
#1}
\begin{document}
\begin{frame}
\frametitle{Something}
\begin{myfitbox}
\blindenumerate[2]
{\par\centering\includegraphics[height=\myspace]{example-image}\par}
\end{myfitbox}
\end{frame}
\begin{frame}
\frametitle{Something}
\begin{myfitbox}
\blindenumerate[2]
{\par\centering\includegraphics[height=\myspace]{example-image}\par}
\blinddescription[2]
\end{myfitbox}
\end{frame}
\begin{frame}
\frametitle{Something}
\begin{myfitbox}
\blindenumerate[6]
{\par\centering\includegraphics[height=\myspace]{example-image}\par}
\blinddescription[2]
\end{myfitbox}
\end{frame}
\begin{frame}
\frametitle{Something}
\begin{myfitbox}[blankest]
\blindenumerate[2]
{\par\centering\includegraphics[height=\myspace]{example-image}\par}
\end{myfitbox}
\end{frame}
\begin{frame}
\frametitle{Something}
\begin{myfitbox}[blankest]
\blindenumerate[2]
{\par\centering\includegraphics[height=\myspace]{example-image}\par}
\blinddescription[2]
\end{myfitbox}
\end{frame}
\begin{frame}
\frametitle{Something}
\begin{myfitbox}[blankest]
\blindenumerate[6]
{\par\centering\includegraphics[height=\myspace]{example-image}\par}
\blinddescription[2]
\end{myfitbox}
\end{frame}
\end{document}