Ivan Rakitic opened the scoring in the 20th minute and Neymar added a penalty in the 41st, after the referee had sent off the Villarreal coach, Marcelino García, for protesting.
But fourth-placed Villarreal rallied with a goal from the forward Cédric Bakambu in the 57th minute before the Barcelona substitute Jérémy Mathieu knocked in an own-goal in the 63rd.
Barcelona’s 12-match winning streak ended a day after second-placed Atlético Madrid stumbled in a 2-1 defeat at Sporting Gijon.
Barcelona extended their Spanish record unbeaten streak to 39 consecutive games in all competitions as, with eight games left, they begin the run-in to maintaining the domestic crown. Next weekend Luis Enrique’s side host Real Madrid, who trail the pacesetters by 13 points, before hosting Sevilla.
As promised, the match between two of the most attractive attacking squads produced an entertaining contest from start to finish.
Bakambu was particularly inspired. He caused the Barcelona centre-back Gerard Piqué, and replacement Mathieu, problems until he was substituted due to an apparent leg problem in the second half.
Less than a minute into the match, Bakambu’s pass hit his team-mate Manuel Trigueros, deflected off Barcelona’s Arda Turan, and reached the post before the goalkeeper Claudio Bravo smothered it.
Bravo saved a shot by Bakambu as the hosts dictated the pace until Rakitic swayed the match in Barcelona’s favor.
The Croatia midfielder fired a ball through a packed area that had fallen to him when the Villarreal defender Victor Ruiz disrupted a free-kick by Lionel Messi destined for Luis Suárez.
García was ejected in the 24th and spent the rest of the match from a private box apparently for protesting against a handball by Piqué that went unpunished. Piqué had already been booked for a handball to stop a Villarreal counterattack.
Bakambu came within inches of reaching a cross that ran across the goalmouth but Barcelona struck a second time after Messi threaded a pass forward to meet Neymar’s run.
The goalkeeper Sergio Asenjo brought down the Brazil striker, colliding with his left leg just before he could paw the ball away. Neymar then waited until Asenjo leaned one way before floating his spot kick into the other side of the net for his 21st league goal and 27th in all competitions this season.
But far from fading, Villarreal recovered all of their verve from the start of the match after half-time and Bakambu finally got his goal when he slotted in a ball that Bravo had parried from a shot by Denis Suárez.
Villarreal almost scored again seconds later but Javier Mascherano intercepted Bakambu’s pass for the unmarked Roberto Soldado.
Neymar almost quashed the host’s rally when he drew an excellent save from Asenjo in the 60th minute but Villarreal quickly levelled the score when a corner kick hit Mathieu and fell into the net.
Both sides had their chances to claim a winning goal. Rakitic’s header was turned away by Asenjo in the 71st, while Javier Mascherano was again critical to stopping Adrián López from streaking toward Bravo’s goal in stoppage time.