Broad took six for 17 as South Africa were bowled out for 83 in their second innings. England won by seven wickets to take a winning 2-0 lead into the final Test in Centurion next week.
Broad ripped the heart out of the South African batting, taking the first five wickets for one run in the space of 31 balls after lunch.
The defeat toppled South Africa from top spot on the International Cricket Council's Test rankings. England led on the first innings by 10 runs after being bowled out for 323 and the match was evenly poised as South African opening batsmen Dean Elgar and Stiaan van Zyl put on 23 runs at the start of the second innings, with Broad having conceded 13 of the runs.
Van Zyl was caught at gully. South African captain AB de Villiers came out to a roar of appreciation from a near-capacity crowd but was caught behind for nought off a delivery which cut back sharply to take an inside edge.
More From This Section
Kagiso Rabada made a quick 16 before he was caught behind off Stokes. Eight wickets fell for 55 runs between lunch and tea. The last two wickets fell quickly after tea. James Anderson took only his second wicket of the match when he had Hardus Viljoen leg before wicket and Broad dived full length down the pitch to take a return catch from Faf du Plessis.
Cook made 43, his highest score of the series, but was caught behind off Morris with three runs needed.
Earlier Rabada claimed a maiden five-wicket haul to restrict England's first inning lead to 10 runs. Rabada, 20, playing in his fifth Test match, took five for 78 and led the Souh African attack, bowling at pace with consistent control.