\documentclass{beery}


\RequirePackage { fontspec }
\newfontfamily \newfontfamilystixtwo { STIX Two Text }
\newfontfamily \newfontfamilysourceseriffour { Source Serif 4 }


\begin{document}


\section*{\Large The \pkg{scaletextbullet} package}

Resize the \cs{textbullet} without changing its vertical center

Oliver Beery

Version 2.0.4\quad 5 November 2025


\section{Introduction}
\label{sec:intro}

\subsection{About}
\label{subsec:about}

The \pkg{scaletextbullet} package enables the user to resize the \cs{textbullet} without moving its vertical center, unlike direct usage of the \LaTeXe{} and \pkg{expl3} commands \cs{scalebox} and \cs{box_scale:}.
This process is not fully automated---the user must use \cs{settextbulletfactor} to set the \cs{textbullet} factor to the correct value to display the resized \cs{textbullet} at the correct height.
The \cs{textbullet} factor is the ratio of the width of the \cs{textbullet}, excluding its empty space, to its width, including its empty space.
One way of estimating the \cs{textbullet} factor is by using \cs{scaletextbulletdebug}.

This package provides a solution that works only in text mode.
For a solution that works only in math mode, see the linked \TeX{} Stack Exchange thread.%
\footnote{\url{https://tex.stackexchange.com/questions/119319/how-to-correctly-shrink-the-bullets-of-itemize}}

\subsection{Loading the package}
\label{subsec:loading}

\listheading{Requirements:}
\begin{itemize}
  \item \LaTeXe{} version 2023-11-01 or newer
  \item \pkg{l3kernel} version 2023-11-01 or newer
\end{itemize}

\subsection{Syntax}
\label{subsec:syntax}

This documentation uses the syntaxes \meta{fp expr} and \meta{int expr}.
These syntaxes have the same meaning as the arguments to \cs{fpeval} and \cs{inteval}, respectively, which are documented in \pkg{usrguide}.


\section{Commands}
\label{sec:commands}

\begin{function}{\settextbulletfactor}
  \begin{syntax}
    \cs{settextbulletfactor}\marg{fp expr}
  \end{syntax}
  Sets the \cs{textbullet} factor to the result of evaluating the \meta{fp expr}.
  This assignment is local to the current group.
  The \cs{textbullet} factor is the ratio of the width of the \cs{textbullet}, excluding its empty space, to its width, including its empty space.
  The initial \cs{textbullet} factor is \num{0.4}---this matches the dimensions of the \cs{textbullet} of the Latin Modern font at size \qty{10}{pt}.
\end{function}

\begin{function}{\scaletextbullet}
  \begin{syntax}
    \cs{scaletextbullet}\marg{fp expr}
  \end{syntax}
  Prints a \cs{textbullet} with its size scaled by a factor equal to the result of evaluating the \meta{fp expr}.
  The new \cs{textbullet} will be printed with the same vertical center only if the \cs{textbullet} factor is set to the correct value.

  \listheading{Some exceptions:}
  \begin{itemize}
    \item
    Issues an error if the result of evaluating the \meta{fp expr} is a negative number.
    \item
    Issues a warning if the new \cs{textbullet} would have zero dimensions.
    \item
    Cannot be used in math mode.
  \end{itemize}
\end{function}

\begin{function}{\scaletextbullets}
  \begin{syntax}
    \cs{scaletextbullets}\oarg{fp expr}\marg{int expr}
  \end{syntax}
  Prints a number of \cs{textbullet}s equal to the result of evaluating the \meta{int expr} with about the same total area as the original \cs{textbullet}.\footnotemark{}
  Adding the optional argument instead scales the size of each \cs{textbullet} by a factor equal to the result of evaluating the \meta{fp expr}.
  The new \cs{textbullet} will be printed with the same vertical center only if the \cs{textbullet} factor is set to the correct value.

  \listheading{Some exceptions:}
  \begin{itemize}
    \item
    Issues an error if the result of evaluating the \meta{int expr} or \meta{fp expr} is a negative number.
    \item
    Issues a warning if no \cs{textbullet}s would be printed.
    \item
    Issues a warning if the new \cs{textbullet} would have zero dimensions.
    \item
    Cannot be used in math mode.
  \end{itemize}
\end{function}
\footnotetext
  {%
    In calculating the total area, I have approximated each \cs{textbullet} as a perfect circle, but, of course, the actual shape depends on the font used.%
  }

\begin{function}{\scaletextbulletdebug}
  \begin{syntax}
    \cs{scaletextbulletdebug}
  \end{syntax}
  This command is provided only to help the user estimate the \cs{textbullet} factor.
  Prints \num{15} consecutive \cs{textbullet}s with decreasing sizes.
  The \cs{textbullet}s are followed by the original \cs{textbullet} inside a framed box.
  The framed box has width equal to the \cs{textbullet} factor \texttimes{} the total width of the \cs{textbullet} (this includes its empty space).
  The \cs{textbullet} factor is set to the correct value when the \num{15} consecutive \cs{textbullet}s have the same vertical center and the \cs{textbullet} fits nicely inside the framed box.
  Cannot be used in math mode.
\end{function}


\section{Application}
\label{sec:application}

I wrote this package primarily to create nicer-looking itemized lists.
The default list labels in \LaTeX{} (and other programs) fail to communicate the list level within the list hierarchy:

\begin{multicols}{2}
  \begin{itemize}[label=\textbullet]
    \item List level 1
    \begin{itemize}[label=\textbf{--}]
      \item List level 2
      \item List level 2
      \begin{itemize}[label=\textasteriskcentered]
        \item List level 3
      \end{itemize}
    \end{itemize}
    \item List level 1
    \begin{itemize}[label=\textbf{--}]
      \item List level 2
      \begin{itemize}[label=\textasteriskcentered]
        \item List level 3
        \item List level 3
      \end{itemize}
    \end{itemize}
  \end{itemize}
\end{multicols}

This contrasts with traditional enumerated list structures where the list level is obvious from the numbering of the list label:

\begin{multicols}{2}
  \begin{enumerate}
    \item List level 1
    \begin{enumerate}
      \item List level 2
      \item List level 2
      \begin{enumerate}
        \item List level 3
      \end{enumerate}
    \end{enumerate}
    \item List level 1
    \begin{enumerate}
      \item List level 2
      \begin{enumerate}
        \item List level 3
        \item List level 3
      \end{enumerate}
    \end{enumerate}
  \end{enumerate}
\end{multicols}

This package allows the user to create nice-looking itemized lists using \cs{scaletextbullets} where the number of scaled \cs{textbullet}s in the list label indicates the list level:

\begin{multicols}{2}
  \begin{itemize}
    \item List level 1
    \begin{itemize}
      \item List level 2
      \item List level 2
      \begin{itemize}
        \item List level 3
      \end{itemize}
    \end{itemize}
    \item List level 1
    \begin{itemize}
      \item List level 2
      \begin{itemize}
        \item List level 3
        \item List level 3
      \end{itemize}
    \end{itemize}
  \end{itemize}
\end{multicols}

The visual effect may be more clear with different fonts.
This example uses STIX Two Text and Source Serif 4, respectively.

\begingroup
  \settextbulletfactor{0.54}
  \newfontfamilystixtwo
  \begin{multicols}{2}
    \begin{itemize}
      \item List level 1
      \begin{itemize}
        \item List level 2
        \item List level 2
        \begin{itemize}
          \item List level 3
        \end{itemize}
      \end{itemize}
      \item List level 1
      \begin{itemize}
        \item List level 2
        \begin{itemize}
          \item List level 3
          \item List level 3
        \end{itemize}
      \end{itemize}
    \end{itemize}
  \end{multicols}
\endgroup

\begingroup
  \settextbulletfactor{0.75}
  \newfontfamilysourceseriffour
  \begin{multicols}{2}
    \begin{itemize}
      \item List level 1
      \begin{itemize}
        \item List level 2
        \item List level 2
        \begin{itemize}
          \item List level 3
        \end{itemize}
      \end{itemize}
      \item List level 1
      \begin{itemize}
        \item List level 2
        \begin{itemize}
          \item List level 3
          \item List level 3
        \end{itemize}
      \end{itemize}
    \end{itemize}
  \end{multicols}
\endgroup


\section{Implementation notes}
\label{sec:implementation}

The procedure of resizing the \cs{textbullet} without changing its vertical center, including the definition of the \cs{textbullet} factor, makes an important assumption:
That the \cs{textbullet} is a perfect circle.
Of course, this is not completely accurate and the actual shape depends on the font used.
This means that the \cs{textbullet} factor may not be exactly the ratio of the width of the \cs{textbullet}, excluding its empty space, to its width, including its empty space.

In writing this package, I have referenced a comment on the \TeX{} Stack Exchange by the user egreg.%
\footnote{\url{https://tex.stackexchange.com/questions/620507/how-to-resize-textbullet-without-the-bullet-moving-down}}
This package uses the same procedure for resizing the \cs{textbullet} without changing its vertical center.


\end{document}
