TikZ is a flexible and powerful tool for creating detailed diagrams directly in LaTeX documents. Whether you’re working with simple shapes or complex scientific illustrations, TikZ offers a precise and customisable approach to producing high-quality, reproducible graphics. In this post, we’ll explore its features, provide examples, and share tips to help you get the best out of this versatile package.
Why TikZ?
Before diving into the details, let’s explore some good reasons to use TikZ:
Setting Up TikZ in Your LaTeX Environment
To use TikZ, you need to load it in the LaTeX preamble. Most LaTeX distributions (e.g., TeX Live, MiKTeX, Overleaf) include TikZ by default. Add this line to your preamble:
\usepackage{tikz}
TikZ also supports optional libraries that extend its functionality. For example:
\usetikzlibrary{arrows.meta, positioning, shapes.geometric}
TikZ Basics: Drawing Your First Diagrams
TikZ diagrams are created inside a tikzpicture
environment. Within this environment, you can define shapes, lines, colors, and more. You need to add arrows.meta
, positioning
and shapes.geometric
libraries (\usetikzlibrary{arrows.meta, positioning, shapes.geometric}
) to use the examples below.
Example 1: Simple Shapes
This example draws a square, a circle, and a triangle:
\documentclass{article}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
% Draw a square
\draw[thick, line width=1.5pt] (0,0) rectangle (2,2); % (x1, y1) to (x2, y2)
% Draw a circle
\draw[red, thick, line width=1.5pt] (4,1) circle (1cm); % (center) circle (radius)
% Draw a triangle
\draw[blue, thick, line width=1.5pt] (6,0) -- (7,2) -- (8,0) -- cycle; % (x1, y1) -- (x2, y2) -- (x3, y3)
\end{tikzpicture}
\end{document}
Example 2: Adding Labels and Colors
TikZ lets you label shapes and fill them with colors to make diagrams more descriptive:
\begin{tikzpicture}
% Rectangle with label
\draw[draw=orange, fill=cyan!20, line width=1.5pt] (0,0) rectangle (4,2)
node[pos=.5] {\Large Rectangle};
% Circle with label
\draw[draw=orange, fill=magenta!30, line width=1.5pt] (6,1) circle (1cm)
node {\Large Circle};
\end{tikzpicture}
Example 3: Connecting Shapes with Arrows
Create flowcharts and process diagrams using arrows and nodes:
\begin{tikzpicture}[node distance=2cm] % Set node distance
% Define nodes
\node[rectangle, draw=orange, fill=cyan!20, line width=1.5pt] (start) {Start}; % Node name: start
\node[rectangle, draw=blue, fill=blue!20, line width=1.5pt, right of=start] (step1) {Step 1}; % Node name: step1
\node[circle, draw=gray, fill=gray!20, line width=1.5pt, right of=step1] (step2) {Step 2}; % Node name: step2
% Connect nodes with arrows
\draw[->] (start) -- (step1);
\draw[->] (step1) -- (step2);
\end{tikzpicture}
You can customise the relative positioning of nodes:
\begin{tikzpicture}
% Define nodes
\node[rectangle, draw=orange, fill=cyan!20, line width=1.5pt] (start) {Start}; % Node name: start
\node[rectangle, draw=blue, fill=blue!20, line width=1.5pt, right=1cm of start] (step1) {Step 1}; % Node name: step1
\node[circle, draw=gray, fill=gray!20, line width=1.5pt, right=2cm of step1] (step2) {Step 2}; % Node name: step2
% Connect nodes with arrows
\draw[->, line width=1.2pt] (start) -- (step1);
\draw[->, line width=1.2pt] (step1) -- (step2);
\end{tikzpicture}
You can customise the nodes dimensions:
\begin{tikzpicture}
% Define nodes
\node[rectangle, draw=orange, fill=cyan!20, line width=1pt, minimum width=2cm, minimum height=1cm] (start) {\large Start}; % Node name: start
\node[rectangle, draw=blue, fill=blue!20, line width=1.5pt, right=1cm of start, minimum width=2.5cm, minimum height=1.5cm] (step1) {\Large Step 1}; % Node name: step1
\node[circle, draw=gray, fill=gray!20, line width=2.5pt, right=2cm of step1, minimum width=3cm, minimum height=2cm] (step2) {\Huge Step 2}; % Node name: step2
% Connect nodes with arrows
\draw[->, line width=1.2pt] (start) -- (step1);
\draw[->, line width=1.2pt] (step1) -- (step2);
\end{tikzpicture}
You can set the text maximum width, to break the text in multiple lines:
\begin{tikzpicture}
% Define nodes
\node[rectangle, draw=orange, fill=cyan!20, line width=1pt, minimum width=2cm, minimum height=1cm] (start) {\large Start}; % Node name: start
\node[rectangle, draw=blue, fill=blue!20, line width=1.5pt, right=1cm of start, minimum width=2.5cm, minimum height=1.5cm] (step1) {\Large Step 1}; % Node name: step1
\node[circle, draw=gray, fill=gray!20, line width=2.5pt, right=2cm of step1, minimum width=3cm, minimum height=2cm, text width=4cm] (step2) {\Huge Step 2 additional text}; % Node name: step2
% Connect nodes with arrows
\draw[->, line width=1.2pt] (start) -- (step1);
\draw[->, line width=1.2pt] (step1) -- (step2);
\end{tikzpicture}
Tip: There are too many options to customise the nodes, you can check the TikZ documentation for more information. In order to well organise these options you can create node styles:
\begin{tikzpicture}
% Define node styles
\tikzset{
% <styleName>/.style={<styleOptions>}
mynode/.style={
rectangle, draw=orange, fill=cyan!20, line width=1.5pt, minimum width=2cm, minimum height=1cm
},
myarrow/.style={
->, line width=1.2pt
}
}
% Define nodes
\node[mynode] (start) {\large Start};
\node[mynode, draw=blue, right=1cm of start] (step1) {\Large Step 1};
\node[mynode, circle, fill=gray!20, text width=4cm, right=2cm of step1] (step2) {\Huge Step 2 additional text};
% Connect nodes with arrows
\draw[myarrow] (start) -- (step1);
\draw[myarrow] (step1) -- (step2);
\end{tikzpicture}
Using the node styles you can easily change the nodes appearance by changing the style options.
With all these you can already create very complex diagrams, for example:
\begin{tikzpicture}
% Define node styles
\tikzset{
mynode/.style={
rectangle, draw=orange, fill=cyan!20, line width=1.5pt, minimum width=2cm, minimum height=1cm
},
decision/.style={
diamond, draw=purple, fill=yellow!20, line width=1.5pt, minimum width=2.5cm, minimum height=1.5cm
},
myarrow/.style={
->, line width=1.2pt
},
note/.style={
draw=none, fill=none, align=center, font=\footnotesize
}
}
% Define nodes
\node[mynode] (start) {\large Start};
\node[mynode, draw=blue, right=2cm of start] (process1) {\Large Process 1};
\node[mynode, fill=gray!20, below right=2cm and 1cm of process1] (process2) {\Large Process 2};
\node[decision, below=2cm of process1] (decision) {\Large Decision?};
\node[mynode, fill=green!20, below left=2cm and 1cm of decision] (yes) {\Large Yes: Task 1};
\node[mynode, fill=red!20, below right=2cm and 1cm of decision] (no) {\Large No: Task 2};
\node[mynode, fill=orange!30, below=3cm of decision] (end) {\Large End};
% Connect nodes with arrows
\draw[myarrow] (start) -- (process1);
\draw[myarrow] (process1) -- (decision);
\draw[myarrow] (decision) -- node[above left, note] {\large Yes} (yes);
\draw[myarrow] (decision) -- node[above right, note] {\large No} (no);
\draw[myarrow] (yes) -- (end);
\draw[myarrow] (no) -- (end);
\draw[myarrow, bend left] (process2) to (process1); % "bend" for curved arrow. you can set the bending angle: bend left=45
% Add annotations
\node[note, below=0.5cm of process2] {\large Iterative step back to \\ Process 1};
\node[note, above=0.5cm of start] {\large Begin the process};
\node[note, below=0.5cm of end] {\large Workflow completion};
\end{tikzpicture}
TikZ code can get complex quickly. Always start with positioning simple style nodes (this is the hardest part) and then add arrows to connect them (the easiest part). After that you can add more complex options.
PGFPlots: High-Quality Plots with TikZ
pgfplots
is a package built on top of TikZ that allows you to create plots directly within LaTeX. It provides a wide range of plot types, styles, and customisation options.
Example: Plotting a Function
Here’s a simple example of plotting a function using pgfplots
:
\begin{tikzpicture}
\begin{axis}[
xlabel={$x$}, ylabel={$f(x)$},
grid, grid style={dashed, gray!30},
width=10cm,
height=6cm,
]
% Plot sin(x)
\addplot[domain=-2*pi:2*pi, samples=100, thick, blue, dashed] {sin(deg(x))};
% Plot cos(x)
\addplot[domain=-2*pi:2*pi, samples=100, thick, red] {cos(deg(x))};
\end{axis}
\end{tikzpicture}
Example: 3D plot
\begin{tikzpicture}
\begin{axis}[
axis lines=middle,
xlabel={$x$}, ylabel={$y$}, zlabel={$z$},
width=10cm, height=6cm,
]
\addplot3[surf, domain=-2:2, domain y=-1:1] {sin(deg(sqrt(x^2 + y^2)))};
\end{axis}
\end{tikzpicture}
Example: Plot from Data File
You can also plot data from a table file:
\begin{tikzpicture}
\begin{axis}[
xlabel={$x$}, ylabel={$f(x)$},
width=10cm, height=6cm,
]
\addplot table[x=x, y=y, col sep=comma] {data.csv};
\end{axis}
\end{tikzpicture}
Advanced TikZ Features
Creating Graphs and Trees
TikZ is excellent for creating graph structures and trees:
\begin{tikzpicture}
% Define styles
\tikzset{
vertex/.style={
circle, draw=blue!60, fill=blue!20, thick, minimum size=1.2cm, line width=1.5pt
},
edge/.style={->,
draw=gray!60, thick, line width=1.5pt
},
highlight/.style={->,
draw=orange!80, thick, line width=1.5pt
}
}
% Define nodes
\node[vertex] (A) at (0,0) {\textbf{\large A}};
\node[vertex] (B) at (2,2) {\textbf{\large B}};
\node[vertex] (C) at (4,0) {\textbf{\large C}};
\node[vertex] (D) at (6,2) {\textbf{\large D}};
\node[vertex] (E) at (8,0) {\textbf{\large E}};
\node[vertex, draw=orange, fill=gray!30] (F) at (4,-2) {\large \textbf{F}};
% Define edges
\draw[edge] (A) -- (B);
\draw[edge] (A) -- (C);
\draw[edge] (B) -- (C);
\draw[edge] (B) -- (D);
\draw[edge] (D) -- (B);
\draw[edge] (C) -- (D);
\draw[highlight] (C) -- (F);
\draw[edge] (D) -- (E);
\draw[highlight, bend left] (E) to (F);
\draw[highlight, bend left] (F) to (A);
% Add labels for edges
\node[font=\footnotesize, above left=0.2cm of A] {\large Start Node};
\node[font=\footnotesize, above=0.2cm of D] {\large Intermediate Node};
\node[font=\footnotesize, below=0.2cm of F] {\large Highlighted Node};
\end{tikzpicture}
Here the vertex ‘F’ is positioned using coordinates, but you can also use relative positioning to place it below ‘C’. Personnally, I prefer the relative positioning because it easier, but in some cases if you change the position of a node, you will need to change the position of all the nodes that are relative to it.
3D Diagrams
TikZ also supports 3D perspectives. Here’s an example of a cube:
\begin{tikzpicture}
% draw a path passing through the points
\draw[thick, line width=1.5pt] (0,0,0) -- (2,0,0) -- (2,2,0) -- (0,2,0) -- cycle; % cycle means go back to the first point
\draw[thick, line width=1.5pt] (0,0,0) -- (0,0,2);
\draw[thick, line width=1.5pt] (2,0,0) -- (2,0,2);
\draw[thick, line width=1.5pt] (2,2,0) -- (2,2,2);
\draw[thick, line width=1.5pt] (0,2,0) -- (0,2,2);
\draw[thick, line width=1.5pt] (0,0,2) -- (2,0,2) -- (2,2,2) -- (0,2,2) -- cycle;
\end{tikzpicture}
Tip: Another example, here instead of setting the coordinates of the points manually, we use variables to simplify the positioning, you may need to add the calc
library (\usetikzlibrary{calc}
) to use this feature:
\begin{tikzpicture}[scale=1] % scale the whole picture
% Define styles
\tikzset{
cube/.style={
draw, thick, fill=gray!20, opacity=0.7, line width=1.5, draw=orange, fill=orange!30
},
arrow3D/.style={
thick, ->, >=stealth, draw=gray, line width=1.5
}
}
% Define position variables
\def\cubeOneOrigin{(0,0,0)}
\def\cubeTwoOrigin{(4,0,0)}
\def\cubeSize{2}
% Draw the first cube
\draw[cube,fill=orange!10] \cubeOneOrigin -- ++(\cubeSize,0,0) -- ++(0,\cubeSize,0) -- ++(-\cubeSize,0,0) -- cycle; % front face
\draw[cube] \cubeOneOrigin -- ++(0,0,\cubeSize) -- ++(\cubeSize,0,0) -- ++(0,0,-\cubeSize) -- cycle; % bottom face
\draw[cube] \cubeOneOrigin -- ++(0,\cubeSize,0) -- ++(0,0,\cubeSize) -- ++(0,-\cubeSize,0) -- cycle; % left face
% Label the first cube
\node at (1, 1, 0) {\large \textbf{Cube 1}};
% Draw the second cube
\draw[cube,fill=orange!10] \cubeTwoOrigin -- ++(\cubeSize,0,0) -- ++(0,\cubeSize,0) -- ++(-\cubeSize,0,0) -- cycle; % front face
\draw[cube] \cubeTwoOrigin -- ++(0,0,\cubeSize) -- ++(\cubeSize,0,0) -- ++(0,0,-\cubeSize) -- cycle; % bottom face
\draw[cube] \cubeTwoOrigin -- ++(0,\cubeSize,0) -- ++(0,0,\cubeSize) -- ++(0,-\cubeSize,0) -- cycle; % left face
% Label the second cube
\node at (5, 1, 0) {\large \textbf{Cube 2}};
% Draw an arrow bellow the cubes
\draw[arrow3D, bend left] (4.7, -0.4) to (0.6, -0.4);
\end{tikzpicture}
The ++
operator is used to specify relative coordinates. For example, \cubeOneOrigin -- ++(1,0,0)
means “start from the origin of the cube and move 1 unit along the x-axis”. This is a convenient way to define points, thus we can change the position of the cubes with minimal effort.
Tip: Efficient TikZ Usage Externalise Graphics: Large diagrams can slow LaTeX compilation. TikZ’s external
library allows you to compile graphics separately:
\usetikzlibrary{external}
\tikzexternalize[prefix=tikz/] % 'tikz/' is the directory where the externalised graphics will be stored (should be created before and be non-empty)
Spy Feature for Zooming
You can create plots and figures with zooming features using the spy
library (\usetikzlibrary{spy}
):
\begin{tikzpicture}[spy using outlines={circle, magnification=6, size=2cm, connect spies}]
\begin{axis}[
width=10cm, height=6cm,
xlabel={$x$}, ylabel={$f(x)$},
grid, grid style={dashed, gray!30},
enlargelimits=false
]
\addplot[domain=0.1:1, samples=100, thick, teal, solid] {1/x};
\addplot[domain=0.1:1, samples=100, thick, orange, solid] {1/(x^2)};
\begin{scope}
\coordinate (A) at (axis cs:0.75,1);
\spy on (A) in node[fill=white] at (3,3);
\end{scope}
\end{axis}
\end{tikzpicture}
Poster Design
TikZ can be used to create posters and banners. Some details are provided in this Overleaf tutorial.
Bonus: Because you came this far, here is a cool package to include emojis in your latex documents (e.g. beamer presentations):
\usepackage{emoji}
% Usage
\emoji{smile}
% inside itemize
\begin{itemize}
\item[\emoji{smile}] Item 1
\item[\emoji{heart}] Item 2
\end{itemize}
You can find more emojis in the emoji package documentation.
⚠️ emoji
package is not compatible with old LaTeX compilers such as pdflatex
, you need to use lualatex
. For Overleaf users, you can change the compiler in the settings.
Keep it clean and efficient!