Dhananjaya de Silva enhanced his rapidly-growing reputation with an unbeaten 43 as he kept South Africa's strike bowlers at bay to see Sri Lanka to 181 for seven in their first innings at the end of the second day of the first test.
The 25-year-old, who hit a six with his first scoring shot when he made his test debut against Australia in July, brought Sri Lanka within 105 runs of South Africa's first innings total of 286 before bad light stopped play for the day.
Sri Lanka had been in serious trouble at 21 for three as their top order was decimated but De Silva's knock and 39 from captain Angelo Matthews stemmed a possible collapse.
Eleven wickets fell on a day when a bowler-friendly track proved something of a nightmare for batsmen.
Suranga Lakmal claimed career-best figures to help dismiss South Africa in the first hour, completing his first test match five-wicket haul and finishing with 5-63 as the home side added just 19 runs to their overnight total of 267-6.
South Africa's hopes of significantly adding to their score quickly faded as Vernon Philander was dismissed and followed back to the pavilion by Keshav Maharaj and Kyle Abbott, who each faced only three balls and failed to score.
Quintin De Kock was the last South African wicket to fall, out for 37.
South Africa then made quick inroads through the pace duo of Abbott and Philander to wrestle back control of the contest.
Dimuth Karunaratne was the first Sri Lankan dismissed, getting an inside edge to Abbott and playing onto his stumps to depart for five.
Kusal Perera went next for seven, caught behind by De Kock off Philander, and Kusal Mendis followed soon after without scoring as the wicketkeeper took another diving catch, this time off Abbott's bowling.
Sri Lanka lost Matthews and opener Kaushal Silva, who had seen three wickets go down before him, in the second session and after tea Dinesh Chandimal (28) was given out leg before wicket off a Philander delivery and Rangana Herath (24) similarly trapped by Maharaj.
Play will start 28 minutes earlier on Wednesday but rain is predicted for some part of the day.