4

I want to have 2 texts in a TikZ node where the upper text has a drawn border and the lower has not, and both texts should be wrapped at a certain length. Furthermore, the border of the upper text should always be as wide as the surrounding node. I can’t get the last part done without obtaining the width of the lower text and setting it as the minimum width of the upper text. Is there a better way to do this?

example

\documentclass{minimal}

\usepackage{tikz}
\usepackage{varwidth}
\usetikzlibrary{positioning,fit,matrix}
\usepackage{calc}

\begin{document}
\newlength{\somelength}
\settowidth{\somelength}{Technically this works.}

\begin{tikzpicture}[mymatrix/.style = {matrix of nodes, nodes=mynode},
    mynode/.style = {rectangle,draw, rounded corners=1pt,anchor=west},
    title/.style = {draw=none, anchor=west}]
  \matrix[mymatrix] (mx1) {
    Hello there, this is fine. \\
    |[title]| Hello\\
  };

  \node[mynode, fit=(mx1)]{};

  \matrix[mymatrix,,below=of mx1.south west,anchor=north west] (mx2) {
    Hello there. \\
    |[title]| This is not how it is supposed to be.\\
  };

  \node[mynode, fit=(mx2)]{};

  \matrix[mymatrix,below=of mx2.south west,anchor=north west] (mx3) {
    \begin{varwidth}{195pt}
     Hello there. This is a longer text and this is also fine.
    \end{varwidth}\\
    |[title]| \begin{varwidth}{200pt} Hello, this works also exactly how it should work.\end{varwidth}\\
  };

  \node[mynode, fit=(mx3)]{};

  \matrix[mymatrix,below=of mx3.south west,anchor=north west] (mx4) {
    |[mynode,minimum width=\the\somelength]| \begin{varwidth}{195pt}
     Hello there.
     \end{varwidth}\\
    |[title]| \begin{varwidth}{200pt}  Technically this works.
     \end{varwidth}\\
  };

  \node[mynode, fit=(mx4)]{};
\end{tikzpicture}
\end{document}
0
4

Something like this?

\documentclass[tikz,border=3.14mm]{standalone}
\usetikzlibrary{calc,fit,positioning}
\begin{document}
\begin{tikzpicture}
\node (lower) {Some text here};
\path let \p1=(lower.west),\p2=(lower.east) in 
node[draw,minimum width=\x2-\x1,above=1mm of lower] (more) {more text};
\node[fit=(lower) (more),draw]{}; 
\end{tikzpicture}
\end{document}

enter image description here

One can of course make this a macro that deals with most cases (but not with all, I admit).

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc,fit,positioning}
\newcommand{\DrawNestedNodes}[2]{%
\node[align=left] (lower) {#2};
\path let \p1=($(lower.east)-(lower.west)$) in
\pgfextra{\pgfmathsetmacro{\mywidth}{width("#1")-\x1}} 
\ifdim\mywidth pt<0pt  
node[draw,text width=\x1-8pt,above=1mm of lower.north west,anchor=south
west,align=left] (more) {#1}
\else
node[draw,minimum width=\x1-8pt,above=1mm of lower.north west,anchor=south
west,align=left] (more) {#1}
\fi;
\node[fit=(lower) (more),draw]{}; 
}
\tikzset{every node/.append style={align=left}}
\begin{document}
\section*{Case 1: one--liners}
\subsection*{Case 1a: lower text wider than upper}
\begin{tikzpicture}
\DrawNestedNodes{some text}{more text here}
\end{tikzpicture}
\subsection*{Case 1b: upper text wider than lower}
\begin{tikzpicture}
\DrawNestedNodes{some long text here}{more text}
\end{tikzpicture}
\section*{Case 2: multi--liners}
\subsection*{Case 2a: lower text wider than upper}
\begin{tikzpicture}
\DrawNestedNodes{some text}{more text here running\\ over two lines}
\end{tikzpicture}
\subsection*{Case 2b: upper text wider than lower}
\begin{tikzpicture}
\DrawNestedNodes{some long text}{more text\\ running over\\ three lines}
\end{tikzpicture}
\end{document}

enter image description here

EDIT: Added screen shot.

3

Another solution based in original matrix code. External border is matrix border without using any fit node. And node length is computed with width operation. In order to avoid double writting of first line, the matrix style is defined with two arguments (top and bootom lines) which are added to node contents parameter. The use of node contents forces that matrix names must be placed before matrix options.

\documentclass[tikz, border=2mm]{standalone}

\usepackage{tikz}
%\usepackage{varwidth}
\usetikzlibrary{positioning,matrix,calc}
%\usepackage{calc}

\begin{document}

\begin{tikzpicture}[%
    mymatrix/.style 2 args = {%
        matrix of nodes, 
        rounded corners=1pt,
        draw, 
        inner sep=3mm,
        nodes={
            inner sep=.333em,
            align=left,
            text width = {width("#1")},
        },
        row 1/.style={nodes={draw}},
        node contents={#1\\#2\\}
    },
    ]

    \matrix (mx1) [mymatrix={Hello there, this is fine.}{Hello}] ;

    \matrix (mx2) [mymatrix={Hello there}{This is not how it is supposed to be}, below right = 5mm and 0pt of mx1.south west] ;

    \matrix (mx3) [mymatrix={Hello there. This is a longer text and this is also fine.}{Hello, this works also exactly how it should work.}, below right = 5mm and 0pt of mx2.south west] ;

\matrix (mx4) [mymatrix={Hello there.}{Technically this works.}, below right = 5mm and 0pt of mx3.south west] ;
\end{tikzpicture}
\end{document}

enter image description here

1
  • I intended it, so that the lower text only wraps if it is longer than 200pt not if it is longer than the upper text (as marmot understood it). Thanks anyway, I hope, I was not unclear in my description.
    – n314159
    Jul 29 '18 at 18:59
2

i understand you question differently as marmot:

enter image description here

is this what you looking for?

\documentclass[tikz,varwidth, margin=3mm]{standalone}
\usetikzlibrary{fit, positioning}

\begin{document}
\begin{tikzpicture}[
node distance = 6mm,
   box/.style = {draw, text width=77mm, align=left},
   tit/.style = {text width=77mm, align=left},
     F/.style = {draw, inner sep= 3mm, node contents={}}
                        ]
\node (n1a) [box]                   {Hello there, this is fine};
\node (n1b) [tit, below=0pt of n1a] {Hello};
\node (n1)  [F, fit=(n1a) (n1b)];
%
\node (n2a) [box, below=of n1]  {Hello there.};
\node (n2b) [tit, below=0pt of n2a]     {This is not how it is supposed to be.};
\node (n2)  [F, fit=(n2a) (n2b)];
%
\node (n3a) [box, below=of n2]  {Hello there. This is a longer text and this is also fine.};
\node (n3b) [tit, below=0pt of n3a]     {Hello, this works also exactly how it should work.};
\node (n3)  [F, fit=(n3a) (n3b)];
%
\node (n4a) [box, below=of n3]  {Hello there.};
\node (n4b) [tit, below=0pt of n4a]     {Technically this works.};
\node (n3)  [F, fit=(n4a) (n4b)];
   \end{tikzpicture}
\end{document}
2
  • @marmot,oh no .. i was interupted with visit and forgot on the my answer :-(
    – Zarko
    Jul 29 '18 at 16:16
  • I meant it as marmot understood it, but thanks nevertheless. Sorry if my description was unclear.
    – n314159
    Jul 29 '18 at 18:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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