Vettel had to settle for third place behind Red Bull’s Max Verstappen.
Hamilton and Vettel made the best starts of the top three and the pole-sitting Mercedes cut cleanly through the first two corners as second-placed Verstappen had to defend his position from Vettel.
Behind them, Sergio Perez nudged his Force India teammate Esteban Ocon into the outside wall at Turn 2, eliminating him from the race and bringing out the safety car.
But before race control took the decision to neutralise the race, Vettel had made use of a better exit from Turn 5 to draw alongside Verstappen and pass him on the outside into Turn 7.
In their wake, the majority of the top 10 got away in grid order – Valtteri Bottas in fourth followed by Kimi Raikkonen, Daniel Ricciardo, Perez and Romain Grosjean – but ultrasoft runners Fernando Alonso and Carlos Sainz each gained two positions on the opening lap, at the expense of Nico Hulkenberg and the absent Ocon.
The race got under way again on lap 4 but the frontrunners were running cautiously, nearly 11 seconds off qualifying pace, so as to manage their fragile hypersoft tyres and extend the first stint as far as possible.
As the lap count entered double figures, the frontrunners lifted their pace in anticipation of the pitstops. Vettel was the first to dive in, on lap 14, taking on a set of ultrasofts.
The stop would prove disastrous for Vettel, since he emerged behind Perez and spent two laps bottled up behind him.
Hamilton and Verstappen pitted on successive laps to take on soft Pirellis with a clear strategy of running to the end with no further stops.
Hamilton returned seamlessly into the net lead, and although Verstappen’s engine stuttered slightly as he left the pit apron, he just squeaked ahead of Vettel into Turn 2.
The initial pitstop phase left Hamilton with a 3s lead over Verstappen once Ricciardo became the last of the frontrunners to change tyres, on lap 27. Vettel was a frustrated third, telling his team: “We were again too late. We will not make it to the end.”
As at the Monaco Grand Prix, drivers starting outside the top 10 with a free tyre choice benefitted as some of those ahead on softer rubber pitted first.
Conversely, when Perez, Hulkenberg and Grosjean shed their hypersoft boots they emerged behind the trundling tail-end Williams pairing of Lance Stroll and Sergey Sirotkin, who had started on soft tyres and had no plans to stop promptly.
This prompted the race’s second significant incident when Perez grew impatient with Sirotkin and swerved at him as he finally went past at Turn 17 on lap 33, picking up a puncture in the process and enabling Hulkenberg to nip through.
As Grosjean tried to follow Hulkenberg through the pair baulked Hamilton as he came up to lap them, briefly enabling Verstappen to enter attacking range.
Once clear, though, Hamilton stretched his margin out to 3s again and remained out of reach until the chequered flag, eventually finishing 8.9s clear – with Vettel a further 30.9s down the road.
While Hamilton, Verstappen, Vettel and Bottas nursed their tyres to the finish, a battle for fourth place erupted in the closing laps as Ricciardo closed in on and challenged Raikkonen, who in turn crept up on Bottas. But nothing came of it and Bottas crossed the line 1s clear.
Alonso won ‘class B’ for McLaren from 11th on the grid, taking advantage of a long first stint on the ultrasofts to gain track position at the expense of Perez and Grosjean, and then undercutting Sainz for seventh place when he made his single stop on lap 38.
Charles Leclerc, another driver to start outside the top 10 on ultrasofts, followed Sainz home in ninth place, while Hulkenberg completed a solid recovery drive to round out the top 10 after losing track position on the opening lap.
That this was very much a tyre-management grand prix was emphasised by Kevin Magnussen setting the fastest lap, a new lap record, while running in 18th place.