The elegant left-hander hit eight fours in his 90-ball 72 to take Sri Lanka to 203-6 at tea for an overall lead of 342 runs.
Skipper Angelo Mathews was batting on 48 with Niroshan Dickwella being dismissed for 16 just before the break.
Sri Lanka had scored 421 in their first innings before bowling out the Proteas for 282 to take a 139-run first innings lead.
The Sri Lankan batsmen started off confidently after rain interrupted play for an hour.
Also Read
Just when he was looking good for a bigger score, he edged to wicketkeeper Quinton de Kock off Morne Morkel (3-38), bringing an end to his enterprising knock.
Kithruwan Vithanage (seven) was superbly caught by Faf du Plessis who ran backwards without taking his eyes off the ball and then dived forward to pluck the ball inches off the ground.
Test debutant Dickwella, who scored a fine 72 in the first innings, top-edged to AB de Villiers off Dale Steyn (2-49) after hitting two fours in his 21-ball effort.
Earlier, Sri Lanka added a healthy 97 runs in the first session while losing their openers and the prolific Mahela Jayawardene.
Opener Upul Tharanga (30) looked in good nick but he edged behind to the keeper while trying to drive Steyn in the sixth over of the morning.
Kaushal Silva welcomed Tahir (1-67) with a neat sweep to the fence in the bowler's first over, setting the tone for the rest of the session that saw the hosts score at a quick pace.
Jayawardene, who cracked a solid 165 in the first innings, was out for a duck in a bizarre fashion off Tahir.
The stylish right-hander played the reverse sweep but the ball popped up and Dean Elgar rushed across from short leg to pouch the ball before crashing into de Kock.