Paco Alcacer took the place of suspended striker Luis Suarez in the starting line-up and scored a first goal in three months to put Barca ahead in the eighth minute at the Nou Camp, side-footing home a pass from Jordi Alba.
Lionel Messi scored for the sixth game in a row in all competitions and for the 25th time in this league campaign when he doubled Barca’s lead in the 30th minute with a deadly strike into the bottom corner from the edge of the area.
Atletico forward Antoine Griezmann won and converted a penalty to put his side ahead at Villarreal in the 20th minute.
However, Turkey striker Enes Unal headed in a deserved equaliser in the 82nd and then struck the winner from close range in stoppage time. The visitors had forward Vitolo sent off moments later for pushing Villarreal forward Nicola Sansone.
Barca lead the standings on 75 points with nine games remaining. Atletico are second with 64, while Villarreal climbed above Sevilla into fifth in the standings after Vincenzo Montella’s side were beaten 2-1 at Leganes. Champions Real Madrid were in action at home to Girona later on Sunday.
The Catalans were rampant in the first half and could have taken a heavier lead into the break as Brazilian midfielder Philippe Coutinho hit the woodwork twice and his compatriot Paulinho struck a post.
The unbeaten league leaders slowed down in the second half and Athletic came into the game for the first time but they rarely came close to troubling goalkeeper Marc-Andre ter Stegen.
“We scored twice in the first half and could have really finished them off, then in the second half we took our foot off the pedal without realising,” Barca coach Ernesto Valverde told a news conference.
“The two halves were very different, perhaps conditioned by the first. There weren’t many chances in the second half, for us or them.”
Atletico have not managed to beat Villarreal at home or away since April 2015 and were fortunate to take the lead from the spot after Griezmann appeared to go down easily following a challenge from Jaume Costa.
Villarreal’s players had surrounded referee David Fernandez Borbalan after that decision and vented their fury at him again in the second half when he refused to award them a penalty when Carlos Bacca went down in the area.
The home side kept on pushing for an equaliser and Atletico coach Diego Simeone sacrificed Griezmann for captain Gabi with 10 minutes remaining to try and protect the lead but his side ended up losing the game due to slack defending.
“There’s no explanation for what happened, we didn’t defend well from the two set pieces and next time we need to be more focused,” said Atletico midfielder Saul Niguez.
“I have the sensation that I lost us the game,” added Simeone.
“The players made a huge effort and I couldn’t help them with my decisions.”
Earlier, Sevilla suffered a hangover from their Champions League triumph over Manchester United as they lost 2-1 at mid-table Leganes, their sixth defeat in 12 league games under Italian coach Montella.