127.0.0.1 is the default loopback of most system. A loopback address is an address used by the system to validate the network stack of the OS.
The loopback address for IPv4 could take any value in the subnet
The loopback address for IPv6 could take any value in the subnet
ping any value in those range should work if your network stack is working on your OS.
localhost is a hostname, this a sort of domain name but local to your own machine.
This hostname by default point to your IPv4 and IPv6 loopback which is often
localhost address could be changed easily by editing the file
If your system use the service
systemd-resolved, this service will handle the way localhost is resolved.
According to the documentation of
The hostnames "localhost" and "localhost.localdomain" (as well as any hostname ending in ".localhost" or ".localhost.localdomain") are resolved to the IP addresses
When you try to ping a hostname or domain name it will ask the OS to resolve this hostname or domain name.
In your case, you disabled
icmpv4 but localhost is resolved as your IPv6 loopback and your IPv4 loopback but only your IPv6 loopback answer.
The difference is in one case you're trying to ping an IP and in the other case you ping a hostname that could take several values.
If you don't need IPv6 I advise you to disable it. It will double all the work you would need to do on firewall and configuring services:
sysctl -w net.ipv6.conf.all.disable_ipv6=0
If you still want IPv6 support and want to avoid
icmpv6, you could use
ip6tables -A INPUT -p icmpv6 --icmpv6-type echo-request -j DROP