Spain coach Luis Enrique had claimed his players prepared by taking 1,000 penalties as homework but Pablo Sarabia, Carlos Soler and Sergio Busquets all missed from the spot and Madrid-born Hakimi dinked his home to the delight of Morocco's raucous support.
Walid Regragui's side will face Portugal or Switzerland in what is uncharted territory for them, with their previous best being a last-16 exit in 1986.
Spain had been hoping they could repeat their 2010 World Cup triumph after reaching the semifinals of Euro 2020, where they were also beaten on penalties by Italy.
The teams were closely matched through a nail-biting clash, with Spain having more of the ball but Morocco creating the better openings, few though they were.
Luis Enrique trialled his third right-back of the tournament in Marcos Llorente, and benched the team's top scorer Alvaro Morata for Marco Asensio, after the shock defeat by Japan.
Spain monopolised the ball, with Morocco's fans furiously whistling with their side out of possession.
Morocco, who are the last African and Arab side left standing at the first World Cup held in an Arab country, were intensely backed and their fans greatly outnumbered Spain's.
With La Roja playing in a pale blue second strip, they resembled the away team on hostile territory.
Gavi, who at 18 years and 123 days old became the youngest player to start a World Cup knockout game since Brazil great Pele in 1958, rose to the occasion.
The Barcelona midfield terrier was at his most intense, smashing into challenges left, right and centre, even diving to make one with his head.
Morocco goalkeeper Yassine Bounou tipped a Gavi strike on to the crossbar, though it would have been ruled offside, while Asensio drilled into the side-netting, although Spain created little.
Regragui's side sat deep defensively and threatened on the counter, with Unai Simon beating away a long-range effort from Noussair Mazraoui.