There are 4 places a browser can leak memory:
The web page
In modern browsers this is fully up to the web developer. Garbage-collected environments don't collect memory that is still being referenced to, and there are a lot of ways to keep referencing memory without meaning to (e.g. create a closure to attach as an event handler and accidentally include a bunch of variables in that closure's scope). A web developer can solve these leaks completely by properly handling variable references in their code. A page reload typically frees up the memory.
All modern browser engines are written in C++. C++ is not garbage-collected, but uses explicit memory allocation instead. If developers allocate memory and then forget to deallocate it, the engine leaks memory. To my knowledge all the browser makers do a lot of testing and code review to find and solve these kinds of leaks. It's not 100% fixed, and never will be, but it's not a huge problem anymore.
Finally there are a range of caching features that mean the browser's process will grow in scope while using it. These aren't leaks, they're intended to optimally make use of available RAM. Typically the memory footprint grows to a maximum and then hovers there.