A goal from Renato Augusto eight minutes from time earned Jupp Heynckes' side all three points and gave them a glimmer of hope of catching Dortmund with eight matches of the season remaining.
Mainz slipped to fifth following their latest defeat at the Bruchweg Stadion to sit only one point ahead of Nurnberg in the race for the last berth in the Europa League next season.
Heynckes sprang a surprise in his team selection, recalling Michael Ballack after the former Chelsea man had missed the last two games amid rumours of a rift between the pair.
Stefan Kiessling was also restored to the Leverkusen attack as Heynckes rang the changes following Thursday's 3-2 defeat to Villarreal in the Europa League.
His side started brightly, showing no signs of tiredness after their midweek exertions.
Mainz were also energetic, though, with Andre Schurrle repeatedly causing problems to the Leverkusen defence early on.
The deadlock was almost broken in the 35th minute when a speculative effort from Daniel Schwaab beat Mainz goalkeeper Christian Wetklo only to come back off the post.
Schwaab threatened again with a free-kick which was headed towards goal by Lars Bender, but Wetklo tipped his effort over the bar.
Leverkusen were slowly asserting their superiority and Kiessling had the chance to put them in front in the 65th minute, but, with only Wetklo to beat, he placed his shot straight into the keeper's arms.
The game seemed to be heading for a draw until Bo Svensson was robbed of possession by Augusto in the 82nd minute.
The Brazilian looked up and spotted Wetklo off his line and beat him with a powerful shot from 20 yards into the top left-hand corner to earn Leverkusen the points.