1

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}

MWE output


Desired output: MWE output

2
  • (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
1

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}

enter image description here

1
  • 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).
    – schtandard
    Nov 13 '21 at 14:02

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.