I have yet to see a long term css file that's not a birds nest of fixes.
I have yet to see a long term css file that's not a birds nest of fixes.
My issue is, ever since 1997, the spec hasn’t really lent itself to composability. Just a list of definitions. Maybe some shareable effects but not idempotent in and of themselves. From tables, to floating divs, to grid 960, to flexbox. We keep inventing new ways of dealing with the shortcomings of the standard.
Inheritance and composition should be paramount. Sass and Less help but still fall short of the ideal state.
When I encounter a “this isn’t lining up” problem. I think about the composition first before I think about styling. Should I put it in a div and give that the right properties that I can then shim a span in there with the rest of the required style? Or do I need a new style definition to achieve the look. I try to avoid creating new styles if I can.
Also known as the C in ”Cascading Style Sheets”. Embrace the cascade instead of having every class fully represent a component-piece.
.animal {
font-weight: bold;
}
.animal.bear {
color: brown;
}
<div class="animal bear">...</div>I have found that there are many tools out there:
- Design systems - Web components - Frameworks - Naming conventions - Higher level transpiled languages
Tools are meant to be used together, not in isolation. Any sufficiently complex app or page can benefit from mixing and matching these tools. At Aha! we have a design system, we use the BEM naming convention, we leverage web components, utility classes, and LESS.
With so many tools you can definitely get yourself into a mess unless you apply each one appropriately. That is where experience, discipline, and good old fashioned code reviews will help prevent a CSS nightmare file.
I think the problem starts with the phrase "a css file". If you're building something complex, you gotta bite the bullet and split things up.
If you're building apps, one way is doing self-contained components, which share absolutely nothing between them. You can have a "base CSS" for the page that is very small, just a few lines (plus maybe a reset), but the rest of the style should be "owned" by components and scoped to them using whatever methodology you choose.
Another possibility is going the completely opposite direction and having only helper classes (like Tailwind) that know absolutely nothing about the elements they're styling.
I don't believe in a middle ground. A lot of messes start by having a single CSS block that is responsible for styling 20 different parts of the screen with a very complex CSS selector targeting multiple components. This is like a COMEFROM in INTERCAL. I don't think you can't have your cake and eat it, except in toy projects. If you want to have a single-source-of-truth for colors, you gotta use variables (SASS, native CSS variables, etc), or a helper class.
Working with frameworks also requires care when you want to slightly change the default appearance, and a lot of people abuse !important for this. You don't have to do it.
To avoid !important when you want to "extend" some third-party CSS, use specificity rather than !important. Have a root class, for example .my-app-with-custom-style (it can be applied to the body tag or some other root element), and then extend each block of the framework using the root class + the same selector. For example, if your framework is .b-button.main-btn and you want to extend it, extend it with .my-app-with-custom-style .b-button.main-btn. This way specificity wins and you don't need !important.
There are numerous React frameworks that supply a "widget set" either of web page elements, UI controls or both that work out of the box.
If you (your client, your employer, ...) like the way these look out of the box they are a great way to build something quickly and not have to understand the underlying CSS.
If you are required to customize the look, however, or you want to combine components from various sources and have them look consistent you have to understand all the concepts of the frameworks, the frameworks the frameworks depend on and CSS.
Ideally as you write more code you get more reuse and writing future code becomes faster. In theory CSS classes act like this too. As you have more (well designed) CSS classes then writing future CSS becomes easier because you can reuse the past work.
Tailwind breaks this benefit that by encouraging you to write your CSS with glorified styles.
And code that uses Tailwind is reusable as long as you use components (React, Vue, Svelte, WebComponents, CSS components with @apply, it doesn't matter). Those are reusable.
Trying to use Tailwind without components, in a CSS-garden style page for example, is just trying to fit a square peg in a round hole. It's just the wrong tool for it.