40

My question is almost opposite to: this question.

I have defined a block:

\begin{tikzpicture}[node distance = 2cm, auto,->=stealth,point/.style= 
                   {circle,fill=red,minimum size=0pt,inner sep=0pt}]
\tikzstyle{block} = [rectangle, draw,thick,fill=blue!0,
    text centered, rounded corners, minimum height=1em]
\node [block] (start) {Start};
\node [block,below of=start] (start) {Start and blah blah blah blah blah blah
                       blah blah blah blah blah blah blah blah blah
                       blah blah blah blah blah blah blah blah blah
                       blah blah blah blah blah blah blah blah blah};
\end{tikzpicture}

The block adjusts itself to accommodate text.

enter image description here

But I would like to control the width of the block by using text width=15em:

\tikzstyle{block} = [rectangle, draw,thick,fill=blue!0,text width=20em,<---------= 
             text centered, rounded corners, minimum height=1em]

I get this:

enter image description here

Though the second block looks good, the first block (start) has lot of empty space in it. My question is

How to adjust the width of the block according to the text and at the same time limiting the maximum width of the block to (say) 15em?

In other words, How to make the first block to fit with start? Or generally speaking,

How to adjust the block size automatically to fit the text with maximum width of block as 15em?

Pl. note: I am aware that I can define block2 with a suitable width and put start in it. But my constraint is to use the single tikzstyle.

3 Answers3

32

I guess there is no TikZ way, but you can use the varwidth package:

\documentclass{article}

\usepackage{tikz}
\usepackage{varwidth}

\begin{document}
\begin{tikzpicture}[node distance = 2cm, auto,->=stealth,point/.style= 
                   {circle,fill=red,minimum size=0pt,inner sep=0pt}]
\tikzstyle{block} = [rectangle, draw,thick,fill=blue!0,
    text centered, rounded corners, minimum height=1em]
\node [block] (start) {\begin{varwidth}{15em}Start\end{varwidth}};
\node [block,below of=start] (start) {%
   \begin{varwidth}{15em}
      Start and blah blah blah blah blah blah
      blah blah blah blah blah blah blah blah blah
      blah blah blah blah blah blah blah blah blah
      blah blah blah blah blah blah blah blah blah
    \end{varwidth}};
\end{tikzpicture}
\end{document}

result

You may wrap the {varwidth} environment in a shorter macro …

Update

It is possible to use execute at begin/end node to include {varwidth} in the sytle definition:

\begin{tikzpicture}[node distance = 2cm, auto,->=stealth]
\tikzstyle{block} = [%
   rectangle, draw,thick,fill=blue!0,
   text centered, rounded corners, minimum height=1em,
   execute at begin node={\begin{varwidth}{15em}},
   execute at end node={\end{varwidth}}]
\node [block] (start) {%
      Start
};
\node [block,below of=start] (start) {%
      Start and blah blah blah blah blah blah
      blah blah blah blah blah blah blah blah blah
      blah blah blah blah blah blah blah blah blah
      blah blah blah blah blah blah blah blah blah
};
\end{tikzpicture}
Tobi
  • 56,353
  • 1
    Thanks. It works. But isn't there a command opposite to minimum width in tikz? –  Mar 02 '12 at 23:12
  • @HarishKumar: I didn’t found something like that in pgfmanual.pdf – Tobi Mar 03 '12 at 00:04
  • May be somebody knowing these things well can dig into the definition of minimum width and change it appropriately for maximum width? –  Mar 03 '12 at 00:09
  • 1
    @HarishKumar: I guess it’s not yet implemented because minimum width only requires to make a box of the given width but maximum width needs an additional calculation to check wether the text is longer than the maximum or not … but I know TikZ not well enough to look at the source and see what’s the thing … – Tobi Mar 03 '12 at 00:28
  • Is it possible to align text using varwidth to the right side? See the code of this question, the command called \You. It has a tikzpicture inside it, also it has a style where the node has align=right, but this cannot prevent from text being aligned to the left. The varwidth documentation does not have enough information. I want it aligned to the right. Thank you! – manooooh Feb 24 '20 at 20:23
  • 1
    Have you tried a \rafgedleft in the varwidth env? – Tobi Feb 24 '20 at 22:17
  • Thanks for the comment!! You have solved the issue. – manooooh Feb 24 '20 at 23:05
9

I just wanted to augment Tobi's answer regarding execute at begin/end node, and put that part into an own style with an argument for the width.

\tikzset{
    max width/.style args={#1}{
        execute at begin node={\begin{varwidth}{#1}},
        execute at end node={\end{varwidth}}
    }
}
\begin{tikzpicture}
    \node[max width=3cm] {this node is maximum 3cm wide although its text is wider};
    \node[max width=10cm] {shrinks to textwidth};
\end{tikzpicture}

Dont forget to load the varwidth package beforehand: \usepackage{varwidth}

dexteritas
  • 9,161
daniatic
  • 288
0

Here is my implementation of a maximum text width key based on the answer by daniatic. The following image and the MWE shows how it interacts with text width and minimum width, and how multiple chained style definitions can override it.

Feel free to suggest improvements. For example, currently the width of multi-line nodes is quasi random because it uses the natural width of the longest line without stretching. I would like to make all nodes longer than one line have exactly the same width, like text width.

Output of the example code

Example code:

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

\makeatletter \newif\iftikz@maximum@text@width@hook@installed \tikz@maximum@text@width@hook@installedfalse% \let\tikz@text@width@backup\pgfutil@empty% \let\tikz@maximum@text@width@value\pgfutil@empty% \pgfkeys{% /tikz/maximum text width/.code={% \def\tikz@maximum@text@width@value{#1}% \ifx\tikz@maximum@text@width@value\pgfutil@empty% 'maximum text width={}' should restore previous value for 'text width' \ifx\tikz@text@width\pgfutil@empty% but only of 'text width' has not been set in the meantime \let\tikz@text@width\tikz@text@width@backup% restore saved 'text width' value \fi \else% maximum text width=<dimension> wil install the varwidth environment code for all nodes \iftikz@maximum@text@width@hook@installed\else \ifx\tikz@text@width@backup\pgfutil@empty \let\tikz@text@width@backup\tikz@text@width \fi \pgfkeysalso{ execute at begin node={% \ifx\tikz@maximum@text@width@value\pgfutil@empty\else% Don't use varwidth if 'maximum text width' is empty \ifx\tikz@text@width\pgfutil@empty% Don't use varwidth if 'text width' has a value \begin{varwidth}{\tikz@maximum@text@width@value}% \leavevmode\begingroup% Prevent Package varwidth Warning: Failed to reprocess entire contents on input line \fi% \fi% },% execute at end node={% \ifx\tikz@maximum@text@width@value\pgfutil@empty\else% Don't use varwidth if 'maximum text width' is empty \ifx\tikz@text@width\pgfutil@empty% Don't use varwidth if 'text width' has a value \endgroup\end{varwidth}% \fi% \fi% },% }% \tikz@maximum@text@width@hook@installedtrue% \fi% \pgfkeysalso{/tikz/text width={}}% 'text width' overrides 'maximum text width' if specified, so we unset it (the value was saved above) \fi }, } \makeatother

\begin{document} \begin{tikzpicture}[ y=-1cm, font=\scriptsize, every node/.style={text width=6cm, draw=red, inner xsep=0}, my style/.style={draw=blue, minimum width=2cm, maximum text width=4cm}, ] \path[very thin, draw=black!10!white] (-5,-1) grid (5,7); \node at (0,0) {\verb|every node| has \verb|text width=5cm|}; % 'maximum text width' overrides 'text width' \node[my style] at (0,1) {custom node style with \verb|maximum text width=4cm|. Note that it is narrower than 4 cm due to line splitting}; \node[my style] at (0,2) {min width}; \node[my style] at (0,3) {single line $>$ min width}; \node[my style, maximum text width=4cm] at (0,4) {multiple \verb|maximum text width| assignments do not add nested \verb|varwidth| environments}; % Setting maximum text width to an empty value restores 'text width' \node[my style, maximum text width={}] at (0,5) {same style, but setting \verb|maximum text width={}| falls back to previous \verb|text width| value}; \node[my style, text width=8cm] at (0,6) {same style, but setting \verb|text width=8cm| overrides and disables \verb|maximum text width|}; \end{tikzpicture} \end{document}

Fritz
  • 6,273
  • 31
  • 55