The home side tried to get an early goal on the board when Pierre-Emerick Aubameyang blasted the ball towards goal after the visitors failed to clear a Henrikh Mkhitaryan corner, but his low strike was deflected wide.
It was Frankfurt who opened the scoring inside the opening 10 minutes through as Haris Seferovic raced through the middle before playing the ball forward to Alexander Meier, who managed to squeeze the ball in at the left post with a 20-yard curling finish.
Aubameyang thought that he had got Dortmund back on level terms three minutes later, getting the better of the keeper in a one-on-one, but the finish was chalked off for offside.
The home side did find an equaliser midway through the opening period though, with Aubameyang turning provider, squaring the ball to Mkhitaryan, who slotted the ball into an empty net.
Aubameyang had the ball in the back of the net again shortly before half time, converting from a Mkhitaryan corner, but once again the striker found his effort wiped off because of an offside in the build-up.
The visitors found themselves reduced to 10 men on the stroke of half time as Slobodan Medojevic received his second booking of the opening 45 minutes for a foul on Aubameyang in the penalty area, but the forward missed the target with the resulting spot kick.
With a man advantage, Dortmund continued to dominate possession at the start of the second half, but Lukas Hradecky denied Shinji Kagawa with a diving save, while Gonzalo Castro had his effort blocked.
The hosts did double their advantage before the hour mark though as Kagawa made a run down the right flank before crossing to Aubameyang, leaving the striker with a simple finish from close range.
It took Dortmund just four minutes to add a third as Mkhitayran tried to rifle the ball in from the edge of the box, but it was blocked, falling for Mats Hummels to power in on the rebound.
Mkhitayran was involved again a couple of minutes later, meeting another cross from Kagawa, but he sliced the ball over from close range, while Kagawa narrowly missed the target a few minutes later.
Dortmund did add a fourth late in the contest though, as Lukasz Piszczek sliced a cross in to set up Adrian Ramos, who hit the ball first time to find the back of the net just four minutes after coming off the bench.
Thomas Tuchel's side continued to pile forward in stoppage time, but an Aubameyang delivery was cleared, while Ramos headed wide while looking to add his second.
The result leaves Dortmund five points behind leaders Bayern Munich, while Frankfurt sit 15th, just outside the relegation places.