Three reasons I think:
(1) The closer you get to the front end (especially GUIs), the further you get from algorithms and other mathematical certainties and the closer you get to something that's more a matter of design and fashion. People get tired of GUIs looking and feeling a certain way and they change, and that often requires a code re-work because changes in GUI look and feel can break previous abstractions.
(2) Form factors and display technologies change. Mobile completely annihilated 30 years of GUI work for example. To a lesser extent high-DPI screens have done a number on some older GUI systems. The stuff under the hood changes too but more slowly and in less fundamental ways e.g. an SSD is mostly a "disk" from an abstraction point of view even though the tech is wildly different. Command lines are fundamentally unchanged since the 1970s. VT emulations have become more advanced but the basic paradigm is incredibly stable.
(3) GUIs look deceptively easy but in reality they're incredibly hard. A modern GUI layer is at the same level of complexity as a modern game engine like Unreal. The list of edge cases and layouts and modes and languages and interaction metaphors and input devices and so on and so on you have to support is very long. Software engineers routinely underestimate this difficulty and try to re-invent GUIs and GUI abstractions in a quest to be clean and small and simple. They're then forced to shoehorn everything a modern GUI requires into these clean and simple abstractions, breaking them and turning them into overloaded monstrosities. Simple clean systems get ugly when you try to extend them too far. A more elegant design could be achieved by starting with the premise that the problem is big and hairy and developing heavier and more flexible abstractions accordingly.