Goals from much-maligned Alvaro Morata and Mikel Oyarzabal finally settled an eventful game in Copenhagen that ended 3-3 after 90 minutes.
Croatia had taken an unexpected lead when Spain goalkeeper Unai Simon allowed a back pass from Pedri to slip into the net.
Spain responded superbly through Pablo Sarabia, Cesar Azpilicueta and Ferran Torres, but Croatia fought back with two goals in the final five minutes of regular time from substitutes Mislav Orsic and Mario Pasalic.
Croatia kept their momentum going in extra time, but Simon made a nice save and Spain eventually secured a place in the last eight.
Spain, who beat Slovakia 5-0 in their last group game. got off to a positive start. Sarabia shot into the side net and Koke should have scored when he was pushed back by the feet of goalkeeper Dominik Livakovic.
Morata’s frustrations then continued as he fended off a great opportunity by missing a header.
Croatia offered little but, remarkably, came out ahead after 20 minutes.
This happened under extraordinary circumstances when Simon passed away. Pedri returned the ball near the halfway line and the keeper looked away as he jumped, caught his foot and rolled into the net.
It was a moment to forget but Spain reacted well to the setback and equalized before the break.
Livakovic did well to save a well-struck shot from Jose Gaya but Sarabia was on hand to get the rebound in, albeit with the help of a deflection.
The Chelsea captain moved into an advanced position as Pedri pushed Spain forward. Manchester City’s Torres then whipped up a handsome cross from the left and Azpilicueta rose to the back post to give the home a header.
Torres appeared to have given Spain a firm grip when he ignored a defender to skillfully score a third goal with 14 minutes remaining.
Croatia, however, were not beaten and woke up to a grandstand finish.
They got back into the game as Orsic got the finishing touches to pull one off in a scrimmage.
Orsic was then involved again as Croatia grabbed a dramatic equalizer in stoppage time, swinging a left cross that Pasalic met with a firm header to beat Simon.
Spain looked deflated and came close to being caught early in extra time, but Simon, redeeming himself somewhat from his earlier mistake, made a superb save to keep Andrej Kramaric at close range.
Armed with that, Morata then delivered a strong retaliation to his detractors, propelling Spain into a 4-3 lead with a fierce strike into the roof of the net in the 100th minute.
Moments later Spain had a two-goal lead again as substitute Oyarzabal rushed into the box to meet a beautiful ball from Dani Olmo and come home.
Faithful to a frantic game, Ante Budimir could have answered for Croatia but missed the target when he was well placed.
Olmo also hit the post as Spain continued to threaten until the end in an entertaining encounter.