An early own goal set the visitors on their way but they were quickly pegged back when Gerard Moreno equalised.
Luis Suarez then restored their lead with a brilliant finish before Antoine Griezmann went one better with a cheeky dink to make it 3-1.
Substitute Ansu Fati added Barcelona’s fourth late on to seal all three points for the visitors.
Barcelona got off to the perfect start when Pau Torres put past his own goalkeeper from close range after just three minutes. It looked initially as though Griezmann had got the goal, but replays showed it was Torres who got the final touch.
Yet once again Barca failed to hold on to their lead and were caught out with another quick break. Santi Cazorla’s shot was parried into Moreno’s path by Marc-Andre ter Stegen, and the Villarreal striker made no mistake from close range.
It looked like being another tough away match for Barca at that point, but they turned on the style with two brilliant goals. The first was a stunning effort from Suarez that flew into the top corner from the edge of the penalty area after a great piece of play by Messi.
The captain then set up Griezmann for the third just before half-time. Messi came up with a little backheel for the Frenchman to latch on to and dink a brilliant chip past Sergio Asenjo and in off the crossbar.
After a thrilling first half the second 45 minutes was a lot quieter, although Barcelona did think they’d added a fourth when Messi found the back of the net.
Sergi Roberto burst into the penalty area and cut the ball back for the captain to pass home, but a VAR check decided Arturo Vidal was offside and it was ruled out.
Quique Setien did remember he was allowed to make changes in the second half which made for a nice change. Suarez and Nelson Semedo came off after an hour for Riqui Puig and Ivan Rakitic.
Ansu Fati and Martin Braithwaite also arrived 10 minutes later to give Sergio Busquets and Griezmann a breather, while there was even time for Ronald Araujo to get some minutes late on.
Jordi Alba set up Fati for Barcelona’s fourth in the closing minutes of the game. The left-back pinged the ball up the flank for the youngster to latch on to and then produce a clever finish.
Villarreal: Asenjo; Mario, Albiol, Torres, Moreno; Chukwueze, Anguissa, Iborra (Bruno), Cazorla (Trigueros); Gerard (Gomez), Alcácer (Bacca) (Nino)
Goals: Moreno (14’)
Barcelona: Ter Stegen; Semedo (Rakitic), Piqué (Araujo), Lenglet, Alba; Vidal, Busquets (Braithwaite), Roberto; Messi; Griezmann (Fati), Suárez (Puig)
Goals: Torres (3’ OG), Suarez (20’), Griezmann (45’), Fati (86’)