Most complex languages get interpreted or compiled into a much simpler format, and the simpler format gets executed. This lets the execution environment be small and understandable, as you said.
Using HTML/CSS as primitives means the execution environment has to be complicated, because the execution environment itself needs to be aware of things like whether certain attributes get inherited and how they are inherited.
I have hope for WebAssembly + Canvas, because it's a simpler set of primitives. There's a clear boundary between the simple execution environment and the tools that translate complex instructions into simple instructions.