CSS Codes

Classical error correction has a century-old toolbox: linear codes, parity checks, dual codes, minimum distances. Quantum error correction seemed to need something entirely new, because a qubit can fail in two independent ways at once — a bit flip XX and a phase flip ZZ — and because the stabilizers you measure to catch those failures must all commute or they cannot be measured together. The CSS construction, found independently by Calderbank and Shor and by Steane in 1996, is the discovery that you do not need something new. You import the classical toolbox twice: one classical binary code C1C_1 to beat bit flips in the computational basis, and a second code C2⊥C_2^{\perp} to beat phase flips in the Hadamard basis. A single algebraic condition — the nesting C2⊆C1C_2 \subseteq C_1 — is exactly what forces the two families of quantum checks to commute, and everything else about the code (its parameters, its logical operators, its transversal gates) then follows by turning a crank you already own from classical coding theory. That one inclusion is the whole recipe, and its reach is enormous. The parity checks of C1C_1 become the ZZ-type stabilizers that flag bit flips; the parity checks of C2⊥C_2^{\perp} become the XX-type stabilizers that flag phase flips; the codewords are uniform superpositions over cosets of C2C_2 inside C1C_1. Because the XX and ZZ checks never mix, decoding splits into two independent classical problems, the transversal CNOT is free, and self-dual choices buy transversal Hadamard and phase gates. The Steane seven-qubit code, the surface code, the color codes, and the modern "good" quantum LDPC codes are all CSS — which is why this one subclass, born from a two-line classical observation, is the working substrate of nearly all fault-tolerant quantum computing.

Key takeaways
  • A CSS code is a stabilizer code built from two classical binary linear codes C1C_1 and C2C_2 with C2⊆C1C_2 \subseteq C_1: the parity checks of C1C_1 catch bit-flip (XX) errors and the parity checks of C2⊥C_2^{\perp} catch phase-flip (ZZ) errors.
  • The nesting C2⊆C1C_2 \subseteq C_1 is algebraically identical to the commutation requirement HXHZT=0H_X H_Z^{T}=0, which is the only thing needed to make the two check families a valid, jointly measurable stabilizer group.
  • It is an [[n, k1−k2, d]][[n,\,k_1-k_2,\,d]] code with d≥min⁡(d(C1), d(C2⊥))d \ge \min\big(d(C_1),\,d(C_2^{\perp})\big): nn physical qubits, k1−k2k_1-k_2 logical qubits (the number of cosets of C2C_2 in C1C_1), distance at least the smaller classical distance.
  • Because the XX-type and ZZ-type checks are kept separate, syndrome decoding decouples into two independent classical decoders, and the transversal CNOT is logical for every CSS code.
  • Dual-containing codes (C1=C2⊥C_1=C_2^{\perp}) add a transversal Hadamard, and doubly-even codes add a transversal phase gate — the Steane code, from the [7,4,3][7,4,3] Hamming code, has the full transversal Clifford group.
  • Key idea: pick two classical binary linear codes with C2⊆C1C_2\subseteq C_1; use the parity checks of C1C_1 as the ZZ-stabilizers (against bit flips) and the parity checks of C2⊥C_2^{\perp} as the XX-stabilizers (against phase flips). The nesting is exactly HXHZT=0H_X H_Z^{T}=0, giving an [[n, k1−k2, ≥min⁡(d(C1),d(C2⊥))]][[n,\ k_1-k_2,\ \ge\min(d(C_1),d(C_2^{\perp}))]] code that corrects XX and ZZ errors independently.

Where this lives today

Nearly every serious effort to build a fault-tolerant quantum computer is running a CSS code. The dominant architecture is the surface code — a planar cousin of Kitaev's toric code, CSS by construction, with only nearest-neighbour XX and ZZ checks and independent matching decoders for the two error types. In 2024 a Google superconducting processor ran a distance-five and then a distance-seven surface-code logical qubit whose logical error rate fell as the code grew, the long-sought below-threshold behaviour that CSS structure and local checks were designed to enable. Color codes, also CSS, trade a denser lattice for transversal access to more gates. At the frontier of theory, the "good" quantum LDPC codes proved to exist by Panteleev and Kalachev and by Leverrier and Zémor — codes with constant rate and linear distance, the asymptotic optimum Calderbank and Shor first showed was possible — are CSS codes built from balanced products, with neutral-atom hardware now demonstrating small instances. Even the non-Clifford TT gate that CSS transversality cannot supply is manufactured through magic-state distillation protocols themselves built from CSS codes. The two-line classical observation of 1996 has become the load-bearing structure of the whole field.

The physical picture

A quantum error has two independent dials. One flips the bit — a Pauli XX swapping ∣0⟩|0\rangle and ∣1⟩|1\rangle. The other flips the phase — a Pauli ZZ swapping ∣+⟩|+\rangle and ∣−⟩|-\rangle. Discretization of errors tells us that beating each dial separately beats any error, since an arbitrary single-qubit fault is a combination of {I,X,Y,Z}\{I,X,Y,Z\} and Y=iXZY=iXZ is just both dials at once. CSS codes take this literally: they run two classical error-correcting schemes side by side, one in the computational basis to catch bit flips and one in the Hadamard basis to catch phase flips. The Hadamard gate bridges the two worlds — it maps X↔ZX \leftrightarrow Z, so the second scheme is the first wearing a Hadamard disguise. The only genuinely quantum requirement is that the two schemes not interfere when measured together, and that requirement has a compact classical translation. The first figure lays out the architecture and the single condition that makes it legal.

Figure
Two classical linear codes make one quantum code: the parity checks of C₁ become the Z-type stabilizers that catch bit-flip X errors, the parity checks of C₂⊥ become the X-type stabilizers that catch phase-flip Z errors, and the single nesting C₂ ⊆ C₁ is exactly the commutation condition H_X H_Zᵀ = 0 mod 2 that lets both check families share the same qubits
Two classical codes, one quantum code — and C₂ ⊆ C₁ makes the checks commute bit-flip X errors corrected by C₁ (computational basis) Z-checks H_Z = H(C₁) n − k₁ generators, supports span C₁⊥ phase-flip Z errors corrected by C₂⊥ (Hadamard basis) X-checks H_X = G(C₂) k₂ generators, supports span C₂ H X ⟷ Z 𝔽₂ⁿ (all n-bit strings) C₁ C₂ H_X H_Zᵀ = 0 (mod 2) ⟺ C₂ ⊆ C₁ rows of H_X span C₂, ker H_Z = C₁

Why does the nesting force commutation? Two Paulis commute unless one is XX-type and the other ZZ-type on an odd number of shared qubits. Every XX-stabilizer has support in C2C_2; every ZZ-stabilizer has support in C1⊥C_1^{\perp}. Demanding an even overlap for every such pair means every C2C_2 vector is orthogonal to every C1⊥C_1^{\perp} vector — precisely C2⊆(C1⊥)⊥=C1C_2 \subseteq (C_1^{\perp})^{\perp} = C_1. The single most useful move in the subject is to build both codes from one classical code: take a code CC whose dual sits inside it, C⊥⊆CC^{\perp}\subseteq C, and set C1=CC_1=C, C2=C⊥C_2=C^{\perp}. The nesting is then automatic, and the smallest interesting example — the [7,4,3][7,4,3] Hamming code, which contains its own dual — produces the seven-qubit Steane code, the subject of the second figure.

Figure
The Steane seven-qubit code from one classical code: take C₁ as the 7,4,3 Hamming code and C₂ as its dual the 7,3,4 simplex code; the Hamming parity-check matrix H has every row of weight 4 and every row-pair overlapping in weight 2, so H Hᵀ = 0 mod 2, the nesting C₂ ⊆ C₁ holds, and the CSS rule delivers a quantum code with n = 7, k = 4 − 3 = 1, and d = min of 3 and 3 = 3 that corrects any single-qubit error
The Steane code: one Hamming matrix, used for both X and Z checks H = parity check of the 7,4,3 Hamming code — its 7 columns are the nonzero 3-bit numbers 1…7 col 1234567 r₁ 0001111 wt 4 r₂ 0110011 wt 4 r₃ 1010101 wt 4 Row overlaps: r₁·r₂ = r₁·r₃ = r₂·r₃ = 2 (even) ⟹ H Hᵀ = 0 (mod 2) Self-orthogonal: C₂ = C₁⊥ = rowspace(H) ⊆ ker(H) = C₁ ⟹ nesting holds CSS parameters n = 7, k = k₁ − k₂ = 4 − 3 = 1 d ≥ min(3, 3) = 3 → [[7,1,3]] 6 stabilizers = 3 X-type + 3 Z-type what it buys corrects any single-qubit error (t = 1) C₁ = C₂⊥ ⟹ transversal H full transversal Clifford: H, S, CNOT

The core equations

The construction begins and ends with one set-theoretic inclusion. Two classical binary linear codes are chosen inside the same nn-bit space, one nested in the other; this single line is the entire hypothesis of the CSS theorem, and every property below is a consequence.

C2⊆C1⊆F2 n(1)C_2 \subseteq C_1 \subseteq \mathbb{F}_2^{\,n} \qquad (1)

where: C1C_1 — a classical [n,k1,d1][n,k_1,d_1] binary linear code whose parity checks correct bit-flip (XX) errors; C2C_2 — a classical [n,k2,d2][n,k_2,d_2] linear code contained in C1C_1, whose dual C2⊥C_2^{\perp} corrects phase-flip (ZZ) errors; F2 n\mathbb{F}_2^{\,n} — the space of nn-bit binary strings. Read it as: pick a big code C1C_1 and a smaller code C2C_2 living inside it, and the quantum code is squeezed between them. The logical codewords are the most concrete object in the theory: uniform superpositions over the cosets of C2C_2 inside C1C_1. Distinct cosets are distinct logical states, so the logical alphabet is literally the quotient C1/C2C_1/C_2.

∣x+C2⟩=1∣C2∣∑y∈C2∣x+y⟩,x∈C1(2)|x + C_2\rangle = \frac{1}{\sqrt{|C_2|}} \sum_{y \in C_2} |x+y\rangle,\qquad x\in C_1 \qquad (2)

where: xx — a representative codeword of C1C_1 labelling the coset; yy — runs over all ∣C2∣=2k2|C_2|=2^{k_2} words of C2C_2; the prefactor normalizes the superposition. Two representatives give the same state iff they differ by an element of C2C_2, so the states are labelled by cosets x+C2x+C_2, and there are ∣C1∣/∣C2∣|C_1|/|C_2| of them. The commutation of all stabilizers — the condition that lets them be measured simultaneously without disturbing the codeword — reduces to a single matrix equation over F2\mathbb{F}_2. This is the algebraic heart of CSS and the reason the construction works at all.

HX HZT=0(mod2)(3)H_X\,H_Z^{T} = 0 \pmod 2 \qquad (3)

where: HXH_X — the k2×nk_2\times n matrix whose rows are the XX-type stabilizer supports, a generator matrix of C2C_2 (equivalently the parity-check matrix of C2⊥C_2^{\perp}); HZH_Z — the (n−k1)×n(n-k_1)\times n parity-check matrix of C1C_1, whose rows are the ZZ-type stabilizer supports and span C1⊥C_1^{\perp}. The equation says every row of HXH_X (a C2C_2 word) is orthogonal to every row of HZH_Z (a C1⊥C_1^{\perp} word), which is exactly C2⊆C1C_2\subseteq C_1. The parameters fall out by counting. There are (n−k1)(n-k_1) independent ZZ-checks and k2k_2 independent XX-checks, so nn qubits minus (n−k1)+k2(n-k_1)+k_2 generators leaves the logical count, and the distance is controlled by the two classical minimum distances.

[[ n, k1−k2, d ]],d≥min⁡(d(C1), d(C2⊥))(4)[[\,n,\ k_1-k_2,\ d\,]],\qquad d \ge \min\big(d(C_1),\ d(C_2^{\perp})\big) \qquad (4)

where: nn — physical qubits, the shared block length; k1−k2k_1-k_2 — logical qubits, equal to log⁡2(∣C1∣/∣C2∣)\log_2(|C_1|/|C_2|), the number of cosets; dd — the quantum distance, the minimum weight of any nontrivial logical operator. The bound is one-sided: degenerate codes can have dd strictly larger than min⁡(d(C1),d(C2⊥))\min(d(C_1),d(C_2^{\perp})). The logical operators are undetectable, non-stabilizer Paulis. Because the stabilizer group splits into XX-type and ZZ-type, so do the logical operators, and each is read off directly from the classical codes as a coset representative.

Xˉ=X(w), w∈C1∖C2;Zˉ=Z(v), v∈C2⊥∖C1⊥(5)\bar X = X(w),\ w\in C_1\setminus C_2;\qquad \bar Z = Z(v),\ v\in C_2^{\perp}\setminus C_1^{\perp} \qquad (5)

where: Xˉ\bar X — logical XX, an XX-string on a C1C_1 word not in C2C_2 — it moves between cosets, so it swaps logical states; Zˉ\bar Z — logical ZZ, a ZZ-string on a C2⊥C_2^{\perp} word not in C1⊥C_1^{\perp} — it applies coset-dependent signs; ∖\setminus — set difference, since representatives are fixed only modulo the stabilizer words C2C_2 and C1⊥C_1^{\perp}. Their minimum weights, d(C1)d(C_1) and d(C2⊥)d(C_2^{\perp}), give the distance bound of equation (4). The first gift of the separable structure is that the two-qubit workhorse gate needs no encoding overhead. Applied qubit-by-qubit between two identical CSS blocks, the physical CNOT is the logical CNOT.

CNOT‾=∏j=1nCNOT j→j′(6)\overline{\mathrm{CNOT}} = \prod_{j=1}^{n}\mathrm{CNOT}_{\,j\to j'} \qquad (6)

where: CNOTj→j′\mathrm{CNOT}_{j\to j'} — a physical CNOT from qubit jj of the control block to the aligned qubit j′j' of the target block; the product runs over all nn aligned pairs. Because CNOT sends X⊗I↦X⊗XX\otimes I\mapsto X\otimes X and I⊗Z↦Z⊗ZI\otimes Z\mapsto Z\otimes Z, and both blocks share the same HX,HZH_X,H_Z, every stabilizer maps to a product of stabilizers — the code space is preserved and the logical action is CNOT. The second gift arrives when the two classical codes coincide up to duality. A self-dual-containing code C1=C2⊥C_1=C_2^{\perp} makes the transversal Hadamard logical, and a doubly-even code makes the transversal phase gate logical, delivering the entire Clifford group transversally.

Hˉ=H⊗n  (if C1=C2⊥),Sˉ=∏jSj±1  (if C1 doubly-even)(7)\bar H = H^{\otimes n}\ \ (\text{if } C_1=C_2^{\perp}),\qquad \bar S = \textstyle\prod_j S_j^{\pm1}\ \ (\text{if } C_1\ \text{doubly-even}) \qquad (7)

where: H⊗nH^{\otimes n} — Hadamard on every qubit; it swaps the XX-check set (span C2C_2) with the ZZ-check set (span C1⊥C_1^{\perp}), which is stabilizer-preserving precisely when C2=C1⊥C_2=C_1^{\perp}; Sˉ\bar S — transversal phase gate, logical when every codeword weight of C1C_1 is ≡0(mod4)\equiv 0 \pmod 4 (doubly-even), which controls the accumulated ii phases. The Steane code satisfies both, so its logical HH, SS, and CNOT are all transversal.

Derivation AWhy the nesting condition makes every stabilizer commute

The goal is to prove that the purely set-theoretic inclusion C2⊆C1C_2\subseteq C_1 is one and the same statement as the physical requirement that all the CSS stabilizers commute, so that a valid quantum code drops out of a valid pair of classical codes with no further checking. We start from the symplectic commutation rule, specialize it to pure-XX and pure-ZZ generators, collect the orthogonality conditions into a single matrix equation, and read that equation as a containment of classical codes.

Step 1. Two Pauli operators written in symplectic form, X(a)Z(b)X(a)Z(b) and X(a′)Z(b′)X(a')Z(b'), commute if and only if a⋅b′+a′⋅b=0(mod2)a\cdot b' + a'\cdot b = 0 \pmod 2. For a pure-XX generator (a=ra=r, b=0b=0) and a pure-ZZ generator (a′=0a'=0, b′=sb'=s) the condition collapses to r⋅s=0r\cdot s = 0. Why: only the XX-part of one operator can clash with the ZZ-part of the other, so an even overlap of their supports is exactly what makes them commute.

Step 2. The XX-stabilizers of the CSS code have supports that are the rows of HXH_X, which span C2C_2; the ZZ-stabilizers have supports that are the rows of HZH_Z, which span C1⊥C_1^{\perp}. Requiring r⋅s=0r\cdot s=0 for every XX-row rr and every ZZ-row ss is the single matrix equation HXHZT=0(mod2)H_X H_Z^{T}=0 \pmod 2. Why: pairwise orthogonality of all rows is precisely what a vanishing matrix product records, so the whole commutation table compresses to one equation.

Step 3. Now decode that equation. Its rows say every element of C2C_2 (the rowspace of HXH_X) is orthogonal to every element of C1⊥C_1^{\perp} (the rowspace of HZH_Z), i.e. C2⊆(C1⊥)⊥C_2 \subseteq (C_1^{\perp})^{\perp}. Since (C1⊥)⊥=C1(C_1^{\perp})^{\perp}=C_1 for any linear code, this is exactly C2⊆C1C_2\subseteq C_1. Why: orthogonality to the dual code is membership in the original code, so "commutes with all ZZ-checks" is literally "lies in C1C_1."

Step 4. Same-type generators need no condition: two XX-type operators always commute, as do two ZZ-type operators, because neither has a part that can clash with the other. So C2⊆C1C_2\subseteq C_1 is not merely sufficient but necessary and complete — it is the whole content of "these Paulis form an abelian stabilizer group." Why: the only possible obstruction to a commuting group is the cross XX–ZZ overlaps, and the nesting kills exactly those.

r⋅s=0  ∀ r∈C2, s∈C1⊥ ⟺ HXHZT=0 ⟺ C2⊆C1r\cdot s=0\ \ \forall\, r\in C_2,\ s\in C_1^{\perp}\ \Longleftrightarrow\ H_X H_Z^{T}=0\ \Longleftrightarrow\ C_2\subseteq C_1

Verified: the symplectic rule and its reduction to HXHZT=0H_X H_Z^{T}=0 are standard (Gottesman 1997); the containment C2⊆(C1⊥)⊥=C1C_2\subseteq(C_1^{\perp})^{\perp}=C_1 uses only linear-algebra duality over F2\mathbb{F}_2. Cross-checked against Nielsen and Chuang §10.4.2 and Preskill Ch. 7.

Go deeper · Derivation B · 2 minBuilding the Steane code from the Hamming code
Derivation BBuilding the Steane code from the Hamming code

The goal is to construct the smallest and most important CSS code entirely from a single classical code and its dual, so that the abstract nesting C2⊆C1C_2\subseteq C_1 becomes a concrete 3×73\times 7 matrix and the parameters [[7,1,3]][[7,1,3]] appear by counting. We take the [7,4,3][7,4,3] Hamming code as C1C_1, show it contains its own dual so C2=C1⊥C_2=C_1^{\perp} satisfies the nesting for free, use the one matrix for both check families, and read off the parameters and transversal gates.

Step 1. Write the Hamming parity-check matrix, the 3×73\times 7 matrix HH whose seven columns are the nonzero binary 33-vectors, ordered 11 through 77. The Hamming code is C1=ker⁡HC_1=\ker H, a [7,4,3][7,4,3] code (rank 33, so dimension 44; its minimum distance is 33). Why: every classical linear code is defined by such a parity-check matrix, and the Hamming choice — all nonzero columns — is what gives it distance 33 and single-error correction.

Step 2. Check self-orthogonality. Each row of HH has weight 44, so ri⋅ri=4≡0r_i\cdot r_i=4\equiv 0; and each pair of rows overlaps in weight 22, so ri⋅rj=2≡0r_i\cdot r_j = 2\equiv 0. Hence HHT=0(mod2)HH^{T}=0 \pmod 2, meaning rowspace(H)=C1⊥\mathrm{rowspace}(H)=C_1^{\perp} is contained in ker⁡H=C1\ker H = C_1. Setting C2=C1⊥C_2=C_1^{\perp} gives C2⊆C1C_2\subseteq C_1 with no extra work. Why: a dual-containing code hands you the nesting automatically, which is why the entire construction can be seeded by one classical code.

Step 3. Assign the stabilizers. Use HH as both the ZZ-check matrix (HZ=H(C1)=HH_Z=H(C_1)=H, three ZZ-generators) and the XX-check matrix (HX=G(C2)=G(C1⊥)=HH_X=G(C_2)=G(C_1^{\perp})=H, three XX-generators, since C1⊥=rowspace(H)C_1^{\perp}=\mathrm{rowspace}(H)). Commutation is HXHZT=HHT=0H_X H_Z^{T}=HH^{T}=0, already verified. Why: because C2=C1⊥C_2=C_1^{\perp}, the same matrix plays both roles, giving a strikingly symmetric code with six generators.

Step 4. Count the parameters. There are 66 independent generators on 77 qubits, so k=7−6=1k=7-6=1; equivalently k=k1−k2=4−3=1k=k_1-k_2=4-3=1. The distance is d≥min⁡(d(C1),d(C2⊥))=min⁡(3,3)=3d\ge\min(d(C_1),d(C_2^{\perp}))=\min(3,3)=3, and it equals 33 because C1C_1 has a weight-33 codeword outside C2C_2. This is the [[7,1,3]][[7,1,3]] Steane code, correcting any single-qubit error. Why: the coset count and the classical distances directly give kk and dd, no explicit codeword enumeration needed.

Step 5. Read off the transversal gates. Since C1=C2⊥C_1=C_2^{\perp}, the transversal Hadamard H⊗7H^{\otimes 7} swaps the XX- and ZZ-check sets and is logical; the Hamming/simplex structure additionally makes the transversal phase gate logical. With the always-available transversal CNOT, the Steane code realizes the full Clifford group transversally. Why: the dual-containing symmetry is exactly the property equation (7) needs, so the Steane code is the canonical fault-tolerant CSS code.

n=7,k=4−3=1,d=min⁡(3,3)=3 ⇒ [[7,1,3]]n=7,\quad k=4-3=1,\quad d=\min(3,3)=3\ \Rightarrow\ [[7,1,3]]

Verified: HHT=0(mod2)HH^{T}=0\pmod 2 by the explicit row weights (44) and overlaps (22); the [7,4,3][7,4,3] Hamming parameters are standard; [[7,1,3]][[7,1,3]] and the transversal Clifford set match Nielsen and Chuang §10.4.3 and Steane (1996).

Go deeper · Derivation C · 2 minCounting logical qubits and bounding the distance
Derivation CCounting logical qubits and bounding the distance

The goal is to establish the two headline numbers of equation (4) — that a CSS code encodes exactly k1−k2k_1-k_2 logical qubits and has distance at least min⁡(d(C1),d(C2⊥))\min(d(C_1),d(C_2^{\perp})) — directly from the coset picture and the definition of a logical operator, without ever touching the 2n2^n-dimensional Hilbert space. We count the coset states for the dimension, then identify undetectable non-stabilizer Paulis with nontrivial coset representatives for the distance.

Step 1. The logical basis states are the coset superpositions ∣x+C2⟩|x+C_2\rangle of equation (2). Two are equal when x−x′∈C2x-x'\in C_2 and orthogonal otherwise, because distinct cosets have disjoint computational support. So the number of orthonormal logical states is the number of cosets of C2C_2 in C1C_1. Why: the code space is spanned by these states and they are automatically an orthonormal basis, so counting them is counting the logical dimension.

Step 2. By Lagrange's theorem for the subgroup C2≤C1C_2\le C_1, that number is ∣C1∣/∣C2∣=2k1/2k2=2k1−k2|C_1|/|C_2| = 2^{k_1}/2^{k_2} = 2^{k_1-k_2}. Taking logarithms, the code encodes k=k1−k2k=k_1-k_2 logical qubits — matching the generator count n−[(n−k1)+k2]n-[(n-k_1)+k_2]. Why: the two independent counts agree, confirming the code space is 2k1−k22^{k_1-k_2}-dimensional exactly as claimed.

Step 3. Now the distance. An XX-error X(e)X(e) is undetectable iff it commutes with all ZZ-checks, i.e. HZe=0H_Z e=0, i.e. e∈ker⁡HZ=C1e\in\ker H_Z = C_1; it acts nontrivially (is not itself a stabilizer) iff e∉C2e\notin C_2. So the lightest logical XX has weight min⁡e∈C1∖C2wt(e)≥d(C1)\min_{e\in C_1\setminus C_2}\mathrm{wt}(e)\ge d(C_1). Why: an undetectable error that still changes the codeword is exactly a logical operator, and here those live in the coset difference C1∖C2C_1\setminus C_2.

Step 4. By the Hadamard-mirrored argument, a ZZ-error Z(f)Z(f) is undetectable iff HXf=0H_X f=0, i.e. f∈C2⊥f\in C_2^{\perp}, and nontrivial iff f∉C1⊥f\notin C_1^{\perp}, so the lightest logical ZZ has weight ≥d(C2⊥)\ge d(C_2^{\perp}). The code distance, the minimum weight over all nontrivial logicals, is therefore ≥min⁡(d(C1),d(C2⊥))\ge\min(d(C_1),d(C_2^{\perp})). Why: XX-type and ZZ-type logicals are bounded separately by the two classical distances, and the smaller one dominates.

dim⁡(code)=∣C1∣∣C2∣=2k1−k2,d=min⁡w∈C1∖C2v∈C2⊥∖C1⊥ ⁣min⁡(wt(w),wt(v)) ≥ min⁡(d(C1),d(C2⊥))\dim(\text{code}) = \frac{|C_1|}{|C_2|}=2^{k_1-k_2},\qquad d=\min_{\substack{w\in C_1\setminus C_2\\ v\in C_2^{\perp}\setminus C_1^{\perp}}}\!\min\big(\mathrm{wt}(w),\mathrm{wt}(v)\big)\ \ge\ \min\big(d(C_1),d(C_2^{\perp})\big)

Verified: the coset count is Lagrange's theorem applied to C2≤C1C_2\le C_1; the distance identification of undetectable non-stabilizer Paulis with C1∖C2C_1\setminus C_2 and C2⊥∖C1⊥C_2^{\perp}\setminus C_1^{\perp} follows the definition of a logical operator (Preskill Ch. 7). The bound is not tight for degenerate codes. Cross-checked against Wilde Ch. 10 and Calderbank–Shor (1996).

Limiting cases

The single recipe C2⊆C1C_2\subseteq C_1 specializes into every important family of quantum codes; pushing the two classical codes to extremes shows both the power and the boundaries of the construction.

CaseResultMeaning
Dual-containing codeC1=C, C2=C⊥, C⊥⊆CC_1=C,\ C_2=C^{\perp},\ C^{\perp}\subseteq COne weakly self-dual code seeds the whole code, giving [[n, 2k−n, d]][[n,\,2k-n,\,d]]; the route to the Steane code and to a transversal Hadamard.
Doubly-even self-dualC=C⊥, wt(x)≡0 ⁣(mod4)C=C^{\perp},\ \mathrm{wt}(x)\equiv 0\!\pmod 4Adds a transversal phase gate on top of HH and CNOT, completing the transversal Clifford group — the Steane code's gate set.
Topological (surface/toric)HX=∂2, HZ=∂1T, ∂1∂2=0H_X=\partial_2,\ H_Z=\partial_1^{T},\ \partial_1\partial_2=0On a cell complex the boundary maps furnish commuting local checks; HXHZT=0H_X H_Z^{T}=0 becomes ∂1∂2=0\partial_1\partial_2=0 and logical operators are homology classes.
Trivial codeC2={0}, C1=F2 nC_2=\{0\},\ C_1=\mathbb{F}_2^{\,n}Then k=nk=n but d(C2⊥)=d(F2 n)=1d(C_2^{\perp})=d(\mathbb{F}_2^{\,n})=1, so d=1d=1: no protection. The recipe is empty unless both codes are genuinely structured.

Worked examples

1 · The Steane code, fully worked from the Hamming matrix

Take C1C_1 to be the [7,4,3][7,4,3] Hamming code with the parity-check matrix HH whose columns are 11 through 77 in binary, and C2=C1⊥C_2=C_1^{\perp}. Verify the nesting numerically, and compute nn, kk, dd, the number of stabilizers, and the transversal gates.

Step 1. Confirm self-orthogonality by hand. The three rows are r1=0001111r_1=0001111, r2=0110011r_2=0110011, r3=1010101r_3=1010101. Each has weight 44, so ri⋅ri=4≡0(mod2)r_i\cdot r_i=4\equiv 0\pmod 2. The pairwise overlaps are r1⋅r2=∣{6,7}∣=2r_1\cdot r_2=|\{6,7\}|=2, r1⋅r3=∣{5,7}∣=2r_1\cdot r_3=|\{5,7\}|=2, r2⋅r3=∣{3,7}∣=2r_2\cdot r_3=|\{3,7\}|=2, all ≡0\equiv 0. Therefore HHT=0(mod2)HH^{T}=0\pmod 2, so C2=rowspace(H)⊆ker⁡H=C1C_2=\mathrm{rowspace}(H)\subseteq\ker H=C_1. The nesting C2⊆C1C_2\subseteq C_1 holds.

Step 2. Dimensions. HH has rank 33, so C1=ker⁡HC_1=\ker H has dimension k1=7−3=4k_1=7-3=4 and C2=C1⊥=rowspace(H)C_2=C_1^{\perp}=\mathrm{rowspace}(H) has dimension k2=3k_2=3. The logical count is k=k1−k2=4−3=1k=k_1-k_2=4-3=\mathbf{1}, and equivalently log⁡2(∣C1∣/∣C2∣)=log⁡2(16/8)=1\log_2(|C_1|/|C_2|)=\log_2(16/8)=1. One logical qubit.

Step 3. Distance. Logical XX lives in C1∖C2C_1\setminus C_2; the lightest such word has weight d(C1)=3d(C_1)=3. Logical ZZ lives in C2⊥∖C1⊥=C1∖C1⊥C_2^{\perp}\setminus C_1^{\perp}=C_1\setminus C_1^{\perp}; the lightest has weight d(C2⊥)=d(C1)=3d(C_2^{\perp})=d(C_1)=3. So d=min⁡(3,3)=3d=\min(3,3)=\mathbf{3}, and the code corrects t=⌊(3−1)/2⌋=1t=\lfloor(3-1)/2\rfloor=1 arbitrary single-qubit error. Distance 33, [[7,1,3]][[7,1,3]].

Step 4. Stabilizers and gates. There are n−k1=3n-k_1=3 independent ZZ-checks and k2=3k_2=3 independent XX-checks, 66 generators on 77 qubits, leaving 7−6=17-6=1 logical qubit — consistent with Step 2. Because C1=C2⊥C_1=C_2^{\perp}, the transversal Hadamard is logical; the doubly-even structure makes the transversal phase gate logical; the transversal CNOT is automatic. Six stabilizers, and a full transversal Clifford group {H,S,CNOT}\{H,S,\mathrm{CNOT}\} — the reason the Steane code is the standard fault-tolerant building block.

2 · The toric code as a CSS code, and its parameters

The toric code places one qubit on each edge of an L×LL\times L square lattice with periodic boundaries. Its XX-checks are the vertex operators AvA_v (a product of XX on the four edges meeting a vertex) and its ZZ-checks are the plaquette operators BpB_p (a product of ZZ on the four edges of a face). Show it is CSS, and find [[n,k,d]][[n,k,d]] for L=3L=3.

Step 1. CSS structure. Every AvA_v is purely XX-type and every BpB_p is purely ZZ-type, so the stabilizers already split into an XX-block and a ZZ-block — the defining CSS form. Any vertex and any plaquette share either 00 or 22 edges, so AvA_v and BpB_p overlap on an even number of qubits and commute; in homological language HX=∂2H_X=\partial_2, HZ=∂1TH_Z=\partial_1^{T}, and HXHZT=∂1∂2=0H_X H_Z^{T}=\partial_1\partial_2=0. It is a CSS code with geometrically local checks.

Step 2. Count qubits and generators. On an L×LL\times L torus there are 2L22L^2 edges, so n=2L2n=2L^2. There are L2L^2 vertices and L2L^2 plaquettes, but each family has exactly one dependency (the product of all AvA_v is the identity, and likewise all BpB_p), giving (L2−1)+(L2−1)=2L2−2(L^2-1)+(L^2-1)=2L^2-2 independent generators. Hence k=n−(2L2−2)=2k=n-(2L^2-2)=\mathbf{2} logical qubits, independent of LL. Two logical qubits.

Step 3. Distance. A logical operator is a non-contractible loop of XX or ZZ around the torus, and the shortest such loop has length LL, so d=Ld=L. Degeneracy makes the code highly forgiving — many equivalent errors share a syndrome — but the distance is exactly LL, not merely bounded by it. d=Ld=L.

Step 4. Evaluate at L=3L=3: n=2⋅9=18n=2\cdot 9=18, k=2k=2, d=3d=3, giving a [[18,2,3]]\mathbf{[[18,2,3]]} code. It corrects any single-qubit error using 2⋅9−2=162\cdot 9-2=16 local checks, and — being CSS — decodes its XX and ZZ errors with two independent minimum-weight matching runs. [[18,2,3]][[18,2,3]], the concrete face of "surface codes are CSS."

Physics of the portrait

CSS codes carry three names — Calderbank, Shor, and Steane — for two independent 1996 discoveries that turned out to be the same construction. Andrew Steane approached it from the physics of interference and gave the field its canonical worked example.

Origins · 1 minAndrew Steane and how this was discovered
AS
Andrew Steane
born 1965, British physicist · quantum error correction and ion-trap computing

Andrew Martin Steane, a physicist at the University of Oxford, arrived at quantum error correction from atomic physics and multiple-particle interference rather than from classical coding theory. In 1996, in "Multiple particle interference and quantum error correction" (Proc. R. Soc. A 452, 2551) and "Error correcting codes in quantum theory" (Phys. Rev. Lett. 77, 793), he showed that a quantum code could be assembled from a classical binary code containing its own dual, using the code to protect amplitudes and its dual to protect phases — the seven-qubit [[7,1,3]][[7,1,3]] code now bearing his name, built from the [7,4,3][7,4,3] Hamming code. At almost the same moment Robert Calderbank and Peter Shor, working from the classical theory of good codes, proved that random dual-containing codes yield quantum codes with provably nonzero asymptotic rate and distance ("Good quantum error-correcting codes exist," Phys. Rev. A 54, 1098). The two results were quickly recognized as one recipe, and the acronym CSS — Calderbank–Shor–Steane — was born. Within a year Gottesman's stabilizer formalism revealed CSS codes as a transparent subclass of stabilizer codes, and the Steane code became, and remains, the code through which most students first meet fault-tolerant gates — its transversal Clifford group a direct consequence of the self-duality Steane exploited. He went on to lead trapped-ion quantum-computing experiments at Oxford, keeping one foot in the theory and the other in the hardware that must run it.

History
1996
— Calderbank and Shor prove good quantum codes exist by importing classical linear codes
1996
— Steane independently builds quantum codes from dual-containing codes and the seven-qubit code
1997
— Gottesman's stabilizer formalism recasts CSS codes as a transparent stabilizer subclass
1997
— Kitaev introduces the toric code, the first topological CSS code
2024
— a CSS surface code is driven below threshold on a superconducting processor

Going further

Texts. Nielsen and Chuang, Quantum Computation and Quantum Information, §10.4.2–10.4.3 (CSS codes and the Steane code) · Preskill, Lecture Notes for Physics 219, Ch. 7 (Quantum Error Correction) · Watrous, The Theory of Quantum Information, error-correction chapter · Wilde, Quantum Information Theory, Ch. 10 (Stabilizer and CSS codes) · Kitaev, Shen and Vyalyi, Classical and Quantum Computation, §15 · Gottesman, Stabilizer Codes and Quantum Error Correction (PhD thesis, 1997).

Provenance. The construction and parameters are standard: the originals are Calderbank and Shor, Phys. Rev. A 54, 1098 (1996), and Steane, Phys. Rev. Lett. 77, 793 (1996) and Proc. R. Soc. A 452, 2551 (1996). A verifier should: (1) confirm the symplectic rule reduces to HXHZT=0H_X H_Z^{T}=0 and that this equals C2⊆C1C_2\subseteq C_1 via (C1⊥)⊥=C1(C_1^{\perp})^{\perp}=C_1; (2) recompute HHT=0(mod2)HH^{T}=0\pmod 2 for the [7,4,3][7,4,3] Hamming matrix from the explicit row weights (44) and overlaps (22), giving the [[7,1,3]][[7,1,3]] Steane code with k=k1−k2=4−3=1k=k_1-k_2=4-3=1; (3) verify k=k1−k2k=k_1-k_2 from Lagrange's theorem on C2≤C1C_2\le C_1 and d≥min⁡(d(C1),d(C2⊥))d\ge\min(d(C_1),d(C_2^{\perp})) from the coset representatives of the logicals; (4) check the toric-code counts n=2L2n=2L^2, k=2k=2, d=Ld=L, giving [[18,2,3]][[18,2,3]] at L=3L=3. The below-threshold surface-code result is the Google Quantum AI Nature 2024 demonstration; the good-quantum-LDPC constructions are Panteleev–Kalachev (2022) and Leverrier–Zémor (2022).

Builds on: Stabilizer Formalism · Pauli Group and Clifford Group · Discretization of Errors · Shor Nine-Qubit Code · Code Distance and Logical Operators. Leads to: Steane Seven-Qubit Code · Syndrome Measurement and Decoding · Quantum Hamming and Singleton Bounds.

Ask the tutor: hand me any two nested classical codes, or a lattice, and I will build the CSS code, verify HXHZT=0H_X H_Z^{T}=0, and read off its [[n,k,d]][[n,k,d]], logical operators, and transversal gate set.

What exactly makes a stabilizer code a CSS code?

A general stabilizer code is a set of commuting Pauli operators that may freely mix XX and ZZ on the same qubit. A CSS code is the special case in which the generators can be chosen so each is purely XX-type or purely ZZ-type. That single restriction is what lets you read the code off two classical binary codes, decode the XX and ZZ errors independently, and inherit the transversal CNOT. Not every stabilizer code is CSS — the five-qubit [[5,1,3]][[5,1,3]] code is not — but the most useful ones (Steane, surface, color, and good quantum LDPC codes) all are.

Why is it C₂ ⊆ C₁ and not the other way around?

The direction is fixed by which code guards which error. The parity checks of C1C_1 are the ZZ-stabilizers that detect bit-flip (XX) errors, so undetectable XX-errors are the words of C1C_1 and the logical XX operators are those not already stabilizers — the difference C1∖C2C_1\setminus C_2. For that to be well-defined, C2C_2 must sit inside C1C_1. The phase protection comes symmetrically from C2⊥C_2^{\perp}. Reverse the inclusion and the two check families stop commuting: you no longer have a stabilizer code at all.

Is the Steane code the smallest CSS code, or just the most famous?

It is the smallest distance-3 CSS code and the most famous, but not the smallest quantum code correcting one error. The [[5,1,3]][[5,1,3]] perfect code reaches distance 33 on five qubits, but it is not CSS — its stabilizers mix XX and ZZ, so it lacks the clean separation and the transversal Hadamard. The Steane code pays two extra qubits for that separation and is rewarded with a full transversal Clifford group and independent X/ZX/Z decoding — the simplest code where fault-tolerant Clifford gates are essentially free.

Why can't a CSS code have a transversal T gate?

Transversal gates are limited to the Clifford group: the Eastin–Knill theorem forbids any code from having a transversal universal gate set, and the transversal logicals respecting the XX/ZZ split of a CSS code are Clifford. The TT gate is the non-Clifford gate that, added to {H,S,CNOT}\{H,S,\mathrm{CNOT}\}, makes the set universal, so it cannot be transversal on the Steane or surface codes. The workaround is magic-state distillation — purifying noisy TT-eigenstates with Clifford operations, then consuming a clean one to apply TT — and the distillation circuits are themselves CSS codes.

How are surface codes CSS codes?

The surface code puts a qubit on every edge of a two-dimensional lattice. Its stabilizers are the star operators (a product of Pauli-XX around each vertex) and the plaquette operators (a product of Pauli-ZZ around each face). Because the stars are purely XX-type and the plaquettes purely ZZ-type, the stabilizer group has exactly the CSS split, and the commutation HXHZT=0H_X H_Z^{T}=0 is the topological identity ∂1∂2=0\partial_1\partial_2=0. This is why surface codes decode XX and ZZ errors with two independent matching algorithms, and why the whole CSS language transfers — with logical operators appearing as non-contractible loops.

Does the distance bound d ≥ min(d(C₁), d(C₂⊥)) ever fail to be tight?

Yes, and usefully so. The bound is a floor, and degenerate CSS codes routinely beat it. Degeneracy means distinct errors share a syndrome and act identically on the code space, so many low-weight errors are harmless because they differ only by a stabilizer. The surface code is the standard example: its classical distances are modest, yet its true quantum distance equals the shortest non-contractible loop and its threshold is far higher than the raw bound suggests. Computing the real distance means searching over logical operators dressed by all stabilizers.

Why build a quantum code out of classical codes at all?

Because it reuses a century of classical coding theory instead of reinventing it. Classical linear codes come with parity-check matrices, dual codes, distance bounds, and fast decoders (belief propagation, minimum-weight matching), and CSS imports all of them wholesale: known classical distances bound the quantum distance, known decoders decode the two error types, and known asymptotic families (Gilbert–Varshamov, expander LDPC) yield good quantum codes. Designing commuting Pauli stabilizers from scratch throws that away. CSS is the bridge that makes quantum error correction an application of classical coding.

Before this

Where this leads