crash course to tikz [1 · basics]

TikZ is a powerful graphics package for $\LaTeX$—arguably the most popular, well documented, and well supported. Many people around me have expressed interest in drawing their technical diagrams with TikZ. Unfortunately, most are turned away by the combination of three factors.

  1. There are few tutorials that don’t read like a user manual.
  2. The actual user manual is a heaping 1300+ pages long.
  3. Many tutorials are tailored towards an (introductory) mathematics community, who are more likely to draw parabolas than neural network diagrams or Petersen graphs.

This guide is a first to many of my limited answers to this dilemma.

Disclaimer

  1. My goal is to teach you how to draw TikZ diagrams as fast as possible, so I will omit encyclopedic details in favor of simplicity.
  2. I try to make examples self-contained and minimally viable, so I will forgo concision for clarity.
  3. This content is biased towards my personal usage patterns.

By the end of this tutorial, you should be able to recreate a basic diagram, like this single attention head.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
\begin{tikzpicture}[scale=0.8,
    every node/.append style={thick,rounded corners=2pt}]
    \node (q) at (.5,0) {Q};
    \node (k) at (1.5,0) {K};
    \node (v) at (2.5,0) {V};

    \node[draw,fill=blue!20] (matmul1) at (1,1) {MatMul};
    \node[draw,fill=yellow!40] (scale) at (1,2) {Scale};
    \node[draw,fill=red!20] (mask) at (1,3) {Mask};
    \node[draw,fill=green!20] (softmax) at (1,4) {Softmax};
    \node[draw, fill=blue!20, minimum width=1.75cm] (matmul2) at (1.75,5) {MatMul};

    \path[->,thick]
        (matmul1) edge (scale)
        (scale) edge (mask)
        (mask) edge (softmax)
        (q) edge (.5,.7)
        (k) edge (1.5,.7)
        (v) edge (2.5,4.7)
        (softmax) edge (1,4.7);
\end{tikzpicture}

The TeX source for this post may be found here.

Basics

All TikZ pictures are drawn within a tikzpicture environment. Within this environment, items are drawn onto an underlying Cartesian plane. In this tutorial, I will refer to this plane as the document grid. Many diagrams can be expressed as a graph, with vertices connected by edges.

1
2
3
4
5
6
7
8
9
10
11
12
\begin{tikzpicture}[
    every node/.append style={draw, minimum height=0.6cm}]
    \node (ideate_name) at (0,0) {ideate};
    \node (model_name) at (2,0) {model};
    \node (test_name) at (4,0) {test};

    \path[->]
        (ideate_name) edge (model_name)
        (model_name) edge (test_name)
        (test_name) edge[bend right=50] (ideate_name)
        (test_name) edge (5,0);
\end{tikzpicture}

We will refer to vertices as nodes and the edges connecting them as paths. With this terminology, let us break down the construction of this drawing.

  • There are three nodes in this drawing, corresponding to “ideate,” “model,” and “test.” Each node is placed within the document grid at a fixed position, which may be absolute or relative. Here, the nodes are placed at the absolute positions of $(0,0),(2,0),(4,0)$. We will discuss relative positioning at a later time.
  • Each node is required to have a label, which may be empty. The label is displayed in your drawing. Each node may also have a name, which is an internal reference for the node. While strictly optional, naming nodes is highly recommended so you can reference them later, whether to position other nodes or to draw paths between nodes.
  • With that in mind, we can connect nodes. There are two ways to do this, \draw and \path. These commands differ in subtle ways, and I personally find that the syntax for \path is safer from beginner bugs.

    Paths are decently self-explanatory: you can draw an edge between any two points (nodes or coordinates) in the document grid, where each edge is a standalone path. Unless otherwise specified, edges point toward the center of each node.

    Finally, observe that one of the edges curves around. Options bend right or bend left allows you to bend edges around obstacles.

Styles

Now that we have the basics down, we can make our nodes and edges look a little less barebones. Each node and path can take a set of options that specify its style and position. In this section we’ll focus on style.

Nodes

In the previous drawing, you may have noticed these options that I passed to the tikzpicture environment:

every node/.append style={draw, minimum height=0.6cm}

The draw option specifies that we should draw a stroke along each node’s boundary. You can disable this via draw=none or simply by omitting the draw option.

Here are some other styles you can explore.

1
2
3
4
5
6
7
8
9
10
\begin{tikzpicture}[
    every node/.append style={draw, minimum size=0.5cm}]
    \node[ultra thin] at (0,0) {};
    \node[very thin] at (1,0) {};
    \node[thin] at (2,0) {};
    \node[semithick] at (3,0) {};
    \node[thick] at (4,0) {};
    \node[very thick] at (5,0) {};
    \node[ultra thick] at (6,0) {};
\end{tikzpicture}

The thickness of your line is specified by line width. This can be set to any numerical unit. You may also use predefined thicknesses, which range from ultra thin (far left) to ultra thick (far right). The default line width is thin.

1
2
3
4
5
6
7
8
9
\begin{tikzpicture}[
    every node/.append style={draw, minimum size=0.5cm}]
    \node at (0,0) {};
    \node[dashed] at (1,0) {};
    \node[dashdotted] at (2,0) {};
    \node[dotted] at (3,0) {};
    \node[loosely dotted] at (5,0) {};
    \node[densely dotted] at (6,0) {};
\end{tikzpicture}

You can specify the dash pattern of each node. There are three built-in variants: dashed, dashdotted, and dotted. These can be modified with loosely or densely.

1
2
3
4
5
6
7
8
9
\begin{tikzpicture}[
    every node/.append style={minimum size=0.5cm}]
    \node[draw=blue] at (0,0) {};
    \node[fill=blue] at (1,0) {};
    \node[fill=blue!50!cyan] at (2,0) {};
    \node[fill=cyan] at (3,0) {};
    \node[fill=cyan!50] at (4,0) {};
    \node[draw=cyan,text=cyan] at (5,0) {hi};
\end{tikzpicture}

You can specify the color of each node’s stroke, fill, and label. This reference has a list of default colors, available in any system, as well as colors available through the xcolor library. While it’s possible to define your own colors, it’s often easier to blend between existing colors with the syntax color1 ! percentage color1 ! color2 If you do not specify a second color, the default is white.

1
2
3
4
5
6
\begin{tikzpicture}[
    every node/.append style={draw}]
    \node at (0,0) {default};
    \node[rectangle] at (2,0) {rectangle};
    \node[circle] at (4,0) {circle};
\end{tikzpicture}

There are three built-in shapes: rectangle, circle, and coordinate. We can ignore coordinates for now. By default, each node is a rectangle. For more shapes you may load the shapes library.

1
2
3
4
5
6
7
8
9
\begin{tikzpicture}[
    every node/.append style={draw}]
    \node[minimum width=0.75cm] at (0,0) {};
    \node[minimum height=0.75cm] at (1,0) {};
    \node[minimum size=0.75cm] at (2,0) {};
    \node[circle] at (4,0) {\footnotesize s};
    \node[circle] at (5,0) {\large M};
    \node[circle] at (6.25,0) {\huge L};
\end{tikzpicture}

Finally, you might want to control the size of your nodes. By default, nodes will always resize to fit their labels, so vanilla TikZ only allows you to set the minimum size of a node. However, you may tweak the inner sep of a node to adjust the amount of padding between the text and the node boundary.

1
2
3
4
5
6
7
8
9
10
\begin{tikzpicture}[
    every node/.append style={draw,thick,text=cyan}]
    \node[inner sep=-2pt] at (0,0) {Hi};
    \node[inner sep=0pt] at (1,0) {Hi};
    \node at (2,0) {Hi};
    \node[inner sep=8pt] at (3.25,0) {Hi};

    \node[inner xsep=8pt] at (5.5,0) {Hi};
    \node[inner ysep=8pt] at (7,0) {Hi};
\end{tikzpicture}

This padding may take on a negative value, and as usual, you can specify different x and y values.

Paths

Many of the styles that apply to nodes also apply to paths, including line width, dash pattern, and color.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
\begin{tikzpicture}
    \path[ultra thin] (0,2) edge (0,2.5);
    \path[very thin] (1,2) edge (1,2.5);
    \path[thin] (2,2) edge (2,2.5);
    \path[semithick] (3,2) edge (3,2.5);
    \path[thick] (4,2) edge (4,2.5);
    \path[very thick] (5,2) edge (5,2.5);
    \path[ultra thick] (6,2) edge (6,2.5);

    \path (0,1) edge (0,1.5);
    \path[dashed] (1,1) edge (1,1.5);
    \path[dashdotted] (2,1) edge (2,1.5);
    \path[dotted] (3,1) edge (3,1.5);
    \path[loosely dotted] (5,1) edge (5,1.5);
    \path[densely dotted] (6,1) edge (6,1.5);

    \path (0,0) edge (0,0.5);
    \path[gray] (1,0) edge (1,0.5);
    \path[blue] (2,0) edge (2,0.5);
    \path[violet] (3,0) edge (3,0.5);
    \path[magenta] (4,0) edge (4,0.5);
    \path[purple] (5,0) edge (5,0.5);
    \path[red] (6,0) edge (6,0.5);
\end{tikzpicture}

Now you might be thinking—the similarities end here, because paths can’t be circles—but actually, they can. To avoid confusion, however, we won’t discuss such paths in this tutorial. Instead, we’ll close off with some shapes that are relevant to paths: arrow tips.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
\begin{tikzpicture}
    \path (0,1) edge (0,1.5);
    \path[->] (1,1) edge (1,1.5);
    \path[<-] (2,1) edge (2,1.5);
    \path[<->] (3,1) edge (3,1.5);
    \path[<<->>] (4,1) edge (4,1.5);
    \path[<<<->>>] (5,1) edge (5,1.5);
    \path[-to] (6,1) edge (6,1.5);

    \path[stealth-stealth] (0,0) edge (0,0.5);
    \path[stealth reversed-stealth reversed] (1,0) edge (1,0.5);
    \path[to-to] (2,0) edge (2,0.5);
    \path[to reversed-to reversed] (3,0) edge (3,0.5);
    \path[latex-latex] (4,0) edge (4,0.5);
    \path[latex reversed-latex reversed] (5,0) edge (5,0.5);
    \path[|-|] (6,0) edge (6,0.5);
\end{tikzpicture}

The general arrow tip syntax is start - end where start and end may be empty. The default arrow tip specified by > is the same as to, similar to the math mode command, $\to$. For more creative arrow tips, you may load the arrows library.

Conclusion

If you’ve followed up to here, you already have the ability to draw a wide range of diagrams—congrats!

At this point, I would recommend that you take out your $\LaTeX$ compiler and go draw some diagrams yourself. There will always be more syntax to be memorized, so there’s no hurry; now is the time to get your hands wet. Out into the TikZ world you go!

Acknowledgements

Thanks to Evan Chen and Tony Zhang for introducing me to $\LaTeX$ + TikZ when I was a baby freshman at MIT. Thanks to Yujia Bao for reading through my draft for this post.