Ante Rebic's eighth Serie A goal of 2020 and a late penalty from Hakan Calhanoglu dented Roma's top-four hopes as Milan claimed a 2-0 Serie A win at San Siro.
The Giallorossi were seeking four successive top-flight victories for the first time all season but hot and humid conditions in Milan seemed to sap them of any creativity.
Edin Dzeko missed with a close-range header in the first half and the contest was heading for a dour draw until Rebic popped up with the opening goal 14 minutes from time to continue his fine form since the turn of the year.
Theo Hernandez was then tripped in the box by Chris Smalling with two minutes to go, allowing Calhanoglu to make sure of the points with an emphatic penalty.
Both sides were slow to get going but it was Roma who eventually seized some sort of control.
Dzeko really should have scored with a header when unmarked six yards out but he could only flick Justin Kluivert's deflected cross wide.
It was a similar story at the other end when Calhanoglu nodded off target from Hernandez's delivery, with the presence of Antonio Mirante possibly putting the Milan man off.
Milan failed to register a single shot on target in the first half but they twice worked Mirante in quick succession midway through the second period following the introduction of Lucas Paqueta and Alexis Saelemaekers from the bench.
Calhanoglu got behind the Roma defence via a one-two with Saelemaekers but Mirante denied the Turkish midfielder with his legs before pushing away an effort from Paqueta.
A Milan goal did eventually come, though, after Davide Zappacosta gave the ball away to Rebic in his own half.
Mirante saved from Franck Kessie and then diverted Rebic's first attempt onto the post but the in-form forward rifled the rebound into the roof of the net.
Hernandez's driving run then paid off when he reached the ball before Smalling, and Calhanoglu converted his penalty to give Milan breathing space.