The macro \inspace
takes something that normally doesn't fit into an fixed number of lines and overlays it over a fixed number of lines. You can specify the number of lines, or it can compute them based on the size of the box. The options t/c/b align the tops/centers/bottoms of the box and the reserved space. (Anything except t and b is treated as c.)
It should be noted that the first \section
was much larger than the second.
\documentclass[10pt,twocolumn]{book}
\usepackage{calc}
\usepackage{geometry}
%\usepackage{ragged2e}
\usepackage[explicit]{titlesec}
\usepackage{lipsum}
\usepackage{fontspec}
\setmainfont{Cambria}
\setsansfont{Calibri}
\usepackage{everypage}
\usepackage{tikzpagenodes}
\AddEverypageHook{%
\begin{tikzpicture}[overlay,remember picture]
\draw[color=red,very thin]
(current page text area.south west) grid[step=\normalbaselineskip]
(current page text area.north east);
\end{tikzpicture}%
}
\pagestyle{empty}
\geometry{showframe}
\setlength{\parskip}{0pt}
\newcommand{\inspace}[3][c]% #1 = t/c/b (optional), #2 = number of lines (0=compute), #3 = contents
{\bgroup
\setbox0=\vbox{#3}%
\count1=#2\relax
\def\test{#1}%
\ifnum\count1<1
\dimen0=\dimexpr \ht0+\dp0\relax
\count1=\numexpr \dimen0/\baselineskip\relax
\fi
\dimen0=\baselineskip
\multiply\dimen0 by \count1
\ifvmode
\noindent
\let\terminate=\par
\else
\newline
\let\terminate=\newline
\fi
\def\opt{t}% align to top
\ifx\test\opt\relax
\strut\rlap{\raisebox{\dimexpr \ht\strutbox-\ht0}[0pt][0pt]{\usebox0}}\terminate
\else
\def\opt{b}% align to bottom
\ifx\test\opt\relax
\strut\rlap{\raisebox{\dimexpr \ht\strutbox+\dp0-\dimen0}[0pt][0pt]{\usebox0}}\terminate
\else% anything else is centered
\strut\rlap{\raisebox{\dimexpr \ht\strutbox-0.5\ht0+0.5\dp0-0.5\dimen0}[0pt][0pt]{\usebox0}}\terminate
\fi
\fi
\loop\ifnum\count1>1
\advance\count1 by -1
\strut\terminate
\repeat
\egroup}
\begin{document}
\raggedbottom%\raggedright
\inspace[b]{3}{\section{First section}}
\lipsum[1-4]
\inspace[b]{3}{\section{Second section}}
\lipsum[5-7]
\end{document}