JP Duminy's unbeaten century guided South Africa to their second highest total in Sri Lanka as the visitors posted 455 on day two in Galle.
Shortly after Duminy sealed his well-deserved 100, South Africa declared with one wicket to spare forcing their opponents to face 12 overs at the crease before stumps.
Sri Lanka's openers came through the final session unscathed, however, to end a gruelling day 30 without loss.
On a dry and dusty pitch, South Africa resumed on 268 for five thanks in part to Dean Elgar's 103 on the opening day, but needed to stabilise after losing a flurry of wickets the previous evening.
Nightwatchman Dale Steyn and Quinton de Kock continued at the crease but the former's resistance was ended after he was bowled for three by Suranga Lakmal (three for 75).
Lakmal almost had De Kock too as the South Africa number six twice edged through the slips.
De Kock went on to make an important 51 alongside the incoming Duminy, but shortly after his half-century he nicked Dilruwan Perera into the hands of Mahela Jayawardene to leave the visitors 314 for seven.
Sri Lanka were in the ascendancy and it took new batsman Vernon Philander 25 balls to get off the mark before lunch.
The afternoon session gradually turned in South Africa's favour, however, as Duminy took charge with some excellent sweep-play against Perera (four for 162).
Philander made 27 before being caught lbw by Angelo Mathews (one for 36) but South Africa had hauled themselves into a healthier position at 389 for eight.
While Duminy kept the scoreboard ticking at one end, Morne Morkel held firm at the other, allowing his partner to sweep a single and seal his century after 206 deliveries faced.
Sri Lanka took the third new ball and finally dislodged Morkel (22), who was bowled by Perera, prompting South Africa to declare at 455 for nine.
After a long day in the field, Sri Lanka's Kaushal Silva (eight not out) and Upul Tharanga (20 no) did well to see out the rest of the day unbeaten as the hosts trailed by 420 at the close.