Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

General description of the intrinsic behavior

The labels in a tikz picture are shifted (e.g. by above) exactly to the extreme of the letters in the labels, i.e. it takes the descender (see Wikipedia's entry for descender) of the letters into account like at the letter "g" (or the "p" of Sphinx).

enter image description here

Different aspect (why that question)

But then the following examples do not look symmetric anymore.

\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\coordinate (leadl) at (1,0);
\coordinate (leadr) at (2,0);
\fill (leadl)  circle[radius=2pt];
\fill (leadr)  circle[radius=2pt];
\node[above] at (leadl) {left};
\node[above] at (leadr) {right};
\end{tikzpicture}
\end{document}

Example with labels above

\documentclass[tikz]{standalone}
\begin{document}
\begin{tikzpicture}
\coordinate (leadl) at (1,0);
\coordinate (leadr) at (2,0);
\fill (leadl)  circle[radius=2pt];
\fill (leadr)  circle[radius=2pt];
\node[below] at (leadl) {lelele};
\node[below] at (leadr) {rerere};
\end{tikzpicture}
\end{document}

enter image description here

Issue to be solved

What is the easiest way to work around this (in some cases wished) feature? I do not want to analyze every character in all nodes' labels that I am typing.

share|improve this question
    
Does there also exist something like anchor=ascent or anchor=descent? I have not found these in the manual. For the case [below] it would be necessary to anchor the ascent or add the font size to the base. –  strpeter Dec 28 '13 at 18:00
add comment

4 Answers

up vote 7 down vote accepted

TikZ understands this problem already and offers text depth length. You can either zero it out or add the fixed amount of depth to all nodes. Example (I somehow like cramped design)

\documentclass[tikz]{standalone}
\begin{document}
\begin{tikzpicture}[scale=1.5]
\coordinate (leadl) at (3,0);
\coordinate (leadr) at (5,0);
\fill (leadr)  circle[radius=2pt];
\fill (leadl)  circle[radius=2pt];
\node[above] at (leadl) {left circle};
\node[above,text depth=0pt] at (leadr) {right circle};
\end{tikzpicture}
\end{document}

enter image description here

share|improve this answer
    
Can you also add an example for labels (rerere vs. lelele) below the node. –  strpeter Dec 28 '13 at 22:00
1  
@strpeter You may use text height and text depth (see pgfmanual, version 3.0.0., pp. 68,69). –  Paul Gaborit Dec 28 '13 at 23:11
    
@strpeter What Paul said. –  percusse Dec 28 '13 at 23:14
    
breath in, breath out ;-) –  Harish Kumar Dec 28 '13 at 23:32
    
@PaulGaborit: text height is independent of the font size, isn't it? I intended to have the same distance above cap height or ascender height and below base w.r.t. the current node - so your reply is not exactly what I intended. Is this reasonable? –  strpeter Dec 30 '13 at 7:44
show 1 more comment

What you need to do is add anchor=base to the options of the two nodes. It will align the two labels by their base lines. Presumably you meant to write:

\node[above of=leadl, anchor=base] {left circle};

In order to anchor to the ascent or descent, you would use e.g. anchor=north. This will anchor the node at the middle of the upper edge of the node. However, there is some invisible padding inside the node (try adding e.g. fill=blue to see the padding). To remove the padding, use inner sep=0pt. Other choices for anchor position include north east, north west, south east, etc.

share|improve this answer
    
above=of leadl is more preferable than the deprecated syntax above of=leadl –  Kevin C Dec 31 '13 at 3:01
    
I always forget which one is preferred. Is there a reason for the preference? –  Yori Jan 1 at 11:19
    
add comment

Here is a general solution with two variants : \strut or \vphantom. This solution may be used with multi-lines nodes or different font sizes.

enter image description here

\documentclass{standalone}
\usepackage{tikz}
\tikzset{
  fix node via strut/.style={
    execute at begin node={\strut},
    execute at end node={\strut},
  },
  fix node via vphantom/.style={
    execute at begin node={\vphantom{Ag}},
    execute at end node={\vphantom{Ag}},
  },
}
\begin{document}
\begin{tikzpicture}
  \coordinate (leadl) at (1,0);
  \coordinate (leadr) at (2,0);
  \fill (leadl)  circle[radius=2pt];
  \fill (leadr)  circle[radius=2pt];
  \node[fix node via strut,above,align=center] at (leadl) {left\\left};
  \node[fix node via strut,above,align=center] at (leadr) {right\\right};
  \node[fix node via strut,below,font=\large] at (leadl) {lelele};
  \node[fix node via strut,below,font=\large] at (leadr) {rerere};
  \node[blue,above] at (current bounding box.north){via strut};
\end{tikzpicture}
\begin{tikzpicture}
  \coordinate (leadl) at (1,0);
  \coordinate (leadr) at (2,0);
  \fill (leadl)  circle[radius=2pt];
  \fill (leadr)  circle[radius=2pt];
  \node[fix node via vphantom,above,align=center] at (leadl) {left\\left};
  \node[fix node via vphantom,above,align=center] at (leadr) {right\\right};
  \node[fix node via vphantom,below,font=\large] at (leadl) {lelele};
  \node[fix node via vphantom,below,font=\large] at (leadr) {rerere};
  \node[red,above] at (current bounding box.north){via vphantom};
\end{tikzpicture}
\end{document}
share|improve this answer
1  
It would be nice to define a key like tall text/.style={every node/.append style={ execute at begin node={\strut}, execute at end node={\strut}, }} so you can use it in a scope to modify the behaviour of text in every node. –  Bordaigorl Dec 31 '13 at 0:41
    
@Paul Gaborit: Why did you set font=\large at the labels below the nodes? –  strpeter Dec 31 '13 at 7:59
    
@strpeter To show that my solution takes into account the current font size of the node. –  Paul Gaborit Dec 31 '13 at 8:10
add comment

I wrote something like this for a similar purpose. Arguably it is a bit bulky for what it accomplishes, but perhaps you will find it useful.

\usepackage{xparse}
\makeatletter
\newcommand{\standardisebox}[1]{%
    \smash{#1}\vphantom{\strpeters@box@determining@symbol}%
}
\let\standardizebox\standardisebox
\NewDocumentCommand{\setboxdeterminingsymbol}{sm}{%
    \IfBooleanTF {#1}%
                 {\gdef\strpeters@box@determining@symbol{#2}}%
                 {\def\strpeters@box@determining@symbol{#2}}%
}
\NewDocumentCommand{\resetboxdeterminingsymbol}{s}{%
    \IfBooleanTF {#1}%
                 {\setboxdeterminingsymbol*{0}}%
                 {\setboxdeterminingsymbol{0}}%
}
\resetboxdeterminingsymbol
\makeatother

The way this works is, you wrap the node text in \standardisebox and it is typeset as though it had the height and depth of a digit 0 instead of its true height and depth. You can change the character used to determine the height and depth using the macro \setboxdeterminingsymbol, and reset it to normal using \resetboxdeterminingsymbol. Use the starred forms for global changes.

\documentclass{standalone}
\usepackage{tikz}
\usepackage{xparse}
\makeatletter
\newcommand{\standardisebox}[1]{%
    \smash{#1}\vphantom{\strpeters@box@determining@symbol}%
}
\let\standardizebox\standardisebox
\NewDocumentCommand{\setboxdeterminingsymbol}{sm}{%
    \IfBooleanTF {#1}%
                 {\gdef\strpeters@box@determining@symbol{#2}}%
                 {\def\strpeters@box@determining@symbol{#2}}%
}
\NewDocumentCommand{\resetboxdeterminingsymbol}{s}{%
    \IfBooleanTF {#1}%
                 {\setboxdeterminingsymbol*{0}}%
                 {\setboxdeterminingsymbol{0}}%
}
\resetboxdeterminingsymbol
\makeatother
\begin{document}
\begin{tikzpicture}
\coordinate (leadl) at (1,0);
\coordinate (leadr) at (2,0);
\fill (leadr)  circle[radius=2pt];
\fill (leadl)  circle[radius=2pt];
\node[above] at (leadl) {\standardisebox{left}};
\node[above] at (leadr) {\standardisebox{right}};
\end{tikzpicture}
\end{document}

In my case I was placing nodes (actually node labels) systematically inside of another macro, so using the macro to reset all of their boxes was not hard work. If you're setting many nodes manually, then wrapping each of them in the macro may prove to be arduous.

share|improve this answer
    
Sorry, I don't understand what's the use case of this: isn't my answer delegating all this hard word to TiKZ which already knows how to deal with ascents and descents? –  Yori Dec 28 '13 at 18:40
    
@Yori, your answer works well when the nodes are positioned above other picture elements. Your prescription for when the nodes are to be positioned below other picture elements is to use e.g. the "north" anchor. This as far as I can see doesn't work so well when one node text has ascenders and the other doesn't (e.g. one node text is "lalala" and the other is "woowoowoo") –  Hammerite Dec 28 '13 at 18:45
    
I see. But wouldn't anchor=base, yshift=-1ex do the trick in that case? This would "anchor" the node at 1ex (the height of an x) above the base line, which is at the median line (see figure above). –  Yori Dec 28 '13 at 18:52
    
Yes, that seems like it would work. –  Hammerite Dec 28 '13 at 19:13
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.