2

How to automatically scale a centred image to be (at the same time to being centred) left aligned with a hanging caption?

enter image description here

MWE with guessed image widths:

\documentclass{book}

\usepackage{graphicx}   
\usepackage{caption}                

\captionsetup{%
    singlelinecheck=false,
    format=hang
}

\begin{document}

\chapter{test}

\begin{figure}[htbp]
    \centering
    \includegraphics[width=.7\textwidth]{example-image}
    \caption{Text}
\end{figure}

\setcounter{figure}{1000}

\begin{figure}[htbp]
    \centering
    \includegraphics[width=.62\textwidth]{example-image}
    \caption{Text}
\end{figure}


\end{document}
2
+100

Due to a missunderstanding in my first answer I adapted the caption to the image. Here the image width is adapted to the caption. It works with different label formats.

For this a new caption format was written, which is a copy of the original hang plus a macro to calculate the \imagewidth. The caption must be known before the image, so the command \captionafter sets it into a box. The latter is then printed with \printcaption after the image.

Using these macros will result in this:

enter image description here

The code:

\documentclass{book}
\usepackage[showframe]{geometry} % just for checking centering
\usepackage{etoolbox}
\usepackage{graphicx}   
\usepackage{caption}                

\makeatletter
\newlength{\imagewidth}

\newcommand*{\set@imagewidth}{%
    \global\imagewidth\dimexpr\textwidth-2\caption@hangindent
}

% copoied from caption3.sty, renamed and added \set@imagewidth
\DeclareCaptionFormat{myhang}[#1#2#3\par]{%
  \caption@ifin@list\caption@lsepcrlist\caption@lsepname
    {\caption@Error{%
       The option `labelsep=\caption@lsepname' does not work\MessageBreak
       with `format=hang'}}%
    {\@hangfrom{#1#2}%
     \advance\caption@parindent\hangindent
     \advance\caption@hangindent\hangindent
     % added
     \set@imagewidth
     \caption@@par#3\par}}

% caption must be known to set \imagewidth, so store it in a box
\newbox\captionafterbox
\newcommand{\captionafter}[2][]{%
    \setbox\captionafterbox\vbox{\caption[#1]{#2}}%
}
% and print it later
\newcommand{\printcaption}{\box\captionafterbox}

\makeatother

\captionsetup{%
    singlelinecheck=false,
    format=myhang
}

% just for testing
\setcounter{totalnumber}{4}

\begin{document}

\chapter{test}

\begin{figure}[htbp]
    \centering
    \captionafter{Text}
    \includegraphics[width=\imagewidth,height=1cm]{example-image}
    \printcaption
\end{figure}

\begin{figure}[htbp]
    \centering
    \captionsetup{labelfont=bf}
    \captionafter{Text}
    \includegraphics[width=\imagewidth,height=1cm]{example-image}
    \printcaption
\end{figure}

\setcounter{figure}{1000}

\begin{figure}[htbp]
    \centering
    \captionafter{A very long caption text, which needs more than one line. Just some more text to fill it.}
    \includegraphics[width=\imagewidth,height=1cm]{example-image}
    \printcaption
\end{figure}

\setcounter{figure}{1000000}

\begin{figure}[htbp]
    \centering
    \captionafter{A very long caption text, which needs more than one line. Just some more text to fill it. Amd make it even longer.}
    \includegraphics[width=\imagewidth,height=1cm]{example-image}
    \printcaption
\end{figure}

\end{document}
  • Fantastic! Thank you very much for this nice and clean solution! – user36296 Nov 18 '17 at 18:25
  • @samcarter Thank you very much for the nice blue box below the green hook :-) – Mike Nov 21 '17 at 22:02
  • Figured your answer would look better with more colour :) Your answer help me a lot! – user36296 Nov 21 '17 at 22:08
1

As long as you set the width of the image manually (or know it), you can use this:

Edit: added a command to set up caption so it ocupies the rest of the line.

Edit 2: added onside to \captionsetup in \captionimagewidth;
added a new command \capimagewidth, which corrects width and indent, so for wide images the label ("Figure 1.1") doesn't move into the left margin.

\documentclass{book}
\usepackage[showframe]{geometry} % just for checking centering
\usepackage{etoolbox}
\usepackage{graphicx}   
\usepackage{caption}                

\captionsetup{%
    singlelinecheck=false,
}

\DeclareCaptionLabelFormat{myfigure}{\llap{#1 #2:\ }}
\captionsetup{labelformat=myfigure}

% Edit
\newlength{\capindent}
\newlength{\capwidth}
\newcommand{\captionimagewidth}[1]{%
    \capindent\dimexpr0.5\textwidth-#1/2\relax
    \capwidth\dimexpr\textwidth-\capindent
    \captionsetup{width=\capwidth,margin={\capindent,0pt},oneside}%
}

% Edit 2: added `oneside` to \captionsetup
%         correction for wide images
\newcommand{\capimagewidth}[1]{%
    \capindent\dimexpr0.5\textwidth-#1/2\relax
    % from your answer
    \addtocounter{figure}{1}%
    \settowidth{\capwidth}{%
        \figurename~\thefigure:\space% 
    }%
    \addtocounter{figure}{-1}%
    %
    \ifdim\capindent<\capwidth
        \capindent\capwidth
    \fi
    \capwidth\dimexpr\textwidth-\capindent
    \captionsetup{width=\capwidth,margin={\capindent,0pt},oneside}%
}

\begin{document}

\chapter{test}

\begin{figure}[htbp]
    \centering
    \includegraphics[width=0.3\textwidth]{example-image}
    \captionsetup{width=0.3\textwidth}
    \caption{Text}
\end{figure}

\setcounter{figure}{1000}

\begin{figure}[htbp]
    \centering
    \includegraphics[width=0.5\textwidth]{example-image}
    % old
    %\captionsetup{width=0.5\textwidth}
    % Edit
    \captionimagewidth{0.5\textwidth}
    \caption{A very long caption text, which needs more than one line. Just some more text to fill it.}
\end{figure}

\begin{figure}[htbp]
    \centering
    \includegraphics[width=0.9\textwidth]{example-image}
    \capimagewidth{0.9\textwidth}
    \caption{A very long caption text, which needs more than one line. Just some more text to fill it. Amd make it even longer.}
\end{figure}

\end{document}

Result after edit:

enter image description here

But for wide images, the label moves into the margin:

enter image description here

With new command from second edit:

enter image description here

Old result:

enter image description here

  • Thanks a lot for your answer! This is an interesting solution if the caption should not occupy the whole line. – user36296 Nov 18 '17 at 0:19
  • @samcarter I added a solution, wich uses the rest of the line. – Mike Nov 18 '17 at 2:00
  • Thank you very much for your effort! Do you happen to see a way to move the "Figure xxxx" part to the begin of the line? – user36296 Nov 18 '17 at 2:05
  • @samcarter does \DeclareCaptionLabelFormat{myfigure}{\llap{\hbox to \capindent{#1~#2:\hfill}}} do what you want? (This doesn't work with the first version.) – Mike Nov 18 '17 at 3:09
  • @samcarter And it doesn't work for wide images with the second version (\captionimagewidth). Where should the second line hang from, left of the image or right of the "Figure xxxx" part? – Mike Nov 18 '17 at 3:28
1

The following solution is a bit clumsy as it calculates the hanging indent of the caption by emulating the caption label ... this has the big drawback that it does not automatically adjust to the format of the caption, the font size and style.

\documentclass{book}

\usepackage{etoolbox}
\usepackage{graphicx}   
\usepackage{caption}                

\captionsetup{%
    singlelinecheck=false,
    format=hang
}

% calculate idention of caption
\newlength{\captionindent}
\AtBeginEnvironment{figure}{%
    \addtocounter{figure}{1}%
    \settowidth{\captionindent}{%
        Figure\space\thefigure:\space% 
    }%
    \addtocounter{figure}{-1}%
}

\begin{document}

\chapter{test}

\begin{figure}[htbp]
    \centering
    \includegraphics[width=\dimexpr\textwidth-2\captionindent\relax]{example-image}
    \caption{Text}
\end{figure}

\end{document}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.