创建具有两列不同宽度的列表的最简单方法可能是将其分成两个小页面:
但是,右列的文本比左列高。我希望左侧列表均匀拉伸(仅在项目之间,项目内的行间空间不增加)并与右列底部对齐。这可以通过 实现multicol
,但这样列的宽度将相同(似乎没有办法解决这个问题):
\documentclass{article}
\usepackage{lipsum}
\usepackage{multicol}
\begin{document}
\begin{multicols}{2}
\begin{description}
\item \lipsum[1][1]
\item \lipsum[1][2]
\item \lipsum[1][3]
\item \lipsum[1][4]
\item \lipsum[1][5-6]
\item \lipsum[1][7-9]
\end{description}
\end{multicols}
\end{document}
有没有一种简单的方法可以用两列不同的宽度来实现这一点?
答案1
新版本
OP 还想删除并平衡环境前后的空间。通常这对于minipage
s 来说很难,但在我们的例子中,我们确切地知道 minipage 的高度以及各个基线应该在哪里,这样我们就可以作弊。
在执行此操作时,我还发现了原始答案的一个错误:当第一行和底线不是通用时,它无法正确考虑。 (例如,您可以看到如果用替换的内容会发生什么rightbody
。\item aaa \item aaa
使用的 minipage 太大而无法获得正确的对齐。)
我们需要做的:
- 设置
\topsep
并\partopsep
使其0pt
不\trivlist
添加额外的空间。 - 通过测量每个框来正确计算所需的空间:第一行的高度、最后一行的深度以及“主体”高度(第一行基线以下和底线基线以上的所有内容)。
- 说服 TeX不是使用 minipage 来计算行距。为此,我将使用
\smash
minipages。我将插入一条规则,其中第一行的高度(高度由顶部框的顶部行高中较大的一个给出),然后是\vskip
适当的量(“主体高度”减一\baselineskip
),并插入另一条规则(在基线以下下降两个框的底部深度中较大的一个)。这样,minipages 前后的行间距将完全按照内容“在线”显示的方式计算。 - 额外的外观变化:
\hfill
如果指定的宽度加起来不等于全宽,我会在两个小页面之间放置一个来将它们展开。
% Note: if using the lua-visual-debug package, build with lualatex
% If comment out the package, you can build with pdflatex
\documentclass{article}
\usepackage{lua-visual-debug} % used to show the boxes so that the proper alignment is clear
\usepackage{lipsum}
\usepackage{enumitem}
\usepackage{environ}
%%%%
\makeatletter
\newlength\@LBwd
\newlength\@RBwd
\newlength\@LBtopht
\newlength\@LBtopdp
\newlength\@LBbodht
\newlength\@LBbotdp
\newlength\@RBtopht
\newlength\@RBtopdp
\newlength\@RBbodht
\newlength\@RBbotdp
\NewEnviron{leftbody}{%
\expandafter\gdef\expandafter\@leftbodycontent\expandafter{\BODY}%
\sbox0{%
\begin{minipage}[t]{\@LBwd}
\BODY
\end{minipage}%
}%
\global\@LBtopht=\ht0\relax%
\global\@LBtopdp=\dp0\relax%
\sbox0{%
\begin{minipage}[b]{\@LBwd}
\BODY
\end{minipage}%
}
\global\@LBbotdp=\dp0\relax%
\global\@LBbodht=\dimexpr\@LBtopdp-\@LBbotdp\relax%
}
\NewEnviron{rightbody}{%
\expandafter\gdef\expandafter\@rightbodycontent\expandafter{\BODY}%
\sbox0{%
\begin{minipage}[t]{\@RBwd}
\BODY
\end{minipage}%
}%
\global\@RBtopht=\ht0\relax%
\global\@RBtopdp=\dp0\relax%
\sbox0{%
\begin{minipage}[b]{\@RBwd}
\BODY
\end{minipage}%
}
\global\@RBbotdp=\dp0\relax%
\global\@RBbodht=\dimexpr\@RBtopdp-\@RBbotdp\relax%
}
\newlength\@pokeabove
\newlength\@pokebelow
\newenvironment{unevencols}[2]{% args: width of the two columns
\setlength{\@LBwd}{#1}%
\setlength{\@RBwd}{#2}%
}{%
\ifdim\@LBbodht<\@RBbodht\relax%
\@LBbodht=\@RBbodht\relax%
\else
\@RBbodht=\@LBbodht\relax%
\fi
\ifdim\@LBtopht<\@RBtopht\relax%
\@pokeabove=\@RBtopht%
\else
\@pokeabove=\@LBtopht%
\fi
\ifdim\@LBbotdp<\@RBbotdp\relax%
\@pokebelow=\@RBbotdp%
\else
\@pokebelow=\@LBbotdp
\fi
\topsep=0pt \partopsep=0pt
\begin{trivlist}
\item\rule{0pt}{\@pokeabove}\smash{\begin{minipage}[t][\dimexpr\@LBbodht+\@LBtopht+\@LBbotdp\relax]{\@LBwd}
\setlist{itemsep=\fill}%
\@leftbodycontent%
\end{minipage}}\hfill\smash{\begin{minipage}[t][\dimexpr\@RBbodht+\@RBtopht+\@RBbotdp\relax]{\@RBwd}
\setlist{itemsep=\fill}%
\@rightbodycontent%
\end{minipage}}\vskip\dimexpr\@RBbodht-\baselineskip\relax
\item \rule[-\@pokebelow]{0pt}{\@pokebelow}
\end{trivlist}
}
\makeatother
\begin{document}
\lipsum[2]
\begin{unevencols}{0.6\textwidth}{0.4\textwidth}
\begin{leftbody}
\begin{description}
\item \lipsum[1][1]
\item \lipsum[1][2]
\item \lipsum[1][3]
\item \lipsum[1][4]
\end{description}
\end{leftbody}%
\begin{rightbody}
\begin{description}
\item \lipsum[1][5-6]
\item \lipsum[1][7-9]
\end{description}
\end{rightbody}
\end{unevencols}
\lipsum[3]
\begin{unevencols}{0.59\textwidth}{0.2\textwidth}
\begin{leftbody}
\begin{description}
\item \lipsum[1][1]
\item \lipsum[1][2]
\item \lipsum[1][3]
\item \lipsum[1][4]
\end{description}
\end{leftbody}%
\begin{rightbody}
\begin{description}
\item aaa
\item aaa
\end{description}
\end{rightbody}
\end{unevencols}
\lipsum[4]
\end{document}
在下面的图片中,您可以看到,即使其中一个框中的文本没有上升部或下降部,基线对齐仍然是正确的。请注意,通过使用测量的顶部行高和底部行深,如果您的材料超出了行的“正常”高度/深度(例如,当您有数学材料或上标/下标时),间距仍然是正确的。如果没有这种计算,可能会出现叠印。
还请注意,此解决方案与基线两个盒子中材料的顶部和底部线条。如果其中一个盒子的材料特别高或特别深,视觉对齐可能会更差。在这里,我通过一些离谱的数学展示了会发生什么。
答案2
对于更适度的目标,即拉伸项目之间的间隙,并使用手动分栏,您可以测量高度并itemsep=\fill
使用适当的迷你页面进行设置。(我的笔记本电脑上没有latin
连字符,因此对于盲文中的错误连字符表示歉意。)
代码(更多的是概念验证;并没有真正优化)
\documentclass{article}
\usepackage{lipsum}
\usepackage{enumitem}
\usepackage{environ}
%%%%
\makeatletter
\newsavebox{\@lefttextbox}
\newsavebox{\@righttextbox}
\newlength\@leftboxwidth
\newlength\@rightboxwidth
\newlength\@leftboxmeasureht
\newlength\@rightboxmeasureht
\newlength\@largerheight
\NewEnviron{leftbody}{%
\expandafter\gdef\expandafter\@leftbodycontent\expandafter{\BODY}%
\savebox{\@lefttextbox}{%
\begin{minipage}[b]{\@leftboxwidth}
\BODY
\end{minipage}%
}%
\global\@leftboxmeasureht=\ht\@lefttextbox\relax%
}
\NewEnviron{rightbody}{%
\expandafter\gdef\expandafter\@rightbodycontent\expandafter{\BODY}%
\savebox{\@righttextbox}{%
\begin{minipage}[b]{\@rightboxwidth}
\BODY
\end{minipage}%
}%
\global\@rightboxmeasureht=\ht\@righttextbox\relax%
}
\newenvironment{unevencols}[2]{% args: width of the two columns
\setlength{\@leftboxwidth}{#1}%
\setlength{\@rightboxwidth}{#2}%
}{%
\ifdim\@leftboxmeasureht<\@rightboxmeasureht\relax%
\setlength{\@largerheight}{\@rightboxmeasureht}%
\else
\setlength{\@largerheight}{\@leftboxmeasureht}%
\fi
\begin{trivlist}\item\begin{minipage}[t][\@largerheight]{\@leftboxwidth}
\setlist{itemsep=\fill}%
\@leftbodycontent%
\end{minipage}
\begin{minipage}[t][\@largerheight]{\@rightboxwidth}
\setlist{itemsep=\fill}%
\@rightbodycontent%
\end{minipage}
\end{trivlist}
}
\makeatother
%%%%
\begin{document}
\lipsum[2]
\begin{unevencols}{0.59\textwidth}{0.4\textwidth}
\begin{leftbody}
\begin{description}
\item \lipsum[1][1]
\item \lipsum[1][2]
\item \lipsum[1][3]
\item \lipsum[1][4]
\end{description}
\end{leftbody}%
\begin{rightbody}
\begin{description}
\item \lipsum[1][5-6]
\item \lipsum[1][7-9]
\end{description}
\end{rightbody}
\end{unevencols}
\lipsum[3]
\end{document}