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 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 loss at Sporting Gijon.
Barcelona extended their Spanish record unbeaten streak to 39 consecutive games in all competitions as they begin the run-in to maintaining the domestic crown with eight games left. Next weekend Luis Enrique’s side host Real Madrid, who trail the pacesetters by 13 points, before hosting Sevilla later on Sunday.
“It was a very intense game against one of the best teams in the league which always presses even more in its stadium,” Rakitic said. “We have to be happy with the result, even if it hurts after being up two goals.”
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 center-back Gerard Pique, 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 host 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 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 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.
“This team never gives up,” Asenjo said. “At half-time we said ’let’s forget what has happened and play like it was 0-0’.”
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, 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.
A moment of silence was held before the match at El Madrigal for the victims of a bus accident in north-east Spain that left at least 13 dead.