South Africa won the second Test by 231 runs to level their three-Test series against Australia at 1-1.
- Related Content
Hashim Amla pushed on from 93 overnight to 127 not out before the Proteas declared on 270 for five to set Australia a target of 448.
Openers Chris Rogers and David Warner put on 126 but remarkably, all 10 wickets then fell for 90 as South Africa avoided a nervous final day, with heavy rain forecast in Port Elizabeth.
Amla's century came up when he guided Ryan Harris behind point for four, his 14th boundary from 139 balls.
His partnership with Test debutant Quinten de Kock reached 64 before the latter, on 34, was caught by Michael Clarke off Nathan Lyon.
Amla and JP Duminy hit boundaries in the same Peter Siddle over and after Duminy (18no) added another in the paceman's next over, Graeme Smith called his players in.
Rogers and Warner, far from merely surviving the 33 minutes before lunch, scored at virtually four an over to reach 33 without loss.
Warner took the tourists to 50 with four successive fours off Morne Morkel but had a let-off when Duminy was unable to hold a return catch after colliding with non-striker Rogers.
Warner needed only 61 balls to advance to 50, doing so with a three off Steyn aided by an overthrow and having hit six fours and a six.
The century partnership came up from the first ball of the next over, the 25th and Rogers brought up his half-century with a boundary off Morkel, who responded by ripping a ball past his edge later in the over.
With the score at 126 without loss, Proteas wicketkeeper AB de Villiers was heard on the stump microphone shouting "150 for four here boys" - and it was to prove prophetic.
Duminy immediately returned for a second spell and trapped Warner lbw for 66 with his second ball, the batsman unsuccessful with a review.
Australia were 141 for one at tea but Alex Doolan's painstaking innings of five was finally ended after 43 balls when he edged Morkel to Graeme Smith at first slip.
Vernon Philander added the scalp of Shaun Marsh, who followed his first-Test century with a pair, and Steyn ripped out Clarke and Steve Smith in successive balls, the Australian captain edging low to Faf du Plessis in the slips before his team-mate was pinned lbw.
The hat-trick ball was harmless but at 156 for five, De Villers' prediction had been more than borne out.
Steyn produced a reverse inswinger to bowl Brad Haddin for one but South Africa failed with an optimistic lbw review against Rogers, the only remaining specialist batsman, when he was on 90.
Two boundaries off Dean Elgar then helped the opener to a deserved century from 192 balls, with 11 fours.
An lbw review against Johnson did pay dividends, Philander's delivery adjudged to be on line for leg stump, but Rogers survived with the help of DRS after De Villiers claimed a catch which replays showed he had knocked into the ground before taking.
Harris, though, could not overturn Steyn's lbw appeal, an 'umpire's call' verdict leaving Australia 209 for eight. Earlier in the over, Harris had chopped a ball into the ground and then, in trying to shepherd it away, almost contrived to edge it back onto his stumps.
Rogers' valiant innings finally ended at 107 when he was run out, substitute fielder Alviro Petersen's throw from mid-off just brushing the stumps and dislodging the bails slowly enough that several replays were needed.
And when Lyon was given lbw despite edging Elgar's delivery, with no reviews remaining, it was 216 all out and all over.
Steyn led the way with four for 55 while Johnson and Harris, amazingly, shared the innings' third-highest score on six.