The number one-ranked bowler in Test cricket finished with figures of five for 56 in the second innings, and Imran Tahir's three for 63 saw the tourists take a 1-0 lead in the three-match series.
England fought to survive for much of the day, losing just one wicket in the morning session, but once Ian Bell fell for a 220-ball knock worth 55 runs, the writing was on the wall.
The tail fell cheaply as Steyn attacked with the second new ball: 203 for five became 240 all out, condemning England to their first defeat by an innings on home soil in three years.
It was not England's worst day of the Test, but the damage had already been done earlier in the game: their failure to convert a solid first day's batting into a major score, their toothlessness with the ball and the cheap dismissals of the top order on day four were all bigger errors.
Bell and Ravi Bopara set about their task of batting out 90 overs positively - Bell stout in defence, Bopara more attacking.
Bopara, under fire after a duck on his return to the Test team, fell for 22 to an ugly chop on to his stumps chasing a wider delivery from Steyn. The manner of his dismissal will do little to quieten critics of his selection.
Matt Prior proved a useful foil to Bell, however, with his positive play complementing Bell's resolution.
South Africa came close to prising out the Warwickshire man, but the faint edge he got to a superb ball from Tahir was not snaffled by AB de Villiers behind the stumps.
The pair saw England through to lunch, Bell crashing a boundary away on the final ball before the interval, and the batsmen continued their form afterwards.
Bell brought up his half-century, and Prior was nearing his, as South Africa began to hope for a fresh lease of life when the second new ball became available after 80 overs.
But they got a timely boost just before that became available as Prior swept at Tahir and an edge behind was grabbed at slip by Jacques Kallis.
Steyn needed just two deliveries with the new ball before ending Bell's resistance with an edge, while in his next over he got another, with Stuart Broad gloving a ball down the leg side behind to de Villiers.
Swann brought up his 1000th run in Test cricket with an uppish drive for four, but playing the same shot in the next over, he picked out Alviro Petersen at cover.
Tim Bresnan and James Anderson fought on for 10 more overs with the game long gone, before Anderson was undone by a ball from Tahir which scuttled low and trapped him plumb in front of the stumps.
It was an ugly end to an ugly Test for the hosts, whose status as the world's best five-day side is now very much under threat from the impressive Proteas.