The home side took a 14th-minute lead when Matt Taylor's touch to a Joe Bryan cross set up Marlon Pack, who lashed in a right-footed volley from 15 yards.
Taylor was involved again as City doubled their advantage five minutes before the break. His control and pass allowed Jamie Paterson to break through the Rangers back-line and shoot past the advancing Alex Smithies from the edge of the box.
It was not until the last minute of stoppage time that Rangers hit back, substitute Idrissa Sylla shooting home from close range from a cross by fellow replacement Conor Washington.
Lee Johnson's men fully deserved their victory and moved to within three points of Rangers in the table, four clear of the drop zone.
City started brightly and Paterson might have done better when shooting over from inside the box after six minutes after Taylor had passed up the initial opening.
Pack soon got it right to fire home the opener, while Rangers only tested home goalkeeper Frank Fielding once in the first half.
Former City midfielder Luke Freeman produced a low shot on the turn in the 20th minute, but it was comfortably saved.
Freeman and Rangers boss Ian Holloway, a former Bristol Rovers player and manager, took some predictable stick from the Ashton Gate fans.
The visitors did get the ball in the net after 38 minutes following a right-wing corner, but referee Jeremy Simpson spotted what looked a clear foul on Fielding.
And instead the hosts went into half-time with a two-goal cushion thanks to Paterson's finish.
City could have sewn things up soon after the break when Paterson shot weakly at Smithies, having been given a clear sight of goal by Tammy Abraham's pass.
But there was a scare for the hosts moments later as Fielding produced a brilliant save, diving to his right, to keep out Yeni Ngbakoto's shot from a cross by Washington, a half-time substitute for Darnell Furlong.
Washington fired into the side-netting from 20 yards following some neat footwork as Rangers upped their game.
But at the other end City continued to create chances. Abraham had a fierce shot deflected just over and Aden Flint had a header from a corner cleared off the line.
Josh Brownhill shot over from a good position after Johnson substituted both his strikers, with Monday's important game at Blackburn in mind.
Rangers kept battling and Fielding had to make a diving save to prevent the impressive Washington netting in injury time.
Then came Sylla's strike, but there was barely time for City to kick off.
Additional reporting by the Press Association
Referee: Jeremy Simpson (Lancashire)
Bristol City: Fielding, Little, Flint, Wright, Bryan, Brownhill, Smith, Pack, Paterson, Abraham, Taylor.
Subs: Tomlin, O'Dowda, Wilbraham, Magnusson, Hegeler, Cotterill, Giefer.
QPR: Smithies, Furlong, Onuoha, Lynch, Bidwell, Luongo, Manning, Freeman, Wszolek, Smith, Ngbakoto.
Subs: Washington,Goss, Mackie, Ingram, Perch, LuaLua, Sylla.