create environment that resizes content

I want to create an environment that puts its content within a minipage as wide as the current page. The environment would work as follows:

\begin{FitToWidth}
HELLO
\end{FitToWidth}


and produce a "HELLO" as wide as the textwidth of the page.

Without defining an environment, this can be done as follows:

\documentclass[letter,11pt]{article}
\usepackage{graphicx}

\begin{document}

\begin{center}
\begin{minipage}{\textwidth}
\begin{center}
\resizebox{\textwidth}{!}{%
HELLO
}
\end{center}
\end{minipage}
\end{center}

\end{document}


The problem is that when I try to turn this code into an environment, LaTeX returns an error (Package graphics Error: Division by 0).

This is what I have unsuccessfully tried:

\newenvironment{FitToWidth}{
\begin{center}
\begin{minipage}{\textwidth}
\begin{center}
\resizebox{\textwidth}{!}{%
} {
}
\end{center}
\end{minipage}
\end{center}
}


What is the problem?

3 Answers

With adjustbox

\documentclass[letter,11pt]{article}
\usepackage{adjustbox}
\usepackage{showframe}  %% just for demo
\newenvironment{FitToWidth}[1][\textwidth]{%
\begin{adjustbox}{width=#1,center}
}
{\end{adjustbox}}

\begin{document}

\begin{adjustbox}{width=\textwidth}
HELLO
\end{adjustbox}

\bigskip
\begin{FitToWidth}
HELLO
\end{FitToWidth}

\bigskip
\begin{FitToWidth}[0.5\textwidth]
HELLO
\end{FitToWidth}

\end{document}


• Using adjustbox rather than reinventing the wheel is a good idea. Thank you! – scaramouche Feb 22 '15 at 15:05

Capture the environment contents, and then resize it. The former is the difficult part, which is causing the problem. However, it's made easy by the environ package:

\documentclass{article}
\usepackage{graphicx,environ}
\NewEnviron{FitToWidth}[1][\textwidth]{%
\begin{center}
\makebox[\textwidth]{resizebox{#1}{!}{\BODY}}%
\end{center}
}

\begin{document}

\noindent X \dotfill X

\begin{FitToWidth}
HELLO
\end{FitToWidth}

\noindent X \dotfill X

\begin{FitToWidth}[.5\textwidth]
HELLO
\end{FitToWidth}

\noindent X \dotfill X

\end{document}


environ allows you to create an environment and captures its contents in the macro \BODY, which you can then work with inside \resizebox. In your attempt you're placing content in the \begin part and \end part of FitToWidth, but the way TeX works is it never gets to grab it's argument that way... since the \begin/\end parts are set independent from one another.

The center environment provides some space above/below, while \makebox[\textwidth] ensures that whatever you supply for the optional argument to FitToWidth (default is \textwidth) it will not cause an overfull box.

Another way to do it (without environ) would be to capture the environment contents in a box, which you can then manipulate:

\documentclass{article}
\usepackage{graphicx}
\newsavebox{\FTWbox}
\newenvironment{FitToWidth}[1][\textwidth]
{% \begin{FitToWidth}[<width>]
\gdef\FTWoptarg{#1}%
\begin{lrbox}{\FTWbox}
}{% \end{FitToWidth}
\end{lrbox}%
\begin{center}
\makebox[\textwidth]{\resizebox{\FTWoptarg}{!}{\usebox{\FTWbox}}}%
\end{center}
}

\begin{document}

\noindent X \dotfill X

\begin{FitToWidth}
HELLO
\end{FitToWidth}

\noindent X \dotfill X

\begin{FitToWidth}[.5\textwidth]
HELLO
\end{FitToWidth}

\noindent X \dotfill X

\end{document}

• This doesn't actually answer the question which is, what is the problem? – cfr Feb 22 '15 at 4:47

Here is your code:

\newenvironment{FitToWidth}{
\begin{center}
\begin{minipage}{\textwidth}
\begin{center}
\resizebox{\textwidth}{!}{%
} {
}
\end{center}
\end{minipage}
\end{center}
}


This has the following syntax:

\newenvironment{arg1}{arg2}


But \newenvironment expects 3 arguments (optionally 4 or 5):

\newenvironment{name of environment}{stuff to do at the beginning of the environment}{stuff to do at the end}


So, your code is interpreted as providing a new enviornment with the name FitToWidth and everything else is interpreted as code to execute before processing the environment's contents.

This means that

  \begin{center}
\begin{minipage}{\textwidth}
\begin{center}
\resizebox{\textwidth}{!}{%
} {
}
\end{center}
\end{minipage}
\end{center}
`

is processed just as it is. That is, you try to resize a box which contains nothing. Nothing has a dimension of zero. Hence, when TeX calculates things, it tries to divide by zero and bails out since it cannot do that.

This answer (admittedly mine) explains the syntax of the standard macros for creating, redefining and providing new LaTeX commands and environments.