I have found a work-around with a datapack.
Minecraft Advancements are checked near the beginning of the game tick and Minecraft's function tag tick is run near the end of the game tick. If Advancement sets block to "powder_snow" and function tag tick sets block to "air", technically the block is "powder_snow", but it is rendered as "air". So basically, invisible powder snow.
Create an Advancement that triggers on tick to call a function.
test.json
{
"criteria": {
"tick":{
"trigger": "minecraft:tick"
}
},
"rewards": {
"function": "mydatapack:test"
}
}
In that function set a block the player is in to powder snow, then revoke the Advancement. (My function makes sure it is only replacing air)
test.mcfunction
execute store success score #snow data run fill ~ ~1 ~ ~ ~1 ~ powder_snow replace air
execute if score #snow data matches 1 run summon marker ~ ~1 ~ {Tags:["snow"]}
advancement revoke @s only mydatapack:test
Then lastly in your datapack's tick function, set the powder snow back to air.
tick.mcfunction
execute at @e[tag=snow] run fill ~ ~ ~ ~ ~ ~ air replace powder_snow
kill @e[tag=snow]
Result

This isn't a simple solution, as technically you are walking around in a powder snow block. It is more effective to use this in an adventure map.