Real Madrid defender Dani Carvajal converted the winning spot-kick after Spain goalkeeper Unai Simon had saved efforts from Croatia’s Lovro Majer and Bruno Petkovic.
Spain’s triumph saw them seal a fifth major trophy and become the second nation after France to have won the World Cup, European Championship and the Nations League.
Manchester City pair Rodri and Aymeric Laporte, who scored and missed for Spain respectively in the shoot-out, have won a fourth major trophy of the season.
Croatia, who beat the Netherlands 4-2 after extra time in their semi-final on Wednesday, had been hoping to win their first major tournament.
Spain did not have one shot on target in a poor first half of regulation time, while Laporte’s last-ditch tackle thwarted Andrej Kramaric, and Ivan Perisic’s header forced Simon into a diving save.
Spain went close in the 58th minute when Marco Asensio headed their best chance up to then just over from the over-lapping Jordi Alba’s cross.
Nations League play-off - in pictures
Croatia responded through Mario Pasalic’s header, after another ball in from Perisic, before Spain stepped it up, with Fabian Ruiz’s chipped effort and Asensio’s shot on the turn both going close.
Spain went closest to breaking the deadlock in the 86th minute when Perisic blocked Ansu Fati’s shot on the goal-line following fellow substitute Mikel Merino’s cut-back.
Croatia substitute Majer was also denied by last-ditch defending as his shot after a counter-attack was blocked by Nacho in the first period of extra time.
Spain threw caution to the wind in the second period and finished the game on top.
Dani Olmo and Asensio had shots deflected for a corner and Rodri’s effort was blocked as the third Nations League final went to penalties, with Carvajal converting a nerveless winner.
Earlier on Sunday, Italy beat the Netherlands 3-2 in the third-place play-off in Enschede.
Roberto Mancini’s side, who sealed Nations League bronze for the second tournament running, made a flying start as Federico Dimarco and Davide Frattesi put them 2-0 up in 20 minutes.
Steven Bergwijn reduced the deficit for the Netherlands midway through the second half, but Federico Chiesa struck Italy’s third four minutes later.
Georginio Wijnaldum ensured a nervy finale with the Netherlands’ second goal in the 89th minute, but it was not enough to prevent a third defeat in four games under boss Ronald Koeman, in his second stint in charge.