Julian Draxler got the home team on their way to victory in the 11th minute with Klaas Jan Huntelaar doubling their advantage 10 minutes before the break.
The defending champions tried to respond in the second half, but only had a Robert Lewandowski consolation goal to show for their efforts as the gap between them and Bayern Munich at the top of the table grew to 20 points.
Draxler was making his 100th appearance for Schalke, becoming the youngest player to reach that mark in the Bundesliga at the age of 19 and a half, and he marked the occasion with the opening goal in the 11th minute.
Mats Hummels, back in the Dortmund side after over 10 days out with flu, seemed to be under the weather still when he let Atsuto Uchida's cross pass and Draxler accepted the invitation.
Dortmund responded well in an open game which swung from end to end with chances aplenty.
Huntelaar's shot in the 14th minute was saved well by Roman Weidenfeller before Joel Matip's header was cleared off the line by Mario Gotze in the 25th minute.
Weidenfeller denied Draxler in a one-on-one situation minutes later, but the Dortmund goalkeeper was beaten again in the 35th minute when Huntelaar headed the Royal Blues' second from another Uchida cross.
Dortmund coach Jurgen Klopp rung the changes at half-time, bringing Marco Reus and Nuri Sahin on and playing with just three defenders in the second half.
It was a gamble which paid dividends with Lewandowski bringing them back into the game on the hour, beating Timo Hildebrand in a one-on-one situation.
Dortmund continued to attack with Schalke getting everybody behind the ball to defend their lead.
They nearly got a third goal on the counter-attack in the 74th minute, but Teemu Pukki's shot was too weak to beat Lukasz Piszczek.
Schalke resisted the late pressure to beat their local rivals 2-1 for the second time this season and give them confidence ahead of the midweek Champions League clash with Galatasaray.