Jacques Kallis was on 78 with Shaun Pollock on 1.
Opener AB de Villiers was the first man out bowled by Chaminda Vaas for 0 in the first over.
But captain Graeme Smith then cut loose making 59 from 69 balls with seven fours and one six before he was stumped by Kumar Sangakkara in the 18th over off the bowling of Muttiah Muralitharan.
The spinner then rocked South Africa by capturing two wickets in two balls to dismiss Herschelle Gibbs caught and bowled for 31 in the 33rd over with the score at 160.
Muralitharan then had Mark Boucher lbw the next ball but Justin Kemp kept out the hat-trick ball.
Kemp didn't last much longer, however, when he was stumped by Sangakkara off Sanath Jayasuriya for 5 in the 38th over.
Earlier, Charl Langeveldt claimed five wickets as Sri Lanka limped to 209 all out.
Tillekeratne Dilshan (58) and Russel Arnold (50) were mainly responsible for Sri Lanka's total, putting on 97 for the sixth wicket after their side slumped to 98 for five.
South Africa, needing a win to get their campaign back on track after losing against Australia in St Kitts Saturday, brought in left-arm spin bowler Robin Peterson in place of batsman Ashwell Prince.
Seam bowler Farveez Maharoof returned for Sri Lanka in place of Dilhara Fernando.
Sri Lanka already have two Super Eight points following a win over fellow group qualifiers Bangladesh.
Fall of wickets: 1-13 (Tharanga), 2-45 (Jayasuriya), 3-65 (Jayawardene), 4-90 (Sangakkara), 5-98 (Silva), 6-195 (Dilshan), 7-208 (Arnold), 8-208 (Maharoof), 9-208 (Vaas)
South Africa: G Smith, A de Villiers, J Kallis, H Gibbs, M Boucher, J Kemp, S Pollock, R Peterson, A Hall, C Langeveldt, M Ntini.
Umpires: Steve Bucknor (WIS) and Daryl Harper (AUS).
TV umpire: Mark Benson (ENG). Fourth umpire: Simon Taufel (AUS). Match referee: Jeff Crowe (NZL).