Getting Started
Document Creation
Working with Content
Creating Diagrams with TikZ
Master TikZ for creating professional diagrams in LaTeX. Learn drawing commands, libraries, flowcharts, graphs, and advanced visualization techniques.
Create publication-quality diagrams directly in LaTeX using TikZ. This comprehensive guide covers basic shapes to complex technical illustrations, including flowcharts, graphs, circuits, and scientific diagrams.
Prerequisites: Basic LaTeX knowledge
Time to complete: 40-45 minutes
Difficulty: Intermediate to Advanced
What you’ll learn: TikZ syntax, libraries, drawing techniques, and practical examples
Introduction to TikZ
What is TikZ?
TikZ (TikZ ist kein Zeichenprogramm - TikZ is not a drawing program) is a powerful package for creating graphics programmatically in LaTeX. It provides:
Precise Control
Exact positioning and measurements
Consistency
Matching document fonts and styles
Programmable
Loops, variables, and calculations
Integration
Seamless LaTeX integration
Basic Setup
\documentclass{article}
\usepackage{tikz}
% Load common libraries
\usetikzlibrary{
arrows.meta, % Arrow styles
positioning, % Relative positioning
shapes.geometric, % Additional shapes
calc, % Coordinate calculations
patterns, % Fill patterns
decorations.pathmorphing, % Path decorations
backgrounds, % Background layers
fit, % Fitting nodes
chains, % Chain positioning
shadows % Drop shadows
}
\begin{document}
% Inline TikZ
\begin{tikzpicture}
\draw (0,0) -- (2,1);
\end{tikzpicture}
% Centered figure
\begin{figure}[htbp]
\centering
\begin{tikzpicture}
% Drawing commands here
\end{tikzpicture}
\caption{TikZ diagram}
\end{figure}
\end{document}
Basic Drawing
Coordinates and Paths
\begin{tikzpicture}[scale=1.5]
% Cartesian coordinates
\draw[->] (-0.5,0) -- (4,0) node[right] {$x$};
\draw[->] (0,-0.5) -- (0,3) node[above] {$y$};
% Points
\fill (1,1) circle (2pt) node[below] {$(1,1)$};
\fill (3,2) circle (2pt) node[right] {$(3,2)$};
% Path with multiple segments
\draw[thick, blue] (0,0) -- (1,1) -- (2,0.5) -- (3,2);
% Curved path
\draw[thick, red] (0,2) .. controls (1,3) and (2,1) .. (3,2.5);
% Closed path
\draw[thick, green, fill=green!20]
(0.5,0.5) -- (1.5,0.5) -- (1,1.5) -- cycle;
% Polar coordinates
\draw[purple] (0,0) -- (45:2) node[midway, above] {$(45:2)$};
% Relative coordinates
\draw[orange, thick] (2,1) -- ++(1,0.5) -- ++(0.5,-0.5);
\end{tikzpicture}
Nodes and Labels
\begin{tikzpicture}[
every node/.style={font=\sffamily},
main node/.style={circle, draw, minimum size=1cm}
]
% Basic nodes
\node (A) at (0,0) {Simple text};
\node[draw] (B) at (3,0) {Boxed text};
\node[circle, draw] (C) at (6,0) {Circle};
% Styled nodes
\node[main node, fill=blue!20] (D) at (0,2) {D};
\node[rectangle, draw, rounded corners, fill=red!20] (E) at (3,2) {Rect};
\node[ellipse, draw, fill=green!20] (F) at (6,2) {Ellipse};
% Node connections
\draw[->] (A) -- (B);
\draw[->] (B) -- (C);
\draw[<->, thick] (D) -- (E);
\draw[->, dashed] (E) -- (F);
% Labels on edges
\draw[->] (D) -- (A) node[midway, left] {edge};
\draw[->] (F) -- (C) node[near start, right] {label};
\end{tikzpicture}
Flowcharts and Diagrams
Basic Flowcharts
\begin{tikzpicture}[
node distance=2cm,
startstop/.style={rectangle, rounded corners, draw, fill=red!30, minimum width=3cm, minimum height=1cm},
process/.style={rectangle, draw, fill=blue!30, minimum width=3cm, minimum height=1cm},
decision/.style={diamond, draw, fill=green!30, minimum width=3cm, minimum height=1cm, aspect=2},
io/.style={trapezium, trapezium left angle=70, trapezium right angle=110, draw, fill=yellow!30, minimum width=3cm, minimum height=1cm},
arrow/.style={thick, ->, >=stealth}
]
% Nodes
\node[startstop] (start) {Start};
\node[io, below=of start] (input) {Input data};
\node[process, below=of input] (process1) {Process data};
\node[decision, below=of process1] (decision) {Valid?};
\node[process, below=of decision] (process2) {Generate output};
\node[startstop, below=of process2] (stop) {End};
% Alternative path
\node[process, right=3cm of decision] (error) {Handle error};
% Connections
\draw[arrow] (start) -- (input);
\draw[arrow] (input) -- (process1);
\draw[arrow] (process1) -- (decision);
\draw[arrow] (decision) -- node[left] {Yes} (process2);
\draw[arrow] (decision) -- node[above] {No} (error);
\draw[arrow] (error) |- (input);
\draw[arrow] (process2) -- (stop);
\end{tikzpicture}
State Diagrams
\begin{tikzpicture}[
>=stealth,
node distance=3cm,
state/.style={circle, draw, minimum size=1.5cm, font=\small},
initial/.style={state, fill=green!30},
final/.style={state, double, fill=red!30},
transition/.style={->, thick}
]
% States
\node[initial] (idle) {Idle};
\node[state, right=of idle] (loading) {Loading};
\node[state, right=of loading] (active) {Active};
\node[state, below=of active] (error) {Error};
\node[final, below=of idle] (terminated) {Done};
% Transitions
\draw[transition] (idle) -- node[above] {start} (loading);
\draw[transition] (loading) -- node[above] {success} (active);
\draw[transition] (loading) -- node[right] {fail} (error);
\draw[transition] (active) -- node[right] {complete} (terminated);
\draw[transition] (error) -- node[below] {retry} (loading);
\draw[transition] (error) -- node[left] {abort} (terminated);
\draw[transition, bend left=30] (active) to node[above] {reset} (idle);
% Self loop
\draw[transition] (active) to[loop above] node {update} (active);
\end{tikzpicture}
Graphs and Trees
Graph Structures
\begin{tikzpicture}[
node distance=2cm,
vertex/.style={circle, draw, fill=blue!20, minimum size=8mm},
edge/.style={thick}
]
% Vertices
\node[vertex] (A) {A};
\node[vertex, right=of A] (B) {B};
\node[vertex, below right=of A] (C) {C};
\node[vertex, below left=of A] (D) {D};
\node[vertex, below=of C] (E) {E};
% Edges
\draw[edge] (A) -- (B);
\draw[edge] (A) -- (C);
\draw[edge] (A) -- (D);
\draw[edge] (B) -- (C);
\draw[edge] (C) -- (D);
\draw[edge] (C) -- (E);
\draw[edge] (D) -- (E);
% Edge labels
\draw[edge] (B) -- node[above right] {5} (E);
\end{tikzpicture}
Tree Structures
\begin{tikzpicture}[
level distance=1.5cm,
level 1/.style={sibling distance=4cm},
level 2/.style={sibling distance=2cm},
level 3/.style={sibling distance=1cm},
treenode/.style={circle, draw, fill=green!30, minimum size=8mm},
edge from parent/.style={draw, ->, >=stealth}
]
% Binary tree
\node[treenode] {8}
child {
node[treenode] {3}
child {
node[treenode] {1}
}
child {
node[treenode] {6}
child {
node[treenode] {4}
}
child {
node[treenode] {7}
}
}
}
child {
node[treenode] {10}
child[missing] {}
child {
node[treenode] {14}
child {
node[treenode] {13}
}
child[missing] {}
}
};
\end{tikzpicture}
Scientific Diagrams
Mathematical Diagrams
\begin{tikzpicture}[scale=1.5]
% Axes
\draw[->] (-0.5,0) -- (4,0) node[right] {$x$};
\draw[->] (0,-0.5) -- (0,3) node[above] {$y$};
% Grid
\draw[gray, very thin] (0,0) grid (3.5,2.5);
% Function plots
\draw[blue, thick, domain=0:3.5, samples=100]
plot (\x, {0.5*\x*\x - \x + 1});
\draw[red, thick, domain=0:3.5, samples=100]
plot (\x, {sin(\x r) + 1});
\draw[green, thick, domain=0.1:3.5, samples=100]
plot (\x, {ln(\x) + 1});
% Labels
\node[blue] at (3,2.2) {$f(x) = \frac{1}{2}x^2 - x + 1$};
\node[red] at (2,0.3) {$g(x) = \sin(x) + 1$};
\node[green] at (3.2,1.3) {$h(x) = \ln(x) + 1$};
% Points of interest
\fill[blue] (2,1) circle (2pt) node[above right] {$(2,1)$};
\end{tikzpicture}
Physics Diagrams
\begin{tikzpicture}[
force/.style={->, thick, blue},
mass/.style={rectangle, draw, fill=gray!30, minimum width=1.5cm, minimum height=1.5cm}
]
% Free body diagram
\node[mass] (m) {$m$};
% Forces
\draw[force] (m.north) -- ++(0,2) node[above] {$N$};
\draw[force] (m.south) -- ++(0,-2) node[below] {$mg$};
\draw[force] (m.east) -- ++(1.5,0) node[right] {$F$};
\draw[force] (m.west) -- ++(-1,0) node[left] {$f$};
% Surface
\draw[thick] (-3,-0.75) -- (3,-0.75);
\foreach \x in {-3,-2.5,...,3} {
\draw (\x,-0.75) -- (\x-0.25,-1);
}
% Angle for inclined plane
\begin{scope}[xshift=6cm]
\draw[thick] (0,0) -- (4,0) -- (4,2) -- cycle;
\node[mass, rotate=26.57] at (2.5,1.25) {$m$};
\draw[force] (2.5,1.25) -- ++(0,-2) node[below] {$mg$};
\draw[force, rotate=26.57] (2.5,1.25) -- ++(0,1.5) node[above] {$N$};
\node at (0.5,0.15) {$\theta$};
\end{scope}
\end{tikzpicture}
Advanced Techniques
Loops and Automation
\begin{tikzpicture}
% Grid of nodes using foreach
\foreach \x in {0,1,2,3,4} {
\foreach \y in {0,1,2,3} {
\node[circle, draw, fill=blue!\x0!green!\y0]
at (\x,\y) {\tiny \x,\y};
}
}
% Radial pattern
\begin{scope}[xshift=7cm, yshift=2cm]
\foreach \angle in {0,30,...,330} {
\draw[thick, color=red!\angle!blue]
(0,0) -- (\angle:2);
\fill[color=red!\angle!blue]
(\angle:2) circle (2pt);
}
\end{scope}
% Connected graph
\begin{scope}[yshift=-5cm]
\foreach \i in {1,...,6} {
\node[circle, draw, fill=orange!30]
(n\i) at ({360/6 * (\i-1)}:2) {\i};
}
\foreach \i in {1,...,6} {
\foreach \j in {\i,...,6} {
\draw[gray] (n\i) -- (n\j);
}
}
\end{scope}
\end{tikzpicture}
Styles and Scopes
\begin{tikzpicture}[
% Define custom styles
my node/.style={
circle,
draw=#1,
fill=#1!20,
minimum size=1cm,
font=\bfseries
},
my edge/.style={
thick,
->,
>=stealth,
#1
},
important/.style={
my node=red,
drop shadow
},
normal/.style={
my node=blue
}
]
% Use custom styles
\node[important] (A) at (0,0) {A};
\node[normal] (B) at (3,0) {B};
\node[normal] (C) at (3,3) {C};
\node[important] (D) at (0,3) {D};
% Styled edges
\draw[my edge={red, dashed}] (A) -- (B);
\draw[my edge={blue}] (B) -- (C);
\draw[my edge={green, bend left}] (C) -- (D);
\draw[my edge={orange, bend right}] (D) -- (A);
% Scope with different settings
\begin{scope}[xshift=6cm, scale=0.8, opacity=0.7]
\node[my node=purple] (E) at (0,0) {E};
\node[my node=cyan] (F) at (2,2) {F};
\draw[my edge={thick}] (E) -- (F);
\end{scope}
\end{tikzpicture}
Decorations and Patterns
\begin{tikzpicture}[
decoration={
snake,
amplitude=.5mm,
segment length=3mm
}
]
% Different decorations
\draw[decorate, thick] (0,0) -- (3,0) node[right] {snake};
\draw[
decoration={coil, segment length=4mm},
decorate, thick
] (0,1) -- (3,1) node[right] {coil};
\draw[
decoration={zigzag, segment length=4mm},
decorate, thick
] (0,2) -- (3,2) node[right] {zigzag};
\draw[
decoration={random steps, segment length=3mm},
decorate, thick
] (0,3) -- (3,3) node[right] {random};
% Text along path
\draw[
decoration={
text along path,
text={This text follows the curve!}
},
decorate
] (5,0) .. controls (6,2) and (7,2) .. (8,0);
% Arrow decorations
\draw[
thick,
decoration={
markings,
mark=at position 0.25 with {\arrow{>}},
mark=at position 0.5 with {\arrow{>}},
mark=at position 0.75 with {\arrow{>}}
},
postaction={decorate}
] (5,3) circle (1);
\end{tikzpicture}
Best Practices
Optimization Tips
TikZ best practices:
- Use styles - Define reusable styles for consistency
- Name nodes - Makes connections easier
- Use calculations - Let TikZ compute positions
- Layer wisely - Background, main, foreground
- Externalize - Compile complex diagrams separately
- Comment code - Especially for complex diagrams
- Use libraries - Don’t reinvent the wheel
- Test incrementally - Build diagrams step by step
Common Pitfalls
Avoid these TikZ mistakes:
- Hardcoded positions - Use relative positioning
- Repeated code - Use loops and styles
- Complex paths - Break into smaller parts
- Missing libraries - Load required libraries
- Scale issues - Test at final size
- Memory problems - Externalize large diagrams
- Forgotten semicolons - Every command needs one
Complete Examples
Network Diagram
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning, shapes.geometric, shadows, backgrounds}
\begin{document}
\begin{tikzpicture}[
node distance=2cm,
server/.style={
rectangle, draw, fill=blue!20,
minimum width=2cm, minimum height=1.5cm,
drop shadow, font=\small
},
client/.style={
rectangle, draw, fill=green!20,
minimum width=1.5cm, minimum height=1cm,
drop shadow, font=\small
},
database/.style={
cylinder, draw, fill=orange!20,
minimum width=2cm, minimum height=1.5cm,
shape border rotate=90,
drop shadow, font=\small
},
cloud/.style={
cloud, draw, fill=gray!20,
minimum width=3cm, minimum height=2cm,
drop shadow, font=\small
},
connection/.style={thick, ->, >=stealth},
label/.style={font=\footnotesize, fill=white, inner sep=2pt}
]
% Core components
\node[cloud] (internet) {Internet};
\node[server, below=3cm of internet] (loadbalancer) {Load Balancer};
% Web servers
\node[server, below left=2cm and 1cm of loadbalancer] (web1) {Web Server 1};
\node[server, below right=2cm and 1cm of loadbalancer] (web2) {Web Server 2};
% Application servers
\node[server, below=of web1] (app1) {App Server 1};
\node[server, below=of web2] (app2) {App Server 2};
% Databases
\node[database, below right=2cm and 0cm of app1] (db1) {Primary DB};
\node[database, right=1cm of db1] (db2) {Replica DB};
% Clients
\node[client, left=3cm of internet] (client1) {Client 1};
\node[client, above left=1cm and 2cm of internet] (client2) {Client 2};
\node[client, above right=1cm and 2cm of internet] (client3) {Client 3};
% Connections
\draw[connection] (client1) -- (internet);
\draw[connection] (client2) -- (internet);
\draw[connection] (client3) -- (internet);
\draw[connection, <->] (internet) -- node[label] {HTTPS} (loadbalancer);
\draw[connection] (loadbalancer) -- (web1);
\draw[connection] (loadbalancer) -- (web2);
\draw[connection] (web1) -- (app1);
\draw[connection] (web2) -- (app2);
\draw[connection] (app1) -- (db1);
\draw[connection] (app2) -- (db1);
\draw[connection, <->] (db1) -- node[label] {Sync} (db2);
% Background regions
\begin{pgfonlayer}{background}
\fill[yellow!20, rounded corners]
([shift={(-0.5,0.5)}]loadbalancer.north west)
rectangle
([shift={(0.5,-0.5)}]db2.south east);
\node[above] at (loadbalancer.north) {Data Center};
\end{pgfonlayer}
\end{tikzpicture}
\end{document}
Data Flow Diagram
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{arrows.meta, positioning, shapes, decorations.pathmorphing}
\begin{document}
\begin{tikzpicture}[
>=latex,
node distance=2.5cm,
process/.style={
rectangle, draw, fill=blue!30,
minimum width=3cm, minimum height=1cm,
rounded corners, font=\small\sffamily
},
data/.style={
trapezium, draw, fill=green!30,
trapezium left angle=70,
trapezium right angle=110,
minimum width=2.5cm, minimum height=0.8cm,
font=\small\sffamily
},
storage/.style={
rectangle, draw, fill=orange!30,
minimum width=2.5cm, minimum height=0.8cm,
path picture={
\draw ([xshift=0.1cm]path picture bounding box.north west)
-- ([xshift=-0.1cm]path picture bounding box.north east);
},
font=\small\sffamily
},
flow/.style={thick, ->, >=stealth},
label/.style={font=\footnotesize, above, sloped}
]
% Input layer
\node[data] (input) {Raw Data};
% Processing pipeline
\node[process, below=of input] (validate) {Validate};
\node[process, below=of validate] (transform) {Transform};
\node[process, below=of transform] (analyze) {Analyze};
% Storage
\node[storage, right=3cm of validate] (raw) {Raw Storage};
\node[storage, right=3cm of transform] (processed) {Processed DB};
\node[storage, right=3cm of analyze] (results) {Results Cache};
% Output
\node[data, below=of analyze] (output) {Reports};
\node[process, right=of output] (visualize) {Visualize};
\node[data, right=of visualize] (dashboard) {Dashboard};
% Main flow
\draw[flow] (input) -- node[label] {Stream} (validate);
\draw[flow] (validate) -- node[label] {Valid} (transform);
\draw[flow] (transform) -- node[label] {Clean} (analyze);
\draw[flow] (analyze) -- node[label] {Insights} (output);
% Storage connections
\draw[flow, dashed] (validate) -- node[label] {Archive} (raw);
\draw[flow, dashed] (transform) -- node[label] {Store} (processed);
\draw[flow, dashed] (analyze) -- node[label] {Cache} (results);
% Visualization flow
\draw[flow] (output) -- (visualize);
\draw[flow] (visualize) -- (dashboard);
\draw[flow, bend right] (results) to node[label, below] {Query} (visualize);
% Error handling
\node[process, left=2cm of transform, fill=red!30] (error) {Error Handler};
\draw[flow, red, bend right] (validate) to node[label, below] {Invalid} (error);
\draw[flow, red, bend right] (transform) to node[label, below] {Failed} (error);
\draw[flow, red] (error) |- (input);
% Decorations
\node[above=0.5cm of input, font=\large\bfseries] {Data Processing Pipeline};
% Legend
\begin{scope}[xshift=8cm, yshift=-3cm]
\node[process, minimum width=2cm] (l1) at (0,0) {Process};
\node[data, minimum width=2cm] (l2) at (0,-1) {Data};
\node[storage, minimum width=2cm] (l3) at (0,-2) {Storage};
\draw[flow] (3,0) -- node[above] {Flow} (4.5,0);
\draw[flow, dashed] (3,-1) -- node[above] {Store} (4.5,-1);
\node[above=0.3cm of l1, font=\bfseries] {Legend};
\end{scope}
\end{tikzpicture}
\end{document}
Next Steps
Explore more LaTeX visualization:
PGFPlots
Advanced plotting and charts
Circuit Diagrams
Electronic circuit drawings
Chemical Structures
Molecular diagrams
3D Graphics
Three-dimensional drawings
Pro tip: Start simple and build complexity gradually. Use the TikZ manual (texdoc tikz) as your reference - it’s comprehensive with excellent examples. Consider externalizing complex diagrams to speed up compilation of your main document.
Was this page helpful?
- Introduction to TikZ
- What is TikZ?
- Basic Setup
- Basic Drawing
- Coordinates and Paths
- Nodes and Labels
- Flowcharts and Diagrams
- Basic Flowcharts
- State Diagrams
- Graphs and Trees
- Graph Structures
- Tree Structures
- Scientific Diagrams
- Mathematical Diagrams
- Physics Diagrams
- Advanced Techniques
- Loops and Automation
- Styles and Scopes
- Decorations and Patterns
- Best Practices
- Optimization Tips
- Common Pitfalls
- Complete Examples
- Network Diagram
- Data Flow Diagram
- Next Steps