City were beaten in Ashton Gate’s first Severnside derby for three and a half years as Cardiff City’s assault on the Sky Bet Championship top six gathered momentum.
Lex Immers and Stuart O’Keefe did the damage with two simple finishes as some heavy second-half pressure proved in vain for Lee Johnson’s men.
The head coach named an unchanged team after City secured a fourth win in five games at Nottingham Forest last time out, though Luke Ayling was fit enough to return to the squad after six weeks out with a knee injury to replace youngster Zak Vyner on the bench.
But Cardiff have been on a good run themselves, losing only one of their last eight, and started brightly.
Right-back Lee Peltier picked up a great position as he surged into the City box, but Immers sliced his volley well wide from ten yards much to the delight of another sell-out crowd in BS3.
The locals were on their feet again when Lee Tomlin showed some brilliant footwork to evade a sea of blue shirts and force a corner, from which Nathan Baker attacked at pace but headed over.
It was typically frenetic for a derby game but lacking clear sights of goal for either side.
Dutchman Immers had seen the best of them, and it was he who profited from an even more straightforward chance to edge the visitors in front after 21 minutes.
It came at the end of a sustained spell of Cardiff pressure in which top scorer Anthony Pilkington retrieved possession down by the corner flag and played a cute pass inside for Joe Ralls.
Ralls powered into the box and slid the ball across goal for Immers to score with a routine finish from six yards.
Cardiff’s play-off push has been built on a rock-solid home record, but they were looking pretty confident on their travels when Ralls tried his luck on the volley from distance at the end of a slick counter-attack.
City’s in-form marksman Jonathan Kodjia had not been involved in much of the play but the Frenchman forced a first notable save from David Marshall on 28 minutes.
Charging on to a long pass over the top, Kodjia struck a bouncing ball firmly into the ground that popped up and needed Marshall to parry into the danger area before Bobby Reid claimed a penalty when eased out by Bruno Ecuele Manga, only for City appeals to fall on deaf ears.
The hosts were enjoying plenty of the ball, with Cardiff content to play on the break, but the bulk of the City threat was coming from set-pieces.
Pilkington and O’Keefe both hit goalbound shots before the interval – one saved and one blocked – to leave the Bluebirds feeling quite pleased with their first half’s work.
Marshall was voted man of the match when the two sides met in South Wales back in October, and the Scottish international would have to react smartly to keep out Tomlin’s deflected toe poke ten minutes into the second period as City chased an equaliser.
Then the keeper was called upon to punch clear a wicked inswinging corner from Luke Freeman, before the midfielder shot wide from the same passage of play.
Ayling entered the fray along with Aaron Wilbraham for the final 25 minutes as Johnson set about turning City’s second-half dominance into goals.
Joe Bryan duly switched from central midfield to a left wing position, leaving Marlon Pack as the only holding player in a 4-1-3-2 formation.
Still City’s most likely route to a result was coming via the dead ball. Again Marshall was in the right place to keep out Tomlin, stooping to his right to turn aside a free kick that bounced awkwardly in front of him, before Scott Golbourne’s low drive had the Scot breathing a sigh of relief as it skidded wide.
Bryan and Wilbraham combined to good effect but Ecuele Manga made a crucial block as time continued to ebb away, before Kieran Agard replaced Kodjia in Johnson’s final change.
Cardiff had rarely ventured out of their half since the break, but made the game safe with a sucker punch seven minutes from time.
Leicester City loanee Tom Lawrence had shifted from the right flank to the left and cut infield on to his stronger side before letting fly with a shot that O’Donnell did well to tip on to the crossbar, only for O’Keefe to follow up with a low header from point-blank range to effectively kill the game.
City kept going and forced more corners – one of which Wilbraham headed over from six yards – but Agard’s booking for a dive summed up the sense of desperation inside Ashton Gate as the travelling fans rejoiced in their derby bragging rights.