Hacker News new | ask | show | jobs
by WheelsAtLarge 1178 days ago
It's always been a time sink for me. Besides using frameworks, does anyone have any suggestions on how to develop a css file without getting into the neverending hacks that require hacks to fix the hacks?

I have yet to see a long term css file that's not a birds nest of fixes.

7 comments

Sass helps with reusable code. Bootstrap and standards also help a bit. Bulma, PureCSS, Tailwind (Pro), Concise. These provide a good starting point.

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.

> inheritance and composition

Also known as the C in ”Cascading Style Sheets”. Embrace the cascade instead of having every class fully represent a component-piece.

I know what the C stands for, while it does cascade, it’s not inheritance and it always lends itself to “why does this have this style? I didn’t want that!”.
It's absolutely inheritance.

  .animal {
    font-weight: bold;
  }
    .animal.bear {
      color: brown;
    }

  <div class="animal bear">...</div>
There is no one silver bullet to clean up CSS. I think much of the problem is that many developers think of clean CSS as an afterthought. The same level of care and organization should be applied to CSS as you would apply to the rest of your code.

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.

It depends on what you're building. For a simple website that only uses a few tags, a single file should be enough, but that's no challenge.

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.

Tailwind * tries * to resolve this, but is probably just a different bird's nest.
Frameworks are going from the frying pan to the fire.

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.

The problem with Tailwind is that it is write-once code. You don't get any leverage.

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.

Well, tailwind itself is very reusable, probably the epitome of reusable CSS.

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.

Tailwind is a bird's nest in one place instead of a bird's nest in two places with hidden abstractions.
Are you building sites or apps? I got to the point a long time ago where I just didn't care to cover every single design need and just made my own mini-framework.
Ask ChatGPT to do it for you. It does surprisingly well.
Some people prefer to actually understand the code they deploy.
The code it generates is pretty understandable