The Rossoneri had an opportunity to forge ahead when Gianluca Lapadula was fouled in the box by Wojciech Szczesny. The goalkeeper, on loan from Arsenal, made up for the rash decision by diving to his left to save the effort from M’Baye Niang.
The two sides had begun level on 32 points but Roma’s win left them alone in second place, four points behind leaders Juventus who they visit on Saturday.
At the Stadio Olimpico in Rome, there were few clear-cut openings but Milan were gifted a chance to go in front when Gianluca Lapadula was clumsily tripped by Szczesny when the Milan forward was running into a dead end.
The Polish goalkeeper made up for his mistake by diving to his left to save Niang’s weak side-footed effort, producing the biggest cheer of the night from the home fans.
Roma were badly missing forward Mohamed Salah, who is out with an ankle injury, and looked unlikely to break through until Nainggolan conjured a goal out of nothing in the 62nd minute.
The heavily tattoed Belgian collected the ball near the touchline, was allowed to run unchecked towards the middle of the pitch and unleashed a curling left foot shot which flew past Gianluigi Donnarumma from the edge of the area.