Improved version
In this improved version, you can apply a scaling factor to the arrow:
\documentclass{article}
\usepackage{tikz-cd}
\usetikzlibrary{decorations.markings,intersections}
\tikzset{%
scalearrow/.style n args={3}{
decoration={
markings,
mark=at position (1-#1)/2*\pgfdecoratedpathlength
with {\coordinate (#2);},
mark=at position (1+#1)/2*\pgfdecoratedpathlength
with {\coordinate (#3);},
},
postaction=decorate,
}
}
\begin{document}
\noindent
Scaling factor=1 (no scaling):\par
\begin{tikzcd}[row sep=huge,column sep=huge]
A \dar\rar & B\dar\dlar[phantom,scalearrow={1}{start}{end}]\arrow[dr,Rightarrow,to path= (start) -- (end)] \\
C \rar & D
\end{tikzcd}
\par\medskip
\noindent
Scaling factor=0.5:\par
\begin{tikzcd}[row sep=huge,column sep=huge]
A \dar\rar & B\dar\dlar[phantom,scalearrow={0.5}{start}{end}]\arrow[dr,Rightarrow,to path= (start) -- (end)] \\
C \rar & D
\end{tikzcd}
\par\medskip
\noindent
Two arrows, each with scaling factor=0.3333:\par
\begin{tikzcd}[row sep=huge,column sep=huge]
A
\dar\rar
&
B
\dar
\dlar[phantom,scalearrow={0.3333}{starta}{enda}]
\arrow[dr,Rightarrow,to path= (starta) -- (enda)] &
C
\dar\lar
\\
D \rar
&
E
&
F
\lar
\ular[phantom,scalearrow={0.3333}{startb}{endb}]
\arrow[ul,Rightarrow,to path= (startb) -- (endb)]
\end{tikzcd}
\end{document}
The idea is to measure the path length using a decoration and \pgfdecoratedpathlength
and to place two marks along the path such that the distance between those marks is the path length scaled by the desired factor.
This is achieved by using a "phantom" arrow with the scalearrow
style; in this style you set the scaling factor (first argument for the style) and two names internally used for the start and end of the scaled path so, for example,
\dar[phantom,scalearrow={0.3333}{name1}{name2
places a downwards arrow from the current node (let's refer to it as X
) to the node below it (let's refer to it as Y
) and sets two internal coordinates called name1
and name2
at the exact position along the path from X
to Y
in such a way that now you can use those names to draw the scaled arrow (using a factor of 0.3333
for the scaling) using, for example
\arrow[d,Rightarrow,to path= (name1) -- (name2)]
First version
One option using shorten
:
\documentclass{article}
\usepackage{tikz-cd}
\begin{document}
\begin{tikzcd}[column sep = large, row sep = large]
* \dar \rar &* \dar \dlar[Rightarrow,shorten >= 10pt,shorten <= 10pt]{} \\
* \rar &*
\end{tikzcd}
\end{document}
Here is a possibility. Define a new arrow type called myarrow
, which is a white arrow decorated with a special arrowhead. The arrowhead is a Butt Cap
of a given length followed by a standard arrowhead (shifted to keep it centered). The length is controlled globally by \myarrowlength
. You can then use myarrow
for a single arrow as in the first example using \arrow[r, myarrow]
, or for all arrows as in the second example using \begin{tikzcd}[arrows=myarrow]
\documentclass{article}
\usepackage{tikz-cd}
\usetikzlibrary{decorations.markings}
\newcommand{\myarrowlength}{10pt}
\tikzset{mytip/.tip={Butt Cap[black, length=\myarrowlength, sep=-1.6pt]>[black]},
myarrow/.style={white, decoration={transform={xshift=.5*\myarrowlength}, markings, mark=at position .5 with {\arrow{mytip}}}, postaction=decorate}}
\begin{document}
\begin{tikzcd}
A\arrow[dr]\\
B\arrow[u]\arrow[r, myarrow] & C
\end{tikzcd}
\qquad
\begin{tikzcd}[arrows=myarrow]
A\arrow[dr]\\
B\arrow[u]\arrow[r] & C
\end{tikzcd}
\end{document}
Update:
To add labels to the arrows, the white arrow must get a label. This is now included in the definition, along with a default empty label. For example, myarrow="h"'
will place the label h
on the "right" side. Use {}
for more complicated labels, e.g., myarrow={"h"', text=red}
.
\documentclass{article}
\usepackage{tikz-cd}
\usetikzlibrary{decorations.markings}
\newcommand{\myarrowlength}{10pt}
\tikzset{mytip/.tip={Butt Cap[black, length=\myarrowlength, sep=-1.6pt]>[black]},
myarrow/.style={white, text=black, #1, decoration={transform={xshift=.5*\myarrowlength}, markings, mark=at position .5 with {\arrow{mytip}}}, postaction=decorate},
myarrow/.default={}}
\begin{document}
\begin{tikzcd}
A\arrow[dr]\\
B\arrow[u]\arrow[r, myarrow="h"'] & C
\end{tikzcd}
\qquad
\begin{tikzcd}[arrows=myarrow]
A\arrow[dr]\\
B\arrow[u]\arrow[r] & C
\end{tikzcd}
\end{document}
Best Answer
The label
long label
contributes to the bounding box of the TikZ picture (usually something you want), however, with the optionoverlay
you can instruct TikZ to ignore the label for the bounding box altogether.Since you've used
\text
(fromamsmath
?)I've also added ano math
key that a) switches off math-mode for the labels of that edge and b) sets the fontsize of the label to\scriptsize
(where\scriptstyle
is used for math-mode). Theno math
key needs to be used as an option to the arrow and not the label itself.You can also use the options
trim left
andtrim right
(as I did in another answer) so that only the matrix itself will determine the horizontal size of the diagram. This is a more general solution but may have disadvantage with wider and complex diagrams?The underlying TikZ matrix that is used by TikZ-CD also supports the columns to be spaced by a distance between their origins (and not their borders), this means you need to specify
between origins
when giving acolumn sep
eration. Unfortunately, the default value and the values predefined by TikZ-CD aren't easily accessible then but you need to specify the length more or less on your own anyway because this is of course dependent on all your diagrams and the content of the cells. I'm randomly choosing 4.6em since it looks good for that case but you can of course change the default value or usecolumns from center=<distance>
manually.Should this be done more automatically, the width of the nodes need to be measured or the widest node needs to be specified by the user and taken into account, this is possible but there are many cases that need to be considered (how should a diagram with three columns look?).
Code
Output