Why Shared Styles Break Applications: The CSS Boundary Problem In short: CSS wants to be global. Three specific leaks account for almost every "the library broke our page" report, and only one of them is fixed by encapsulation. An enterprise adopts a shared UI library for consistency. Then the platform team ships a patch that adjusts a dropdown's padding, and the tanker dispatch dashboard — in a different repository, maintained by a different team — looks wrong. This is not carelessness. It is CSS behaving as designed: one global namespace, a cascade that crosses component boundaries, and specificity as the only referee. Leak 1: the global namespace A feature developer writes a helper class in their application's global stylesheet: Reasonable name. Unfortunately also has an element with the class . Angular's default emulated encapsulation protects the library's styles from leaking out , but it does not protect the library's elements from being styled from outside . Angular's own documentation is explicit about this: global styles defined outside a component may still affect elements inside a component with emulated encapsulation. So every card in the application now has uppercase headings, and nobody edited the library. The fix is namespacing. Every class the library emits carries a prefix: A consumer would have to write deliberately to collide, and if they do that, they have chosen to. Leak 2: This is the leak that causes the most damage, because it looks like a solution. The QA team wants "rejected" badges to have a pulsing red border. The library's has no such option. So: It works today. Angular's documentation notes that stops applying encapsulation boundaries from that point on, and strongly discourages new use of it. Here is the failure. Six months later the library renames to — an internal refactor, no API change, patch release. The library's tests pass. The QA dashboard's border silently disappears. Nobody gets an error; the style simply stops matching. The consumer built on a lucky selector , not a contract. The library never promised that class name existed, but by using it, the consumer made it a promise anyway. Leak 3: layout assumptions The subtlest one, and the hardest to lint for. The library styles while testing it inside a flex column with a known width. It looks perfect. A consumer drops it into a CSS Grid track, or a sidebar, or a container with . Now it stretches, collapses, or gets clipped — because the component made assumptions about its parent that were never written down. Lesson five fixes this properly with container queries. What to do instead of There are two legitimate answers, and picking the right one depends on what the consumer actually needs. Answer 1: the consumer owns a wrapper If the customisation is around the component rather than inside it, the consumer styles their own element: The library can rename every internal class it likes; this keeps working. Answer 2: the library exposes a custom property If the consumer genuinely needs to change something inside the component — the badge's own background, not a ring around it — the library has to offer it deliberately: That is a contract. The internal class name is still free to change; is not, and Chapter 9 treats renaming it as a breaking change. Lessons two and three build this out properly. Which answer, and when The consumer wants Answer --- --- A ring, a badge, a shadow around the component Their own wrapper Spacing between components Their own layout — the library should not set outer margins A different brand colour on the component itself A documented custom property A different internal layout Neither — this is a missing projection slot (Chapter 5) Something genuinely unsupported A conversation, then an API That second row is worth stating as a rule of its own: a library component should never set its own outer margin. Margin is a relationship with siblings, and only the consumer knows what those are. Padding is internal and belongs to the component; margin is external and belongs to whoever placed it. "But I thought was fine because it still works" It does still work, and that is exactly what makes it dangerous — this is not a case where the tooling will stop you. The reason to avoid it is not that it is deprecated. It is what it does to the definition of "breaking change". Once one consumer reaches into , that class name is part of your public API — and you did not know, did not document it, and have no way to find out short of grepping twenty repositories. Chapter 4 made the case that a small public API is what keeps a library changeable. widens your public API silently, from the outside, without a pull request in your repo. The failure mode is uniquely bad: It fails silently. A renamed class does not throw. The style just stops applying, and someone notices in production or, worse, does not. It fails asymmetrically. The library team ships a correct patch release. The consumer team gets the bug. Neither did any…