La bataille d'Aspern-Essling commença à 14h30 le 21 mai. Les premières attaques autrichiennes mal coordonnées contre Aspern échouèrent complètement mais Charles persista. Finalement, les Autrichiens parvinrent à s'emparer de tout le village. L'attaque d'Essling ne commença pas avant 18h00 car les quatrième et cinquième colonnes avaient plus de chemin à parcourir. Les Français repoussèrent toutes les attaques sur le village durant la journée du 21. Le 22, les combats commencèrent dès 3 h du matin et quatre heures plus tard, les Français avaient repris Aspern. Napoléon disposait maintenant de hommes et 152 canons sur l'autre rive mais les Français étaient toujours dangereusement inférieurs en nombre. Il lança alors un assaut massif contre le centre autrichien pour donner suffisamment de temps au corps pour qu'il puisse traverser et remporter la victoire. Lannes avança avec trois divisions d'infanterie sur avant que les Autrichiens n'engagent leurs réserves et n'obligent les Français à se replier. À 21h00, le pont français fut une nouvelle fois détruit par de lourds chalands que les Autrichiens avaient fait dériver grâce au courant. Charles lança une autre puissante offensive une heure plus tard et s'empara d'Aspern pour de bon mais ne put reprendre Essling. Cependant la ville tomba quelques heures plus tard malgré la défense obstinée d'un grenier à blé. Napoléon se retira mais la Garde impériale commandée par le général Rapp désobéit aux ordres de l'Empereur et reprit Essling. Charles poursuivit ses bombardements qui coûtèrent la vie au maréchal Lannes. Les affrontements diminuèrent peu après et les Français se replièrent sur l'île de Lobau. Les Français n'étaient pas parvenus à traverser le Danube et Charles avait infligé la première défaite majeure de la carrière militaire de Napoléon.