The day started well enough for the tourists as they took South Africa's remaining four first-innings wickets for just 19 runs to dismiss the hosts for 286; Suranga Lakmal (5-63) claiming a first Test five-for.
But the tourists' top-order flopped, with three further wickets falling before lunch to make it seven for the session, in stark contrast to the six in total on day one.
Vernon Philander was the pick of the Proteas bowlers, taking 3-35, though greater application was shown by the Sri Lankan middle and lower order; Dhananjaya de Silva doggedly fighting through to 43 not out when play was ended 22 overs early due to bad light.
In the morning session, South Africa's final four wickets lasted all of 8.5 overs as they were bowled out for their lowest first innings Test total at St George's Park in nine years.
Philander (13) was the first to fall, caught at deep square-leg when top-edging a pull off Nuwan Pradeep (2-66).
Lakmal then claimed his five-for, in his 32nd Test, Keshav Maharaj edging behind for a duck, before Kyle Abbott was run out without scoring and Quinton de Kock (37) was bowled by a Pradeep yorker to end the innings.
However, Sri Lanka's reply got off to a terrible start as Dimuth Karunaratne (5), Kusal Perera (7) and Kusal Mendis (0) were dismissed inside the opening eight overs of their innings.
Karunaratne first inside-edged a Kyle Abbott (2-49) delivery onto his stumps, before Perera and Mendis both edged loose drives behind off Philander and Abbott, respectively.
Skipper Angelo Mathews (39) led the way after lunch, while Kaushal Silva (16) and Dinesh Chandimal (28) too tried to occupy time at the crease, though runs proved to be a struggle.
Philander ultimately accounted for both Silva and Chandimal lbw either side of tea, while Kagiso Rabada (1-63) had Mathews out, caught at third slip, sandwiched between those strikes.
But just as it looked like Sri Lanka might collapse to the close, De Silva battled on bravely, although he should have been caught by left-arm spinner Keshav Maharaj off his own bowling when on 27.
Maharaj (1-30) did at least pick up the scalp of Rangana Herath (24) lbw, after he missed an attempted reverse sweep.