It was the second last-16 game of the day to go to a shootout after Russia had earlier shocked 2010 champions Spain.
Croatia could have won the game in extra-time but Captain Luka Modric had a penalty saved by Leicester's Kasper Schmeichel, after Mathias Jorgensen brought down Ante Rebic.
Denmark took the lead in the first minute as Huddersfield's Jorgensen squeezed in from close range, but Croatia levelled just three minutes later from Mario Mandzukic's fortuitous strike.
Juventus striker Mandzukic flicked a header wide Ivan Perisic blazed a shot over from 10 yards out, while Denmark's Christian Eriksen clipped the bar with a cross.
After the explosive start, the game turned into a cagey affair. A poor second half saw Nicolai Jorgensen strike an effort straight at Croatia goal-keeper Danijel Subasic as the game move in to extra-time.
Substitute Pione Sisto spun and curled a shot narrowly wide, before Ivan Rakitic struck the winning penalty.
Croatia and Russia meet at the Fisht Stadium in Sochi on Saturday.
Add commentComments will be edited (grammar, spelling and slang) and authorized at the discretion of Daily Mirror online. The website also has the right not to publish selected comments.