Lionel Messi opened the scoring from Luis Suarez’s cutback four minutes before the break, but Villarreal levelled shortly after half-time when Marc-Andre Ter Stegen failed to keep out Manu Trigueros’s drive.
However, Barca were back in front within a minute through Andres Iniesta and Gerard Pique’s header 26 minutes from time made it 3-1.
The Catalans could have had an even healthier advantage to take into the second leg on March 4, but Neymar had his penalty saved by Sergio Asenjo.
“I think it was a very good performance on our part against an opponent that was more defensive than we expected, but against a very good team. It is a good result, although it isn’t definitive,” said Barca boss Luis Enrique.
“It could have been even better with the penalty we missed, but it is a good result and deserved based on what we saw on the pitch.”
Villarreal coach Marcelino meanwhile described his side’s evening like a “horror film” having not only lost the match but captain Bruno and former Barca midfielder Jonathan dos Santos to injury.
“This game seemed lke a horror film. Barcelona took advantage of our mistakes and scored the type of goals we didn’t expect.
“We have two injuries, one of which could be serious. I am sad for all these combined circumstances that mean we are much further away from reaching the final.”
All of Villarreal’s good defensive work in the opening 45 minutes was undone four minutes before half-time when Mateo Musacchio slipped to allow Suarez to rob possession and he squared for Messi to slot home his 11th goal in his last nine games.
The roles were reversed a minute later as this time Messi freed Suarez inside the box, but the Uruguayan drove his low shot beyond the far post.
For all their dominance, Barca nearly went in at the break level as Villarreal’s only threatening counter-attack of the half ended with Ter Stegen making a fine save to turn Luciano Vietto’s shot behind.
However, the young German goalkeeper was very much at fault when Villarreal did equalise just three minutes after half-time when he failed to keep out Trigueros’s thunderbolt from outside the area.
The visitors were only on level terms for a minute as Suarez again created the danger when he claimed to have been fouled inside the area by Mario Gaspar and Iniesta swept the loose ball into the far corner.
Another defensive error allowed Barca to extend their lead when Musacchio and Asenjo were caught flat-footed by Messi’s corner and Pique headed home unmarked at the far post.
Musacchio was also at fault seven minutes later when he handled as Messi tried to wriggle free inside the area.
The Argentinian had missed from the spot in the previous round against Atletico Madrid and handed the responsibility to Neymar, but he too failed from 12 yards as Asenjo made a comfortable save low to his right.
Suarez nearly rounded off the evening with a stunning effort from just inside the Villarreal half, but the ball floated just wide with Asenjo beaten.
Espanyol also moved closer to making it an all-Catalan final as they secured a vital away goal in a 1-1 draw away at Athletic Bilbao in the night’s other semi-final.
Aritz Aduriz put the hosts in front with a lovely chip on 11 minutes, but Espanyol levelled when Victor Sanchez volleyed home 10 minutes before half-time.
Espanyol could even have taken in a lead into the second leg when Victor Alvarez headed against the post five minutes from time.