# How to avoid or compensate horizontal and vertical shifts in a tikz' struck out node?

The following MCE below points out that, for a tikz' struck out node, the line width causes both horizontal and vertical shifts. Is it possible to

• avoid them?
• Or, at least, to know exactly the dimensions of these shifts in order to compensate them (the struck out text to be at the same place as would be the "normal" one)?

This question is in the same spirit as How to avoid shifts for content which is "strike out" (from tikz shapes.misc library)? but the other way round: here, I want the "normal" text to not be shifted as is the struck out one but the struck out text to not be shifted and being at the same place as would be the "normal" one.

\documentclass{article}
\usepackage[arrows=false]{pagegrid}
\usepackage[margin=0cm,papersize=2cm]{geometry}
\usepackage{tikz}
\usetikzlibrary{shapes}
%
\setlength{\parindent}{0pt}
%
\newcommand{\test}[1][]{%
\tikz \node [draw,inner sep=0pt,outer sep=0pt,strike out,draw=red,#1] {%
test%
};%
}
%
\begin{document}
test \test{} \test[line width=.5ex]

\test{} \test[line width=.5ex] test

\test[line width=.5ex] test \test{}
\end{document}


If I understand you correctly you could perhaps draw the strike out as a separate node (using the fit library to get the correct size), and add the overlay option to that node, so that it isn't considered for the calculation of the bounding box.

\documentclass{article}
\usepackage[arrows=false]{pagegrid}
\usepackage[margin=0cm,papersize=2cm]{geometry}
\usepackage{tikz}
%
\setlength{\parindent}{0pt}
%
\newcommand{\test}[1][]{%
\begin{tikzpicture}
\node [inner sep=0pt,outer sep=0pt] (foo) {test};
% draw strike out in separate node, with overlay option
\node [overlay,inner sep=0pt,fit=(foo),strike out,draw=red,#1] {};
\end{tikzpicture}%
}
%
\begin{document}
test \test{} \test[line width=.5ex]

\test{} \test[line width=.5ex] test

\test[line width=.5ex] test \test{}
\end{document}


It is quite easy to create your own strike out command using tikz. Just use [remember picture,overlay] option for the tikz environment to avoid interfering with the text.

\documentclass{article}
\usepackage[arrows=false]{pagegrid}
\usepackage[margin=0cm,papersize=2cm]{geometry}
\usepackage{tikz,calc}
\usetikzlibrary{shapes}
%
\setlength{\parindent}{0pt}
%
\newlength\teht
\settoheight\teht{t}
\newcommand\tikzmark[1]{\tikz[remember picture,overlay]\coordinate(#1);}

\newcommand{\test}[2][]{%
\tikzmark{o}#2\tikzmark{a}%
\tikz[remember picture, overlay]{\draw[red,#1](o)--([yshift=\teht]a);}%
}
\begin{document}
test \test{test} \test[line width=.5ex]{test}

\test{test} \test[line width=.5ex]{test} test

\test{test} test \test[line width=.5ex]{test}
\end{document}


• Works well, but needs to manually specify the height of the text. Mar 4, 2018 at 9:44
• LaTeX will help you specify the height automatically by the \settoheight\teht{t} command. Mar 4, 2018 at 9:54
• That's what I meant :) You have to manually specify the height (with \settoheight) of the text's highest letter. Mar 4, 2018 at 10:23

An almost identical question has been asked here, and I am just recycling this answer.

\documentclass{article}
\usepackage[arrows=false]{pagegrid}
\usepackage[margin=0cm,papersize=2cm]{geometry}
\usepackage{tikz}
\usetikzlibrary{calc}
\usepackage{tikzpagenodes}

\tikzset{StrikeOut/.style={-,red}}

\makeatletter
\newcommand{\gettikzxy}[3]{% from https://tex.stackexchange.com/a/58590/121799
\tikz@scan@one@point\pgfutil@firstofone#1\relax
\global\edef#2{\the\pgf@x}%
\global\edef#3{\the\pgf@y}%
}
\makeatother
\newcommand{\StrikeOut}[2][]{%
\tikz[remember picture,overlay, baseline=(Begin.base)]{%
\node[anchor=base,inner sep=0pt,outer sep=0pt] (Begin) {\strut};}#2%
\tikz[remember picture,overlay, baseline=(End.base)]{%
\node[anchor=base,inner sep=0pt,outer sep=0pt] (End) {\strut};}%
\begin{tikzpicture}[overlay,remember picture]
\gettikzxy{($(Begin.north)-(current page.south west)$)}{\BeginxN}{\BeginyN}
\gettikzxy{($(End.north)-(current page.south west)$)}{\EndxN}{\EndyN}%\typeout{\BeginyN\space\EndyN}
\pgfmathtruncatemacro{\mytest}{\EndyN-\BeginyN}
\ifnum\mytest=0\relax% begin and and in the same line %\typeout{begin and end in the same line}
\draw[StrikeOut,#1] (Begin.north) -- (End.south);
\draw[StrikeOut,#1] (Begin.south) -- (End.north);
\else% \typeout{end below begin}
\path (current page text area.north west) -- (current page text area.south west)
node(WestLine)[left]{};
\path (current page text area.north east) -- (current page text area.south east)
node(EastLine)[right]{};
\gettikzxy{($(End.north)-(current page.south west)$)}{\EndxN}{\EndyN}
\gettikzxy{($(Begin.south)-(current page.south west)$)}{\BeginxS}{\BeginyS}
\pgfmathtruncatemacro{\mytest}{\BeginyS-\EndyN+1pt}% \typeout{\mytest}
\ifnum\mytest<2\relax% \typeout{end in the next line after begin}%
\pgfmathtruncatemacro{\mytest}{\BeginxS-\EndxN}% \typeout{\mytest}
\ifnum\mytest>0\relax
\draw[StrikeOut,#1] (Begin.north) -- (Begin.south -| EastLine);
\draw[StrikeOut,#1] (Begin.south) -- (Begin.north -| EastLine);
\draw[StrikeOut,#1] (End.north -| WestLine) -- (End.south);
\draw[StrikeOut,#1] (End.south -| WestLine) -- (End.north);
\else
\draw[StrikeOut,#1] (Begin.south) -- (Begin.north -| EastLine);
\draw[StrikeOut,#1] (Begin.north) -- (Begin.south -| EastLine);
\draw[StrikeOut,#1] (End.north -| WestLine) -- (End.south);
\draw[StrikeOut,#1] (End.south -| WestLine) -- (End.north);
\fi
\else
\pgfmathsetmacro{\LineHeight}{\the\baselineskip}
\pgfmathtruncatemacro{\NumLines}{-1+(\BeginyN-\EndyN)/\LineHeight}
\typeout{\NumLines}
\foreach \X in {1,...,\NumLines}
{
\draw[StrikeOut,#1] ($(Begin.north -| WestLine)+(0,-\X*\LineHeight pt)$) --
($(Begin.south -|EastLine)+(0,-\X*\LineHeight pt)$);
\draw[StrikeOut,#1] ($(Begin.south -| WestLine)+(0,-\X*\LineHeight pt)$) --
($(Begin.north -|EastLine)+(0,-\X*\LineHeight pt)$);
}
\draw[StrikeOut,#1] (Begin.north) -- (Begin.south -| EastLine);
\draw[StrikeOut,#1] (Begin.south) -- (Begin.north -| EastLine);
\draw[StrikeOut,#1] (End.north -| WestLine) -- (End.south);
\draw[StrikeOut,#1] (End.south -| WestLine) -- (End.north);
\fi
\fi
\end{tikzpicture}}
\begin{document}
\noindent
test \StrikeOut{test} \StrikeOut[line width=.5ex]{test}\\
\StrikeOut{test} \StrikeOut[line width=.5ex]{test} test\\
\StrikeOut[line width=.5ex]{test} test \StrikeOut{test}\\
\end{document}


• Works well, but much more complicated than the fit method. Mar 4, 2018 at 9:43
• @DenisBitouzé The method is not too different. The reason why it looks more complicated is that this macro works also when the text runs over more than one lines.
– user121799
Mar 4, 2018 at 10:48
• Indeed but, in such a case, maybe a unique cross over the whole paragraph would be expected (instead of a each line of the paragraph to be crossed). Anyway, this would be matter of another question :) Mar 4, 2018 at 12:08
• @DenisBitouzé If you look at this answer, you'll see that the crossed out text has in general not a box shape, so I wonder how you would put a big cross on it. However, if you have a clear prescription, then the above may be the basis for a macro since it already recognizes the three situation: (1) all in one line, (2) two lines and (3) more than three lines. (Notice that this answer can be the basis for a macro that also works with page breaks.)
– user121799
Mar 4, 2018 at 20:08