Sri Lankan left-arm spinner Lasith Embuldeniya claimed a five-wicket haul on his debut and sparked a South African collapse on the third day of the first Test on Friday.
Embuldeniya, 22, took five for 66 as South Africa were bowled out for 259 in their second innings, leaving Sri Lanka to get 304 to take a 1-0 lead in the two-match series.
Opening batsmen Dimuth Karunaratne and Lahiru Thirimanne reduced the target to 276 by adding 28 without loss by tea.
South Africa were on course to set the tourists a more challenging target when they reached 251 for five, with captain Faf du Plessis and Vernon Philander looking solid in a sixth wicket partnership of 60.
But Embuldeniya, who bowled with impressive control, bowled Philander to start a collapse in which the last five wickets fell for eight runs.
Left-arm swing bowler Vishwa Fernando dismissed Du Plessis for 90 three overs later and the rest of the batting crumbled.
Fernando took four for 71 to follow up a career-best four for 62 in the first innings.
Du Plessis played a solid innings, facing 182 balls and hitting 11 fours before he padded up to a ball from Fernando which swung in and trapped him palpably in front of his stumps.
Du Plessis and Quinton de Kock (55) put on 96 for the fifth wicket. De Kock was in sparkling form in a 62-ball innings before he went back on his stumps to Embuldeniya and was leg before to a ball which spun in to the left-hander and kept low.
South Africa 235 and 259 (F du Plessis 90, Q. de Kock 55; V. Fernando 4-71, L Embuldeniya 5-66) Sri Lanka 191 and 28-0