# Balancing ragged right line lengths

I have a \section-like command that takes an optional title. The title may be empty (default), short or so long that it doesn't fit on one line. In the latter case, I would like it to be split into lines of about equal length and printed \raggedright. Is this possible?

I found other questions where the approach is to reduce the glue added at the end of each line, but I don't think I can go that route since the title may be empty and I would need the glue to stretch over the whole line in that case.

Here's a toy version of my command.

\documentclass{article}

\newcommand*\foo[1]{%
\par
{\raggedright\Large\bfseries\sffamily
\strut #1%
\par
}%
\hrule
\noindent\ignorespaces
}

\begin{document}

\noindent
asdf

\foo{}
asdf

\foo{short}
asdf

\foo{long, I mean really long, so long that it can't fit on a single line}
asdf

\end{document}


Desired output:

• (Not tested.) Set the title in a box, and determine if the width exceeds the default text width. If it does, try using a parbox that's (say) .6 times the width of the measured line. Some iteration may be needed to determine an "ideal" length. Nov 12 '21 at 18:29
• you could set it first in an hbox, measure the natural length decide how many lines are needs and then set in a parbox of a suitable width, but to be honest I wouldn't I would just use \\  to add line breaks by hand, choosing good breaks for the heading Nov 12 '21 at 18:29

I compute the natural width of the text and then set \rightskip to the line width minus an approximate width for the lines to typeset, with some stretchability.

Also applying a rather high value for \linepenalty, we keep the number of lines at the minimum.

\documentclass[draft]{article}
\usepackage{xfp}

\newcommand{\fooformat}{\Large\bfseries\sffamily}

\newcommand*\foo[1]{%
\par
\sbox0{\fooformat #1}%
{%
\raggedright
\fooformat
\linepenalty3000
\rightskip=\dimexpr\linewidth-\wd0/\fpeval{1+round(\wd0/\textwidth)}\relax plus 4em\relax
\strut #1\par
}%
\hrule
\noindent\ignorespaces
}

\begin{document}

\noindent
asdf

\foo{}
asdf

\foo{short}
asdf

\foo{long, I mean really long, so long that it can't fit on a single line}
asdf

\foo{long, I mean really long, so long that it can't fit on a single line
and even longer, but really really longer}
asdf

\end{document}


• Very nice. I allowed my \rightskip to shrink to zero, which avoids additional problems (in my tests, changing \lineskip wasn't necessary with this change). Nov 13 '21 at 14:02