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.

I am new here to Tikz and I need to draw 2 rows of nodes that are identical in size but having different text of different length in it. Sure the upper and lower nodes should have enough room for the longest of the two texts. The upper nodes should be aligned to the lower ones and have the same size.

To be specific, I need to draw the following picture using Tikz:

enter image description here

share|improve this question
1  
Welcome to TeX.SX! Please provide a MWE showing some code illustrating your problem. A MWE begins with \documentclass{...}, the required \usepackage's, \begin{document}, and \end{document}. That may seem not easy for you, but think of the extra work it represents for TeX.SX users willing to give you a hand. Help them help you. –  AboAmmar Aug 7 at 0:16
1  
Please see my updated answer for a solution without hard-coded widths; LaTeX does all the calculations. –  Gonzalo Medina Aug 7 at 1:50

4 Answers 4

up vote 6 down vote accepted

A possible TikZ free solution with automatic width calculation and allowing multi-line texts (a TikZ solution is below):

enter image description here

The command \EightTexts has eight mandatory arguments and LaTeX performs all necessary calculations using simple conditional tests on the length of the corresponding strings. The code in the image was produced using

\EightTexts{Small}{Medium}{Large}{Larger}{AA}{Even larger}{B}{The largest}

\vskip1cm

\EightTexts{AAAA}{B}{CCCCC}{DD}{EEEEEEEEE}{FFFFF}{GG}{HHHHHHHH}

The complete code:

\documentclass{article}
\usepackage{varwidth}

\newlength\mylenai
\newlength\mylenbi
\newlength\mylenMaxi
\newlength\mylenaii
\newlength\mylenbii
\newlength\mylenMaxii
\newlength\mylenaiii
\newlength\mylenbiii
\newlength\mylenMaxiii
\newlength\mylenaiv
\newlength\mylenbiv
\newlength\mylenMaxiv

\newsavebox\myboxi
\newsavebox\myboxii
\newsavebox\myboxiii
\newsavebox\myboxiv
\newsavebox\myboxv
\newsavebox\myboxvi
\newsavebox\myboxvii
\newsavebox\myboxviii

\newcommand\TikZEightTexts[8]{%
% Save the texts in boxes so we can measure their widths. 
\savebox\myboxi{\begin{varwidth}{\textwidth}#1\end{varwidth}}
\savebox\myboxii{\begin{varwidth}{\textwidth}#2\end{varwidth}}
\savebox\myboxiii{\begin{varwidth}{\textwidth}#3\end{varwidth}}
\savebox\myboxiv{\begin{varwidth}{\textwidth}#4\end{varwidth}}
\savebox\myboxv{\begin{varwidth}{\textwidth}#5\end{varwidth}}
\savebox\myboxvi{\begin{varwidth}{\textwidth}#6\end{varwidth}}
\savebox\myboxvii{\begin{varwidth}{\textwidth}#7\end{varwidth}}
\savebox\myboxviii{\begin{varwidth}{\textwidth}#8\end{varwidth}}
% Choose maximum width between width of first box and fifth box
% store the maximum in `\mylenMaxi`
\setlength\mylenMaxi{\the\wd\myboxi}%
\setlength\mylenai{\the\wd\myboxi}%
\setlength\mylenbi{\the\wd\myboxv}%
\ifdim\mylenbi>\mylenai\relax
  \setlength\mylenMaxi{\mylenbi}
\fi
% Choose maximum width between the width of second box and the 
% width of sixth box; store the maximum in `\mylenMaxii`
\setlength\mylenMaxii{\the\wd\myboxii}%
\setlength\mylenaii{\the\wd\myboxii}%
\setlength\mylenbii{\the\wd\myboxvi}%
\ifdim\mylenbii>\mylenaii\relax
  \setlength\mylenMaxii{\mylenbii}
\fi
% Choose maximum width between the width of third box and the 
% width of seventh box; store the maximum in `\mylenMaxiii`
\setlength\mylenMaxiii{\the\wd\myboxiii}%
\setlength\mylenaiii{\the\wd\myboxiii}%
\setlength\mylenbiii{\the\wd\myboxvii}%
\ifdim\mylenbiii>\mylenaiii\relax
  \setlength\mylenMaxiii{\mylenbiii}
\fi
% Choose maximum width between the width of fourth box and the 
% width of eighth box; store the maximum in `\mylenMaxiv`
\setlength\mylenMaxiv{\the\wd\myboxiv}%
\setlength\mylenaiv{\the\wd\myboxiv}%
\setlength\mylenbiv{\the\wd\myboxviii}%
\ifdim\mylenbiv>\mylenaiv\relax
  \setlength\mylenMaxiv{\mylenbiv}
\fi
\noindent
\fbox{\parbox[c][1.2cm][c]{\mylenMaxi}{\centering#1}}\hfill
\fbox{\parbox[c][1.2cm][c]{\mylenMaxii}{\centering#2}}\hfill
\fbox{\parbox[c][1.2cm][c]{\mylenMaxiii}{\centering#3}}\hfill
\fbox{\parbox[c][1.2cm][c]{\mylenMaxiv}{\centering#4}}%
\bigskip\par\noindent
\fbox{\parbox[c][1.2cm][c]{\mylenMaxi}{\centering#5}}\hfill
\fbox{\parbox[c][1.2cm][c]{\mylenMaxii}{\centering#6}}\hfill
\fbox{\parbox[c][1.2cm][c]{\mylenMaxiii}{\centering#7}}\hfill
\fbox{\parbox[c][1.2cm][c]{\mylenMaxiv}{\centering#8}}\par
}

\begin{document}

\TikZEightTexts{Small}{Medium}{Large}{Larger}{AA}{Even larger}{B}{The 3 lines\\largest solution\\ever}

\vskip1cm

\TikZEightTexts{AAAA \\ AAAAAAAA \\ AAA}{B}{CCCCC}{DD}{EEEEEEE}{FFFFF}{GG \\ GGG }{HH \\ HH}

\end{document}

A solution using TikZ has been required in comments; here it is:

\documentclass{article}
\usepackage{varwidth}
\usepackage{tikz}
\usetikzlibrary{positioning}

\newlength\mylenai
\newlength\mylenbi
\newlength\mylenMaxi
\newlength\mylenaii
\newlength\mylenbii
\newlength\mylenMaxii
\newlength\mylenaiii
\newlength\mylenbiii
\newlength\mylenMaxiii
\newlength\mylenaiv
\newlength\mylenbiv
\newlength\mylenMaxiv

\newsavebox\myboxi
\newsavebox\myboxii
\newsavebox\myboxiii
\newsavebox\myboxiv
\newsavebox\myboxv
\newsavebox\myboxvi
\newsavebox\myboxvii
\newsavebox\myboxviii

\newcommand\TikZEightTexts[8]{%
% Save the texts in boxes so we can measure their widths. 
\savebox\myboxi{\begin{varwidth}{\textwidth}#1\end{varwidth}}
\savebox\myboxii{\begin{varwidth}{\textwidth}#2\end{varwidth}}
\savebox\myboxiii{\begin{varwidth}{\textwidth}#3\end{varwidth}}
\savebox\myboxiv{\begin{varwidth}{\textwidth}#4\end{varwidth}}
\savebox\myboxv{\begin{varwidth}{\textwidth}#5\end{varwidth}}
\savebox\myboxvi{\begin{varwidth}{\textwidth}#6\end{varwidth}}
\savebox\myboxvii{\begin{varwidth}{\textwidth}#7\end{varwidth}}
\savebox\myboxviii{\begin{varwidth}{\textwidth}#8\end{varwidth}}
% Choose maximum width between width of first box and fifth box
% store the maximum in `\mylenMaxi`
\setlength\mylenMaxi{\the\wd\myboxi}%
\setlength\mylenai{\the\wd\myboxi}%
\setlength\mylenbi{\the\wd\myboxv}%
\ifdim\mylenbi>\mylenai\relax
  \setlength\mylenMaxi{\mylenbi}
\fi
% Choose maximum width between the width of second box and the 
% width of sixth box; store the maximum in `\mylenMaxii`
\setlength\mylenMaxii{\the\wd\myboxii}%
\setlength\mylenaii{\the\wd\myboxii}%
\setlength\mylenbii{\the\wd\myboxvi}%
\ifdim\mylenbii>\mylenaii\relax
  \setlength\mylenMaxii{\mylenbii}
\fi
% Choose maximum width between the width of third box and the 
% width of seventh box; store the maximum in `\mylenMaxiii`
\setlength\mylenMaxiii{\the\wd\myboxiii}%
\setlength\mylenaiii{\the\wd\myboxiii}%
\setlength\mylenbiii{\the\wd\myboxvii}%
\ifdim\mylenbiii>\mylenaiii\relax
  \setlength\mylenMaxiii{\mylenbiii}
\fi
% Choose maximum width between the width of fourth box and the 
% width of eighth box; store the maximum in `\mylenMaxiv`
\setlength\mylenMaxiv{\the\wd\myboxiv}%
\setlength\mylenaiv{\the\wd\myboxiv}%
\setlength\mylenbiv{\the\wd\myboxviii}%
\ifdim\mylenbiv>\mylenaiv\relax
  \setlength\mylenMaxiv{\mylenbiv}
\fi
\noindent
\begin{tikzpicture}[every node/.append style={
draw,minimum height=1.3cm,align=center}
]
\node[text width=\mylenMaxi] (11) {#1};
\node[text width=\mylenMaxii,right= of 11] (12) {#2};
\node[text width=\mylenMaxiii,right= of 12] (13) {#3};
\node[text width=\mylenMaxiv,right= of 13] (14) {#4};
\node[text width=\mylenMaxi,below=of 11] (21) {#5};
\node[text width=\mylenMaxii,right= of 21] (22) {#6};
\node[text width=\mylenMaxiii,right= of 22] (23) {#7};
\node[text width=\mylenMaxiv,right= of 23] (24) {#8};
\end{tikzpicture}%
}

\begin{document}

\TikZEightTexts{Small}{Medium}{Large}{Larger}{AA}{Even larger}{B}{The 3 lines\\largest solution\\ever}

\vskip1cm

\TikZEightTexts{AAAA \\ AAAAAAAA \\ AAA}{B}{CCCCC}{DD}{EEEEEEE}{FFFFF}{GG \\ GGG }{HH \\ HH}

\end{document}

enter image description here

share|improve this answer
    
Thank you Medina, but here you have made all boxes of the same size. Besides, in your first solution you don't know the width in advance. –  Power_Project Aug 7 at 1:28
1  
@Power_Project Ah, I think I know what you want. Please see my updated answer. No need to do anything. LaTeX can do all the measurements for you :) –  Gonzalo Medina Aug 7 at 1:45
    
Thank you for this great and very helpful solution. Please do not remove it but I need to perform this within Tikz because this is part of a larger picture that is written in a \tikzpicture environment. I will be thankful if you can add the tikz approach. –  Power_Project Aug 7 at 1:55
1  
@Power_Project TikZ approach added :) –  Gonzalo Medina Aug 7 at 2:01
1  
@Power_Project You're welcome. The code is fairly easy once you know how it works: looking at this bit: \settowidth\mylenMaxi{#1}% \settowidth\mylenai{#1}% \settowidth\mylenbi{#5}% \ifdim\mylenbi>\mylenai\relax \setlength\mylenMaxi{\mylenbi} \fi the idea is to compare the widths og the first and fifth strings; initially the max width is set to be the one of the first string and then a conditional test is used; if the width of the fifth string is bigger thatn the one of the first string, the max is updated to be the one of the fifth string. –  Gonzalo Medina Aug 7 at 2:35

You can use a tikz matrix which simplifies the placement, and creation of node markers, and then \draw the boxes after:

enter image description here

Code:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc,matrix}

% http://tex.stackexchange.com/questions/33703/extract-x-y-coordinate-of-an-arbitrary-point-in-tikz
\newdimen\XCoordA
\newdimen\XCoordB
\newdimen\YCoordA
\newdimen\YCoordB
\newcommand{\ExtractMinX}[3]{%
    % #1 = csname to hold min x value
    % #2 = coordinate 1
    % #3 = coordinate 2
    \path (#2); \pgfgetlastxy{\XCoordA}{\YCoordA};%
    \path (#3); \pgfgetlastxy{\XCoordB}{\YCoordB};%
    \ifdim\XCoordA<\XCoordB
        \edef#1{\XCoordA}%
    \else
        \edef#1{\XCoordB}%
    \fi
}%
\newcommand{\ExtractMaxX}[3]{%
    % #1 = csname to hold max x value
    % #2 = coordinate 1
    % #3 = coordinate 2
    \path (#2); \pgfgetlastxy{\XCoordA}{\YCoordA};%
    \path (#3); \pgfgetlastxy{\XCoordB}{\YCoordB};%
    \ifdim\XCoordA>\XCoordB
        \edef#1{\XCoordA}%
    \else
        \edef#1{\XCoordB}%
    \fi
}%

\tikzset{My Matrix Node Style/.style={every node/.style={draw=none, minimum height=5ex, anchor=base, row sep=15.0ex, column sep=5.0em}}}


\begin{document}
\begin{tikzpicture}
\pgfsetmatrixcolumnsep{2.0em}
\matrix (M) [matrix of nodes, My Matrix Node Style] {
    Small & Medium & Larger Text & Even Larger Text \\[2.0ex]
    Even larger text & Larger Text & Medium & Small \\
};
% Now draw the boxes based on the min and max x value for each column
\foreach \x in {1,...,4} {% for each column
    \ExtractMinX{\MinX}{M-1-\x.south west}{M-2-\x.south west}%
    \ExtractMaxX{\MaxX}{M-1-\x.north east}{M-2-\x.north east}%
    \foreach \y in {1,...,2} {% for each row
        \coordinate (Left Bottom) at (\MinX,\YCoordA |- M-\y-\x.south west);
        \coordinate (Right Top) at   (\MaxX,\YCoordB |- M-\y-\x.north east);
        \draw [red, rounded corners=3pt, thick]
            (Left Bottom) rectangle (Right Top);
    }
}
\end{tikzpicture}
\end{document}
share|improve this answer

This simple thing needs no tikz:

\documentclass{article}
\usepackage{calc}
\newlength\mylen

\settowidth\mylen{Even larger text}

\newcommand{\row}[4]{%
\fbox{\makebox[\mylen][c]{\rule[-0.55ex]{0ex}{1.2em}#1}}%
\hfill
\fbox{\makebox[\mylen][c]{\rule[-0.55ex]{0ex}{1.2em}#2}}%
\hfill
\fbox{\makebox[\mylen][c]{\rule[-0.55ex]{0ex}{1.2em}#3}}%
\hfill
\fbox{\makebox[\mylen][c]{\rule[-0.55ex]{0ex}{1.2em}#4}}%
}

\begin{document}

\noindent
\row{Small}{Medium}{Larger text}{Even larger text}

\vspace{1cm}
\noindent
\row{Even larger text}{Larger text}{Medium}{Small}

\end{document}

enter image description here

share|improve this answer
    
Thank you Kumar, but you have fixed the width of the box at first. What I need is a stretchable box which can accommodate for the longer text. –  Power_Project Aug 7 at 1:24

So, probably you need to use the \phantom{} command. Here is a MWE but I am sure you will get the idea:

\documentclass[border=0.125cm,tikz]{standalone}
\usetikzlibrary{positioning,calc}
\begin{document}
\begin{tikzpicture}[blk/.style={rounded corners, minimum height=.7cm,draw,align=center},node distance=2cm,line width=1pt]

\node (a) [blk] at (0,0){\phantom{small no 2}\\Small\\ \phantom{small no 2}};
\node (b) [blk,below=of a] {\phantom{Small}\\small no 2\\ \phantom{Small;/}};
\node (c) [blk,right=of a] at (0,0){\phantom{short}\\very long text\\ \phantom{short}};
\node (d) [blk,below=of c] {\phantom{very long text}\\short\\ \phantom{very long text}};

\end{tikzpicture}
\end{document}

The out as you need is:

enter image description here

share|improve this answer
    
Simplest and smartest!! But I have learned a lot from the above solutions. Thanks @AboAmmar. –  Power_Project Oct 25 at 23:22

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.