In general, the way these vectors work is by exploiting flaws in the software used to read/render the HTML, CSS, and JavaScript. In a perfect world with perfectly secure browsers/email programs with perfect sandboxes, then you'd be right that just viewing a page or an email couldn't load a virus on your computer. But we don't live in that perfect world.
One example is the "buffer overrun" vulnerability: The attacker spends a huge amount of time and effort to find that a particular program loads some resource (a CSS cursor, for instance) into a buffer failing to check that the resource is small enough to fit in the buffer. So the program writes bytes beyond the end of the buffer. Buffers are frequently on the stack, and so overwriting them can overwrite things like the return addresses for function calls. If you craft the data just right, you can make a return address jump to instructions in the data of the resource you're loading. At that point, all bets are off, the attacker can run arbitrary machine code embedded in that resource.
Other vectors involve vulnerabilities in the sandbox in which the JavaScript on the page runs.