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.

This is a question which has been discussed here and here. One of the solution discussed is to use fit to cover empty cells. However, while trying it, it displayed an alignment problem between the empty cells and the others. Here is the MWE from the discussion thread, and where alignment problem is:

\documentclass[xcolor=dvipsnames, 14pt]{beamer}
\usepackage{lmodern}
\usepackage{tikz} 
\usetikzlibrary{matrix, fit}

\begin{document}
\begin{frame}
  \begin{tikzpicture} [
      block/.style ={rectangle
                      %,text width=6em
                      , draw
                      , minimum height=4em
                      , minimum width=4em
                      , outer sep=0pt}
    ]
    \matrix (table) [%
      matrix of nodes
      , nodes in empty cells
      , ampersand replacement=\&
      , nodes=block
    ] {%
      A \& B \& C \& D \\
      E \&   \&   \& G \\
      H \& I \& J \&   \\
      K \& L \& M \&   \\
   };
    %\node[fit=(table-2-2)(table-2-3), inner sep=0pt]{F};
    %\node[fit=(table-3-4)(table-4-4), inner sep=0pt]{N};
  \end{tikzpicture}
\end{frame}
\end{document}

enter image description here

Why do I need multicolumn cells? I actually want to plot the following stacked enter image description here

I managed to do it in tikz, but the code is very inelegant (xshift, yshfit kind of tweaking). I was hoping Matrix could serve as a better solution, but met the aforementioned alignment issue. The following are the MWE of my tweaking solution:

\documentclass[xcolor=dvipsnames, 14pt]{beamer}
\usepackage{lmodern}
\usepackage{tikz} 
\usetikzlibrary{matrix, fit}

\begin{document}
\begin{frame}

  \centering
  \footnotesize
  \begin{tikzpicture}[
      , every node/.style={
                  , rectangle, rounded corners=1mm  % the shape 
                  , very thick , draw % the border 
                  , fill=orange!50
       }]
    \node [minimum width=.6\textwidth] (a) {AAAA};
    \node [minimum width=.3\textwidth] (b) at (a.north) [xshift=-16mm, yshift=4mm] {B};
    \node [minimum width=.07\textwidth] (c) at (b.east) [xshift=5mm] {CCC};
    \node [minimum width=.20\textwidth] (d) at (c.east) [xshift=12mm] {DDDDD};
  \end{tikzpicture}
\end{frame}

\end{document}
share|improve this question

2 Answers 2

up vote 6 down vote accepted

For the alignment issue, you can use the keys text height, text depth, row sep and column sep:

\documentclass[xcolor=dvipsnames, 14pt]{beamer}
\usepackage{lmodern}
\usepackage{tikz} 
\usetikzlibrary{matrix, fit}

\begin{document}
\begin{frame}
  \begin{tikzpicture} [
      block/.style ={rectangle
                      , draw
                      , text height=2em
                      , minimum width=4em,
                      , text depth=1em
                      , outer sep=0pt}
    ]
    \matrix (table) [%
      matrix of nodes
      , nodes in empty cells
      , ampersand replacement=\&
      , nodes=block
      , row sep=-\pgflinewidth
      , column sep=-\pgflinewidth
    ] {%
      A \& B \& C \& D \\
      E \&   \&   \& G \\
      H \& I \& J \&   \\
      K \& L \& M \&   \\
   };
  \end{tikzpicture}
\end{frame}
\end{document}

enter image description here

For the other layout, borrowing some of Jake's code from his answer to Creating a node fitting the horizontal width of two other nodes) to automate the calculations of wider nodes:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning,calc,fit}

\definecolor{myorange}{RGB}{250,192,116}

\pgfkeys{
    /tikz/node distance/.append code={
        \pgfkeyssetvalue{/tikz/node distance value}{#1}
    }
}

\newcommand\widernode[5][myorange]{
\node[
        #1,
        inner sep=0pt,
        shift=($(#2.south)-(#2.north)$),
        yshift=-\pgfkeysvalueof{/tikz/node distance value},
        fit={(#2) (#3)},
        line width=1pt,
        label=center:{\sffamily\bfseries#4}] (#5) {};
}

\begin{document}

\begin{tikzpicture}[node distance=5pt,outer sep=0pt,
block/.style={
  line width=1pt,
  draw=black,
  fill=myorange,
  rounded corners,
  text width=#1,
  font={\sffamily\bfseries},
  align=center,
  text height=12pt,
  text depth=9pt
},
block/.default=1.5cm
]
\node[block=3cm] (a) {AAA};
\node[block=4.5cm,right=of a] (b) {BBB};
\node[block,right=of b] (c) {CCC};
\widernode[block]{a}{c}{DDD}{d}
\end{tikzpicture}

\end{document}

enter image description here

share|improve this answer
    
I did't try Jake's code. Instead, with the settings you give on matrix and fit, I have achieved stacked components with nice alignment. Could you briefly explain what text height and text depth? Why there is no text width? Thanks. –  Causality Jul 20 '13 at 0:16
    
@Causality of mismatching baselines is caused by the fact that the nodes have different heights and depth. Had they all the same, they would all be positioned vertically in the same manner. This is precisely what text height and text depth do: they select an specific fixed height and depth for the nodes. There's no text width in my first code since you used minimum width and I used that setting. –  Gonzalo Medina Jul 20 '13 at 0:27

The code from the linked answer below is included in the positioning-plus library which is used in the second example for more than what the linked answer provides.


The alignment problem has two reasons:

  1. The matrix of nodes style sets the anchor of every node in the matrix to base (which is usually what you want).
  2. The empty cells are empty and thus the baseline of the empty text box is at the same height as the center of the node and thus will be aligned a little bit lower.

This can be reverted by using the center anchor again, though this will fail if all node texts do not have the same height and depth (something similar will happen if one of the node’s text is wider than <minimum width> - 2 <inner xsep>). For normal one-lined text you can fix this with a \strut in every node, applied by the font key.

For the multi-columns and multi-rows I actually would set nodes in empty cells to false and use a not-drawn node (so that it can used later as a reference but is not seen). Instead of fit, I’d use my span key from another answer of mine to TikZ: Make node height span several others. The span style only sets the correct minimum widths and minimum heights, the location must been set with at (fit bounding box), a pseude-node created by the span key. As it doesn’t change text depth or text height the vertical position of the text is not changed.

Code

\documentclass[tikz,convert=false]{standalone}
\usepackage{lmodern}
\usetikzlibrary{matrix, positioning-plus}
\tikzset{
  block/.style={
    rectangle,
    draw,
    minimum height=4em,
    minimum width=4em,
    outer sep=0pt,
%    anchor=center,
    font=\strut},
  empty cells are empty/.style={
    execute at empty cell={\node[draw=none,fill=none]{};},
    nodes in empty cells=false
  },
  overlapping lines in matrices/.style={
    row sep=-\pgflinewidth,
    column sep=-\pgflinewidth}
}
\begin{document}
\begin{tikzpicture}
    \matrix (table) [%
      matrix of nodes,
      ampersand replacement=\&,
      nodes=block,
      overlapping lines in matrices,
      empty cells are empty
    ] {%
      A \& B \& C \& D \\
      e \&   \&   \& G \\
      H \& I \& J \&   \\
      K \& L \& M \&   \\
   };
    \node[block, span=(table-2-2)(table-2-3)] at (fit bounding box) {F};
    \node[block, span=(table-3-4)(table-4-4)] at (fit bounding box) {N};
\end{tikzpicture}
\end{document}

Output

enter image description here


For your other diagram, I again advise against fit and a manual adjustment with xshift and yshift. It would be better to use the positioning library with its node distance key (<vertical distance> and <horizontal distance> is the syntax).

For the first code example, the nodes b, c and d are placed in a horizontal fashion with right=of <previous node> (the chains library can help with the creation of many nodes). The positioning keys are again improved with the code from the linked answer above, so that you can use below=of -(b)(d) which means that the new node will be created below b and d and with a minimal width such that it spans both nodes horizontally.

The second example places first the a node and then the nodes b and d are placed above of a but west- and east-aligned, thus the keys are west above and east above. These keys are provided by my positioning-plus library.
Much as above sets the own anchor to south while the referenced node’s anchor is set to north, west above sets the own anchor to north west and the referenced node’s anchor to south west. An overview of the positioning keys can be seen in another answer of mine.

The fourth node c is then simply placed between the borders of b and d. This does not check the minimum widths for validity nor does it use the horizontal node distance.

Code

\documentclass[tikz,convert=false]{standalone}
\usepackage{lmodern}
\usetikzlibrary{positioning-plus}
\tikzset{
  node distance=+2mm and +2mm,
  every node/.style={
    rectangle,
    rounded corners=1mm,
    very thick,
    draw,
    fill=orange!50
  }
}
\begin{document}
\begin{tikzpicture}% Code A
  \node[minimum width=+.3\textwidth]  (b) {B};
  \node[minimum width=+.07\textwidth, right=of b] (c) {C};
  \node[minimum width=+.2\textwidth, right=of c] (d) {D};
  \node[below=of -(b)(d)] (a) {AAAA};
\end{tikzpicture}
\begin{tikzpicture}% Code B
  \node[minimum width=.6\textwidth] (a) {AAAA};
  \node[minimum width=+.3\textwidth, west above=of a] (b) {B};
  % or: \node[minimum width=+.3\textwidth, above=of a.north west, anchor=south west] (b) {B};
  \node[minimum width=+.2\textwidth, east above=of a] (d) {D};
  % or: \node[minimum width=+.2\textwidth, above=of a.north east, anchor=south east] (d) {D};
  \path (b) -- node[minimum width=+.07\textwidth] (c) {C} (d);% places the node (c) in the
                                                              % middle between (b) and (d)
\end{tikzpicture}
\end{document}

Output

Output A

enter image description here

Output B

enter image description here

share|improve this answer
    
You can have another fix for-one-liner nodes via nodes={...} in the matrix without any hassle with struts –  percusse Jul 20 '13 at 1:31
    
If I understand, west above=of a (form positioning-plus) is equivalent to above=of a.north west,anchor=south west... –  Paul Gaborit Jul 20 '13 at 8:04
    
@PaulGaborit Correct. –  Qrrbrbirlbel Jul 20 '13 at 15:45
    
@Qrrbrbirlbel This is a rather detailed answer and a complete reference for similar problems. This could be my ultimate choice, though Gonzalo Medina's answer give me a quick way to solve the problem ("in may original way"). –  Causality Jul 22 '13 at 22:24

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.