Ivan Perisic scored the winner with three minutes left after Croatia keeper Danijel Subasic had saved a penalty from Spain captain Sergio Ramos with 20 minutes remaining.
Croatia’s Nikola Kalinic had cancelled out an early goal from Spain striker Alvaro Morata in the first half.
Spain meet Group E winners Italy in a heavyweight last-16 tie on Monday in Paris — a rematch of the 2012 final — while Croatia will play one of the third-placed teams in Lens on Saturday.
“Now we will face a more difficult rival than had we finished first in our group,” Ramos said.
Spain’s path suddenly looks more perilous. Not only do Italy stand in the champions’ way in the round of 16. World champions Germany are then potential quarter-final opponents while hosts France and England also lie in wait as possible semi-final opposition.
“We are disappointed,” conceded Spain coach Vicente del Bosque. “The path now might be seen as more difficult, but you never know where the danger is.”
Kalinic’s goal just before the break was the first goal conceded by Spain in 948 minutes of European Championship matches since October 2014.
Croatia’s excellence and commitment in battling back from behind condemned a jaded Spain, going for a third straight title, to their first defeat in a European Championship finals since they were beaten 1-0 by Portugal in the 2004 group stages.
“When you play against the world’s best, you have to play like this,” Ivan Rakitic said.
“We deserve it. We gave everything until the last minute.”
Croatia overcame the disappointment of their second group match against the Czech Republic by starting confidently, seeking to set the tone with an intense press.
However, it was the Spanish who struck decisively in the seventh minute with a goal that encapsulated the technical prowess, the movement and the vision that sets them apart from the rest of this summer’s contenders.
David Silva drove inside before sending a delicious reverse pass out to Cesc Fabregas, whose diagonal run across the box went unnoticed by everyone else.
His cross was met by Morata, arriving at the back post, and on the day that his move back to Real Madrid from Juventus was announced, the striker touched home for his third of the tournament, moving level with top scorer Gareth Bale.
Spain, unchanged and enjoying the cohesion that familiarity breeds, could have doubled their lead when Nolito directed Silva’s searching cross just wide, but Croatia held tight and steadily began to rediscover their early menace.
Ivan Rakitic sent an ambitious chip onto the bar with the goalkeeper stranded while Kalinic, picked ahead of goalless Mario Mandzukic, offered mobility and a tenacity that had previously been missing.
With Spain eyeing a second, it was Croatia who struck, as Perisic’s cross found Kalinic, stealing in ahead of Ramos, who flicked the ball past De Gea with the outside of his foot.
It was hugely entertaining fare, thankfully unaffected by the crowd troubles that have accompanied Croatia’s other matches this summer.
Croatia began the second half confidently and David De Gea was called into action to tip away Darijo Srna’s cross before closing down Tin Jedvaj’s follow up.
They were then left fuming at an unjust penalty in the 72nd minute when Silva, chasing a delicious lofted ball from Andres Iniesta, fell under imperceptible pressure from Sime Vrsaljko.
Captain Ramos sent a hesitant spot kick down the centre of the goal and Subasic, advancing well off his line before the shot, was able to bat it away as justice was served.
“I had a chance to put my team ahead and unfortunately I couldn’t convert,” Ramos said stoically. “It wasn’t to be.”
Late goals have been a theme of this tournament, and while Spain struck late to down the Czech Republic in their opener, here they were on the receiving end.
A Spanish foray forward was halted abruptly and Marko Pjaca surged on the counter before laying the ball off to Perisic, whose low shot, aided by the merest deflection, evaded De Gea at his near post as Croatia were able to celebrate a famous win.
“We are playing outstanding football in this tournament,” Pjaca told reporters, “and shouldn’t be afraid of anyone.”