South Africa captain Hashim Amla remained unbeaten after his 22nd Test hundred but off-spinner Dilruwan Perera's career best figures gave Sri Lanka a big first innings lead at the end of the third day of the second Test on Saturday.
South Africa were dismissed for 282 in reply to Sri Lanka's first innings total of 421. At stumps Sri Lanka were 11 without loss with Upul Tharanga on six and Kaushal Silva on five, with a lead of 150.
Amla put on a fine display of concentration and application as he fought hard to give his team a fighting chance of saving the Test and preserving their 1-0 lead in the two-match series.
The stylish right-hander, who resumed on 46 on Saturday, batted through the South Africa innings to remain not out on 139, having batted for eight hours during which he faced 382 balls and hit 12 fours.
Amla was the only South African batsman to come to terms with the slow turning pitch as Sri Lankan spinners Perera and Rangana Herath proved a handful for the rest of them.
Sri Lanka's attempt to finish off the South African innings quickly was not helped by wicketkeeper Niroshan Dickwella's missed stumping of Steyn on 19 when the batsman jumped out against Herath and missed the ball.
Steyn was eventually dismissed for 30 but by then he had eaten up valuable time which Sri Lanka can ill-afford if they are to win the Test and draw the series.
Herath took Steyn's wicket when the batsman holed out to Kumar Sangakkara at long off after spending 75 minutes and 71 balls in the middle.
The left-arm spinner also accounted for Imran Tahir (15) having him caught at wide mid-off to finish with figures of four for 71.
Perera, who had been tormenting the batsmen with his guile and flight, picked up his second five-wicket haul of his career when he had Mornie Morkel caught at forward short leg for a duck to end the South African innings.
Amla, in his second Test as captain, survived a dropped catch by Kaushal Silva at extra cover, seven runs short of his century when he drove Suranga Lakmal in the air.
Perera also bowled Vernon Philander through the gate for nine. JP Duminy, who took 58 balls to score his three runs before being drawn outside his crease by Herath, was out stumped.
South Africa appeared intent on occupying the crease for as long as possible and Amla was helping them do just that with the second session producing just 71 in 29 overs.
In the morning, Perera struck twice in one over to dent South Africa's hopes of getting close to Sri Lanka's first innings total.
South Africa, who resumed on 98-3, went to lunch on 163 for five with a defiant Amla holding up one end as his team-mates struggled to cope with the home spin attack.
Overnight pair Amla and AB de Villiers took South Africa to 143-3 in the first hour of play, adding 45 fairly untroubled runs, with the former completing his 28th test fifty off 140 balls.
The only alarming moments of the day up to that point came when De Villiers was struck on the helmet by a short delivery from Lakmal and then survived an appeal for a catch behind off the same bowler when he was on 30.
TV replays confirmed the ball had bounced before it reached the wicketkeeper but the introduction of Perera in the 17th over of the day dramatically changed the momentum of the innings.
Perera struck twice in his 19th over by getting rid of De Villiers for 37 and the dangerous Quinton de Kock for a duck.
Perera was able to make one turn appreciably to beat De Villiers' bat and crash onto his pads, leading the umpire to raise his finger immediately with the decision upheld following an unsuccessful review by the visitors.
De Villiers' dismissal ended a stubborn fourth-wicket partnership of 79 with Amla but De Kock lasted just two balls before he was beaten by the flight and clean bowled as Perera.