Rising COVID cases deprived Milan of several key players ahead of their first game since the winter break, but the hosts started well, racing into 2-0 lead inside 17 minutes thanks to Olivier Giroud's penalty and a fine Junior Messias finish.
Roma coach Jose Mourinho, making his first return to the San Siro since he guided Inter to the treble in 2010, saw his side respond well, with striker Tammy Abraham getting the visitors back into the match five minutes before the break.
There were chances at both ends of an entertaining second half, before Milan's task became more manageable after Roma's Rick Karsdorp was sent off for a second booking in the 74th.
As the 10 men pressed for an equaliser, substitutes Zlatan Ibrahimovic and Rafael Leao combined to put the game to bed eight minutes from time, with the Brazilian arrowing home his side's third goal.
Roma went down to nine players when Gianluca Mancini was sent off in stoppage time when he conceded another penalty and although Ibrahimovic failed to convert from the spot, it mattered little as the hosts saw out the win.
Inter's clash at Bologna was abandoned earlier on Thursday due to the number of COVID-19 cases in the hosts' camp, allowing Milan to put pressure on the champions as they reached 45 points from 20 matches, while Roma are seventh on 32.
"We all worked hard for this win, me, the club and the coaches together with the players," Milan coach Stefano Pioli told DAZN. "It's a pleasure to coach these guys.
"They want to grow, learn even through the mistakes we made. We are down in numbers and in three days we play another important match."
Three Milan players tested positive for COVID-19 on Wednesday, adding to two already in isolation. As a result, Milan's backline looked especially depleted for Roma's visit.
All the early action, however, took place down the other end with Abraham penalised for handball, which was spotted by VAR, and gifting veteran Giroud the chance to open the scoring from the penalty spot and the Frenchman made no mistake.
Roma won three of their last four games in all competitions before the winter break but the visitors were poor early on, with a mistake from Roger Ibanez allowing Giroud in again after 17 minutes. Ibanez thought he had got away with it as Giroud hit the post, but the rebound fell to Messias, who made no mistake.
Nicolo Zaniolo and Abraham were denied by excellent saves from Milan's Mike Maignan as Roma finally found their feet, before former Chelsea striker Abraham made one count, diverting Lorenzo Pellegrini's strike home.
Karsdorp's dismissal effectively ended Roma's hopes of getting back into the match before Leao's fifth of the season, after Ibrahimovic's chested assist, put the icing on the cake.
Ibrahimovic then thought he was about to net his eighth league goal of the season from the spot after Mancini's foul on Leao, but Patricio superbly saved the Swede's penalty.