Elgar made 129 before falling to the second new ball. South Africa were 297 for six at the close after being sent in to bat.
The left-handed Elgar batted imperturbably while wickets fell at the other end, with Sri Lanka's seam bowlers taking advantage of a well-grassed pitch and overcast sky.
Stephen Cook, man of the match in South Africa's 206-run win in the first Test in Port Elizabeth, was out to the fourth ball of the match before a run had been scored.
Two more wickets fell to teenage fast bowler Lahiru Kumara with the total on 66 and South Africa were still struggling at 169 for five when Elgar was joined by Quinton de Kock.
Elgar and De Kock shared a 103-run partnership for the sixth wicket. With the sun coming out during the afternoon, South Africa were getting on top when Elgar pushed at a ball from Suranga Lakmal and was caught behind.
It was a rare false stroke in a 230-ball innings which included 15 fours. It was Elgar's sixth Test century and two runs better than his previous highest Test score, made against Australia in Perth in November.
De Kock was unbeaten on 68 at the close. On 41, he reached 1000 Test runs in 23 innings. Only four South Africans, led by former captain Graeme Smith on 17, have reached four figures in fewer innings.
Kumara, 19, who replaced Dushmantha Chameera in one of two changes from the side that lost in Port Elizabeth, took three for 86 and bowled with pace and aggression.
Playing in only his third Test and sixth first-class game, it was the first time he had taken more than two wickets in an innings at first-class level.
His first victim was Hashim Amla, bowled between bat and pad by an in-swinger for 29. Five balls later JP Duminy gloved a legside catch to a diving wicketkeeper Kusal Mendis. Later he had Temba Bavuma caught at deep square leg.
Sri Lanka were hampered in mid-afternoon when opening bowler Nuwan Pradeep left the field with an apparent muscle injury and was unable to take the second new ball.