CSS is hard. But this is not because the language is faulty. Rather, the difficulty lies in what the language seeks to accomplish. I’ve heard many developers say they wish they could “throw out CSS and start over with something better.” I think this betrays a fundamental misunderstanding of the purpose of the language:
When you code CSS, you’re writing abstract rules to take unknown content and organize it in an unknown medium. That shit is hard.— keith•j•grant (@keithjgrant) March 17, 2017
Furthermore, CSS isn’t just code, it’s also part of the design. A vital concern of CSS is consistency. You should want “global” styles: colors and spacing should be consistent throughout your application. Similar components need to look similar. Your buttons should all be consistently sized and your box shadows or border radiuses should not be ad-hoc.
I find it ironic that developers who bemoan the “global” nature of CSS are usually the ones who run into specificity problems because they unnecessarily scope their styles to particular parts of a particular page. When you have selectors like
#directory .sorted .sidebar :nth-child(2) button, your problem isn’t that CSS is global. Your CSS isn’t global enough!
The next thing you know, you find yourself using
!important to correct specificity problems. This is a red flag that you need to stop and learn the cascade. You can use
!important to sweep specificity problems under the rug once. But you will soon need it a second time, at which point you will face the same specificity problem all over again.
Design your styles so they can be reused, anywhere in the app. Learn SMACSS and BEM. And don’t stop because you understand the “naming system”—these methodologies are about far more than double-underscores and double-hyphens. They are about code organization, reuse, and refactoring. They are the solution to dead code elimination. They offer ways to utilize the cascade instead of fearing it. They allow you to know precisely where in your code you can find a certain set of styles.