"Very disappointing because we had a chance to line up here and get something done today," coach Gary Kubiak said. "That doesn't mean we still can't get it done. That's the most important thing."
Houston (12-3) could still clinch home-field advantage next with a win at Indianapolis.
The Texans' latest stumble was fueled by an anemic running game that combined for 34 yards and an inability to convert on third downs.
"We didn't play well," Kubiak said. "I think we battled defensively, but offensively we probably played as bad as we've played. I take full responsibility for that. It's a huge, huge disappointment. We've got to get over it really quick."
Quarterback Matt Schaub went 18 of 32 for 178 yards, and Andre Johnson caught seven passes for 97 yards, but the Texans were a woeful 1 for 11 on third downs.
While Houston had a season-low 187 yards in failing to score a touchdown for the first time since the 2006 season, the Vikings (9-6) were 9 for 18 on third-down conversions.
"That was frustrating," said Texans defensive end J.J. Watt, who had a sack to give him 20 1/2, making him the ninth player in NFL history with 20 sacks in a season. "I know we gave up some third-and-shorts. We can't put ourselves in that situation."
Arian Foster, Houston's leading rusher, left the game with an irregular heartbeat in the third quarter and did not return. He finished with 15 yards rushing on 10 carries. He also had two catches for 14 yards.
"He's doing fine," Kubiak said. "That is something that happened once before in practice . (It was a) precaution."
Ben Tate took over midway through the third quarter and didn't fare much better, totaling 17 yards on four carries.
The Texans held Vikings running back Adrian Peterson to below-average numbers, but Minnesota found other ways to inflict damage.
One of them was rookie kicker Blair Walsh, who made three field goals, including a record-setting 56-yarder in the first half. The kick gave Walsh, a rookie, the NFL record with nine field goals of 50 yards or longer this season.
Peterson finished with 86 yards on 25 carries, leaving him with 1,898 yards for the season and 208 short of the Eric Dickerson's NFL record for yards rushing in a single season.
Peterson had his lowest rushing total since getting 79 yards on Oct. 14 in a loss at Washington, breaking a streak of eight 100-yard games.
He is trying to become just the seventh player in NFL history to rush for 2,000 yards in a season and the first since Chris Johnson in 2009.
Christian Ponder threw a touchdown pass, and Toby Gerhart added a score to cap the win for the Vikings, who remain in contention for a playoff spot with a game to go.
"We have to play better in all facets of the game," Watt said.
The Vikings took a 10-3 lead on the 56-yard field goal by Walsh.
Houston got within 10 points before Gerhart's 3-yard run extended the lead to 23-6 with about five minutes left in the fourth quarter. That drive was helped by a 29-yard carry by Ponder.
Ponder was 16 of 30 for 174 yards to help the Vikings pile up 345 yards. He finished with seven rushes for 48 yards—14 more yards rushing than the Texans had.
Houston got to the Minnesota 1 with a 12-yard reception by Kevin Walter late in the third quarter. Then came an incomplete pass followed by a run for no gain by Tate. Schaub was sacked by Fred Evans for a loss of 14 yards to make the Texans settle for a 33-yard field to cut the lead to 16-6.
"It was ugly," Kubiak said. "We made things really hard on ourselves."
Houston had to punt on its first possession of the third quarter, but got the ball right back when Watt sacked Ponder and forced a fumble. Bradie James recovered, but the Texans couldn't take advantage of the miscue and had to punt again.
"We hurt ourselves," Schaub said. "We had a chance. We've got to execute and have a killer instinct to score down there."
The Vikings extended their lead to 16-3 when Walsh made a 39-yard field goal on the first drive of the second half.
Houston was on the Minnesota 28 early in the second quarter when Jasper Brinkley forced Foster's fumble, which was recovered by A.J. Jefferson.
Houston had to punt later in the second quarter when Schaub was sacked for a 9-yard loss. A 41-yard field goal by Walsh left Minnesota up 13-3 at halftime.
Peterson ran for 20 yards to get Minnesota's offense going. The Vikings took a 7-3 lead when Kyle Rudolph grabbed a 3-yard touchdown reception. Rudolph also had a 27-yard catch that drive.
NOTES: The Texans wore decals with the initials S.H.E.S. as a tribute to the school shooting victims at Sandy Hook. ... Playing in his 137th game, Johnson got his 800th career reception on his first catch, making him the second-fastest player to reach the milestone. Marvin Harrison did it in his 131st game. ... Johnson has 100 catches this season, making him the fifth player in NFL history to have at least 100 catches in four or more seasons.