SVG Paths Explained: Bézier Curves, Smooth Joins, and Elliptical Arcs
DDEVELOPER
DeveloperPublished: 10 min read

SVG Paths Explained: Bézier Curves, Smooth Joins, and Elliptical Arcs

An SVG path describes moves, lines, curves, and closed subpaths. A string such as M10,10 C20,20 40,20 50,10 becomes readable when you separate the current point from the control points. This guide follows the W3C SVG 2 Paths chapter (Candidate Recommendation, 4 October 2018) and the SVG 1.1 arc implementation notes, connecting the geometry to practical editing decisions.

Japanese original published: 2026-04-25

Ten command types, with a few important exceptions

Uppercase commands generally use absolute coordinates; lowercase commands use coordinates relative to the current point. Z and z take no coordinates and do the same thing.

Scroll horizontally if the table does not fit.

CommandArgumentsAction
M / mx yMove without drawing
L / lx yDraw a line
H / hxHorizontal line
V / vyVertical line
C / cx1 y1 x2 y2 x yCubic Bézier curve
S / sx2 y2 x yCubic with a conditional reflected control point
Q / qx1 y1 x yQuadratic Bézier curve
T / tx yQuadratic with a conditional reflected control point
A / arx ry rotation large-arc sweep x yElliptical arc
Z / zNoneClose the current subpath

Repeated argument groups often let you omit a command letter: L 10,20 30,40 50,60 draws three lines. Extra coordinate pairs after M are treated as line commands. Closing with Z also differs from merely drawing an L back to the start: the stroke uses a closed join rather than two open ends.

A cubic Bézier curve has four control points

SVG directly supports quadratic and cubic Bézier curves. A cubic uses P₀, P₁, P₂, and P₃, evaluated for t between 0 and 1:

B(t) = (1-t)³ P₀ + 3(1-t)²t P₁ + 3(1-t)t² P₂ + t³ P₃

The weights are Bernstein basis polynomials. The curve passes through P₀ and P₃; it generally does not pass through P₁ or P₂. Its endpoint derivatives are B′(0) = 3(P₁ − P₀) and B′(1) = 3(P₃ − P₂). If one of those vectors is zero, that formula alone does not give a tangent direction.

The curve stays within the control points’ convex hull. Moving, rotating, or scaling the control points applies the same affine transformation to the curve. In a C command, the current point is P₀, the first two coordinate pairs are P₁ and P₂, and the last pair is P₃.

Evaluating and splitting with de Casteljau’s algorithm

Repeated linear interpolation provides a numerically stable way to evaluate a Bézier curve. It does not eliminate floating-point rounding error. For a cubic, the pseudocode is:

function deCasteljau(P0, P1, P2, P3, t):
  Q0 = lerp(P0, P1, t)  // lerp(A,B,t) = (1-t)A + tB
  Q1 = lerp(P1, P2, t)
  Q2 = lerp(P2, P3, t)
  R0 = lerp(Q0, Q1, t)
  R1 = lerp(Q1, Q2, t)
  return lerp(R0, R1, t)

The intermediate results also let you split the original curve into two Bézier segments without changing its mathematical shape. Splitting at t = 0.5 is useful when inserting a point during editing. That does not imply every operation in every vector editor uses the same implementation.

When S and T reflect a control point

S reflects the previous segment’s last control point about the current point only when the preceding command is C or S. Otherwise, its implicit first control point is the current point. T performs the corresponding reflection only after Q or T; otherwise its control point is the current point.

reflectedX = 2 * currentX - previousControlX
reflectedY = 2 * currentY - previousControlY

M 0,0 C 10,10 30,10 40,20 S 60,10 70,20
M 0,0 C 10,10 30,10 40,20 C 50,30 60,10 70,20

The two paths above describe the same curve. For equal-degree segments each parameterized over [0,1], the reflection matches the first derivatives at the join. It is not a general guarantee that S or T makes an arbitrary preceding segment smooth.

The seven arguments of an elliptical arc

A rx ry x-axis-rotation large-arc-flag sweep-flag x y

The radii describe the ellipse before rotation. Rotation is in degrees; x and y specify the endpoint. The starting point is the current point. The large-arc flag chooses an arc of at most 180 degrees or at least 180 degrees; the distinction can collapse for a semicircle.

A sweep flag of 0 selects the negative angular direction and 1 the positive direction. In the usual SVG coordinate system, with y increasing downward, these appear counterclockwise and clockwise respectively. Reflections or other transforms can change how that looks on screen.

In the general case, two ellipses can fit the endpoints, producing up to four arc choices. Some cases coincide. Negative radii are treated as positive; a zero radius produces a line; identical start and end points omit the arc. One A command cannot describe a complete circle.

Converting endpoints to a center

Some geometric operations need a center, corrected radii, a start angle, and a sweep angle rather than SVG’s endpoint form. The W3C implementation notes describe this conversion. Handle coincident endpoints and zero radii first, take absolute radii, and convert the rotation to radians before calling trigonometric functions.

// Start (x1,y1), end (x2,y2), rotation phi, flags fA and fS
xp = cos(phi)*(x1-x2)/2 + sin(phi)*(y1-y2)/2
yp = -sin(phi)*(x1-x2)/2 + cos(phi)*(y1-y2)/2

lambda = (xp/rx)^2 + (yp/ry)^2
if lambda > 1:
  rx *= sqrt(lambda)
  ry *= sqrt(lambda)

sign = (fA != fS) ? 1 : -1
factor = sign * sqrt(max(0,
  (rx^2*ry^2 - rx^2*yp^2 - ry^2*xp^2) /
  (rx^2*yp^2 + ry^2*xp^2)))
cxp = factor * rx*yp/ry
cyp = factor * -ry*xp/rx

cx = cos(phi)*cxp - sin(phi)*cyp + (x1+x2)/2
cy = sin(phi)*cxp + cos(phi)*cyp + (y1+y2)/2
start = atan2((yp-cyp)/ry, (xp-cxp)/rx)
sweep = atan2((-yp-cyp)/ry, (-xp-cxp)/rx) - start
if !fS and sweep > 0: sweep -= 2*pi
if  fS and sweep < 0: sweep += 2*pi

This is pseudocode: ^ denotes a power here, not JavaScript’s XOR operator. The max with zero handles a small negative radicand caused by rounding after radius correction. Extreme inputs need additional numerical care, including overflow handling. This outline is not a finished numerical library or a claim about a particular editor’s internals.

Four ways to draw or approximate a circle

For a radius of 50 and center at (100,100), compare a circle element, two arcs, four cubics, and four quadratics:

<circle cx="100" cy="100" r="50"/>

<path d="M 50,100 A 50,50 0 0 1 150,100 A 50,50 0 0 1 50,100"/>

<path d="M 100,50 C 127.614237,50 150,72.385763 150,100 C 150,127.614237 127.614237,150 100,150 C 72.385763,150 50,127.614237 50,100 C 50,72.385763 72.385763,50 100,50"/>

<path d="M 100,50 Q 150,50 150,100 Q 150,150 100,150 Q 50,150 50,100 Q 50,50 100,50"/>

The circle and arc constructions describe a circle. The polynomial curves approximate it; the quadratic example has a visibly larger deviation. The cubic uses κ = 4(√2 − 1)/3, about 0.5523. Before rounding the coordinates, its maximum radial error is about 0.0273% of the radius.

This classical coefficient places the endpoints and midpoint on the circle. It is not optimal for every error criterion; other approximations can reduce the maximum radial error. SVGO’s convertShapeToPath can convert circles and ellipses when convertArcs is enabled, but it does not mean “always replace a circle with four C commands.” A different representation is not necessarily a smaller one.

Geometric continuity is not the same as derivative continuity

Scroll horizontally if the table does not fit.

ConditionWhat matches at the join
G⁰Position; a corner is neither required nor excluded
Position and tangent direction, assuming a regular join
Position and first derivative
Position, first derivative, and second derivative

These derivative conditions assume the parameterization of each segment is fixed. Continuous curvature is not the same definition as C². The S/T reflection provides the first-derivative match described earlier, not a second-derivative guarantee. SVG path has no direct B-spline or NURBS command; such data needs conversion to supported segments or an approximation.

What path optimization can change

Size reductions may come from omitting repeated command letters, choosing shorter relative coordinates, using S/T where their control-point conditions hold, converting shapes, rounding coordinates, or merging compatible paths.

These operations do not all have the same consequences. Omitting syntax and rounding coordinates are different: rounding can change geometry. Merging paths can affect fills, markers, animation, or external references. Retain the original and compare the result at the actual display scales and in its real context. Neither a fixed reduction percentage nor perfect visual preservation is guaranteed.

Key points

  • SVG paths have ten command types; M repetition and Z/z have specific rules.
  • Bézier curves can be evaluated and split using their control points.
  • S/T reflection depends on the preceding command.
  • Arcs require attention to degenerate cases, radii, flags, and coordinate systems.
  • Circle approximations and coordinate rounding are not exact shape preservation.

References and sources

Editorial note

This article was prepared with AI assistance and reviewed by an editor before publication. It may still contain factual errors, interpretation mistakes, or outdated information. Check the cited primary sources or official documentation before making an important decision.

Related articles