Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Another minimalist CSS framework, another review from me. :-)

> :root { color-scheme: dark light; }

The stylesheet is written with light values by default, and dark values in a prefers-color-scheme media query. Therefore, this should be `color-scheme: light dark` instead. As written, if no preference is expressed, your styles will be light, but UA styles will be dark.

> * { box-sizing: border-box; }

I personally am one of the rare contrarians that prefers content-box for the web (simplifying my position a lot: good responsive design bases sizes and such on content, not layout). But if you’re going to change it to border-box, you might want to consider changing it on pseudoelements (at least ::before and ::after) as well. Then again, you’re not using them. Then too, the whole box-sizing declaration seems no-op.

> * { color: var(--dark); }

That’s… um… courageous. No, I can’t leave it at that: this is a very bad idea. This will make custom styling painful, may ruin elements that have backgrounds set in the UA stylesheet (e.g. input, mark), and I detest links being the same colour as the surrounding text.

> :root { --light: …; --dark: …; }

I don’t like how these two variables are used: you’re using them as #defines (to use C preprocessor lingo) rather than what custom properties can be, and end up with significant duplication because of it. Consequently, every time you use --light or --dark, you have a counterpart the other way round in the tail @media (prefers-color-scheme: dark) block (except that input[type=submit]’s counterpart is just input; I’ll remark on that later). Here’s how you should do it:

  :root {
      --bg: #fff;
      --fg: #404040;
  }

  @media (prefers-color-scheme: dark) {
      :root {
          --bg: #404040;
          --fg: #fff;
      }
  }
… and then use --bg and --fg throughout, and need no more dark color scheme media query at the end. You could define two colours and have --bg and --fg use them, but because of how light works, you may not want to just swap the two colours—for example, you might want to darken both --bg and --fg in dark mode (it’s currently fairly bright for a dark mode; something like #eee on #333 would be more common).

> html { border-style: solid; border-width: 5px 0 0 0; border-color: var(--dark); }

Shorter written in the :root block before it and as `border-top: 5px solid var(--dark)`. As for what it represents, I don’t like it. It’ll tend to be an eyesore, especially on dark. If it was a colour, sure, but just --light or --dark? Nah, don’t like it.

> font-family: sans-serif;

Thank you for a sensible font-family.

> px

There’s quite a bit of not-great usage of pixels. Remember that the root em is not necessarily 16 pixels, so for correctness most px things should actually be defined font-relative. As a simple rule of thumb, take any px value, divide by 16 and change the unit to rem. (Single-pixel lines are about the only place I can think of where px is genuinely what you want, though even then it’s still not guaranteed to be a crisp single pixel, due to possible fractional scaling.)

> p { margin-bottom: 10px; }

This doesn’t do what you probably intended. Indeed, in the sample document, I think it does nothing: remember that most of your flow content elements have 1em block margin, which is (likely) greater than your 10px, and margin collapse applies.

> p { line-height: 1.4em; }

Dubious: now anything that’s not inside a <p> uses some other line-height. You probably want to specify line-height on the root element. Remember that line-height accepts a unitless value, too, to be calculated relative to each element’s font-size, whereas em fixes it. Me, I’ve actually started experimenting with this, to conveniently reduce otherwise-extravagant leading in headings:

  * {
      line-height: calc(1em + 0.5rem);
  }
That is, 1rem (16px) body text gets line-height 1.5 (24px), 2rem (32px) heading gets line-height 1.25 (40px).

> img { width: 100%; }

This needs `height: auto`, or else <img width=… height=…> (which you should strongly prefer, to avoid layout reflow as the image loads) will get a mangled aspect ratio. Also consider using max-width instead of width.

> button, .button, input[type=submit]

I’m not fond of various of the styling here. I reckon it could do with a hover/focus-visible colour change, and no `cursor: pointer`, among other things.

> button:last-child, .button:last-child { margin-right: 0; }

This kind of thing is smelly.

> ol { column-count: 2; }

This is a phenomenally bad idea. Some opt-in class, maybe. Numbered lists in general, no.

> .row .column:not(:last-child) { margin-right: 10px; }

Better, provided you’re OK with as low as two years (to the day!) of browser support (https://caniuse.com/flexbox-gap): `.row { gap: 10px }`.

> Put in four columns and you'll get four equally sized columns.

Not true, actually; put something too big in one column and it’ll cause the other columns to shrink. That’s what you get for using flexbox! (Grid, by contrast, is… well, more size-is-defined-by-the-parent-and-the-children-are-welcome-to-lump-it.)

Really, I don’t like the columns arrangement. I much prefer to use flexbox with flex-wrap and sensibly-chosen flex-{basis/shrink/grow}, so that the content defines when things can fit beside one another or wrap. The current .row and .column arrangement is much too fiddly, specific, and weird. Also the .column class name is superfluous, should have just used `.row > *`.

> input

I said I’d address this later, but I’ve taken too long on this. Suffice it to say that there are problems with how form elements other than buttons are handled in diverse colouring situations. Either override (nigh-) everything, or nothing. Never override just one of background and foreground colour.



Fascinating review.

It begs the question: is CSS beyond repair? So many footguns, so little time.

I recall browsing one of the websites collecting such CSS "frameworks" in a previous episode and was stunned by the mediocrity of it all. It is breathtaking. Basically, most of these things fail in various ways, like:

- gross display errors: it could not possibly be what the author intended, on plain current Firefox

- gross design errors: really ugly, like text outside the viewport or impossibly bad use of whitespace or colors

- responsiveness fails: becomes unusable or very ugly on a simple window resize.

That's without trying to actively find less obvious problems like things that will fall over in future, or past, browsers, in other browsers, or facing different user settings.

And this is the output of people who went out of their way to write and publish a CSS toolkit, thus presumably consider themselves competent, and maybe sell their malpractice for money to be deployed against users on the real web.


> It begs the question: is CSS beyond repair? So many footguns, so little time.

CSS has come a long way; unfortunately people get stuck on the CSS they learned 10 years ago.

As soon as I saw the width being specified in pixels and the use of custom properties like they were static like Sass variables, I was like “what are we doing?”


> font-family: sans-serif;

> Thank you for a sensible font-family.

Not sure this is sensible in 2023.

I'd suggest:

    font-family: system-ui, sans-serif;
After all, the purpose of system-ui [1] "is to allow web content to integrate with the look and feel of the native OS". Seems like a natural for something that's supposed to be minimalist.

system-ui [2] is supported by 96% of web users, so there's no reason not to use it.

[1]: https://w3c.github.io/csswg-drafts/css-fonts-4/#system-ui-de...

[2]: https://caniuse.com/?search=system-ui


system-ui is not suitable for general web content. Apps might have an argument for using it, but general web content should not use it. https://github.com/w3c/csswg-drafts/issues/3658 has some details (mostly by others, but I chip in towards the end), and I’ve written more in other threads here on HN too which you can search for.

(That `box-sizing: content-box` is a good default might be my most unpopular CSS opinion, but writing off system-ui is probably not too far off it. But I care more about it because it’s one that actually affects users, not just developers. Maybe I should get round to pestering browser makers to improve their defaults for the sans-serif generic family so that “proxy for a maybe-prettier sans-serif” goes away as a reason to use system-ui.)


> system-ui is not suitable for general web content. Apps might have an argument for using it, but general web content should not use it.

I emphatically disagree.

On most platforms, font-family: sans-serif results in Helvética or even worse, Arial, which weren’t created with with the web or screens in mind.

One could argue that a website that has any interactive elements is an app; in 2023, that’s a distinction without a difference. system-ui would work fine for an app or a website.

system-ui also gets a developer great typographical features—optical sizing, extensive internationalization support, small caps, ordinals, etc.—“for free” on current platforms without breaking anything and without downloading a font.


This is a weirdly contentious issue by web devs, but in my experience, system-ui is fine. It's used as the default in popular frameworks like Bootstrap[1], and most of the teething issues have been solved for a while now.

[1] https://github.com/twbs/bootstrap/blob/adf7b8dc4083b6ddc318e...


> I personally am one of the rare contrarians that prefers content-box for the web (simplifying my position a lot: good responsive design bases sizes and such on content, not layout).

This is interesting to me. How is content-box better for responsive design? Could you elaborate?


This stood out to me too, and makes me scratch my head a bit, because it is not in line with the otherwise pragmatic advice.

For projects that have a design made by a designer (with something like Figma/Sketch/XD) it is definitely _not_ better for responsive design. Almost all designs assume that the border is part of an element. It's the more intuitive option, plus the tooling around designs will show you the spacing _between_ borders.

Intuitive: In the real world, when I need measurements from you and you omit the conceptual borders of a thing, I'm not going to be very happy.

Then you also have the issue that many of the common idioms get hairy and intuitive. Say you put an element with a border inside a container. With content-box, your 100% values are now not respecting the border, meaning you'd have to subtract the border width in order to fit the element.

Lastly there is the philosophical argument about layout vs content. HTML/CSS does not in fact provide a meaningful and clear distinction of layout and content/structure. They do somewhat in theory, but that falls apart so quickly that you're better off just ignoring the theory and live with the practice. And on a human level, there is no clear distinction either. The letters, colors, images and shapes we put on the screen are all part of the same visual experience we try to communicate.


The notes I’ve written in my “I might eventually turn this into a blog post” file:

—⁂—

border-box is about layout, content-box about content. You should aim to design things around content, not layout: leave layout to the parent.

border-box is incompatible with ratios: you need content-box there.

border-box is only actually useful for things like making body fill the viewport.

See also what I wrote in https://news.ycombinator.com/item?id=29357636

—⁂—

Elucidating a bit more: there’s only a difference if you have border or padding, and I just find it increasingly rare for border-box to be in any way useful, because we’re generally separating layout.

Consider the row/column thing in Neat here: do you use margin on the children, or gap on the parent? Consensus is that gap on the parent is normally better: let the child be itself, and handle layout concerns at a higher level. That fits with why I say content-box is the better model for the web, the model that you should aim to think in terms of: treat border and padding as semantically part of a parent, automatically-sized component, and so if you are specifying your own dimensions, specify them relative to the content, because the border and padding are layout concerns.

Designers tend to prefer layout to lead content, because that’s what’s easiest for them. I prefer to have content lead layout, choosing dimensions to fit the content and letting the layout size itself around that.

All up, it’s still fairly nebulous, based around concepts and broad design patterns rather than concrete demonstrations, and that’s part of the reason I haven’t written it up more fully—I need to make a compelling case if I want to present it at all. (Another reason is that I just haven’t been doing any of them, really; my potential-blog-posts notes file has about 38 entries and 6,000 words, and I have another dozen or two drafts in my site, but I haven’t been focusing on that stuff recently.)


> border-box is about layout, content-box about content. You should aim to design things around content, not layout: leave layout to the parent. > border-box is incompatible with ratios: you need content-box there. > border-box is only actually useful for things like making body fill the viewport.

I get the contrarian thing, but this doesn't make a whole lot of sense.

Both border-box and content-box are about content; it's just a matter what's included or not in the width of a box. Sure, there's some truth about what designers expected, but they weren't the only ones who were confused about how a box's border and padding changed how content worked…

There's a reason why virtually every widely-used CSS framework starts by changing content-box to border-box.

It's one of those issues that if we could go back in a Time Machine, content-box would have been the default; this is the next best thing:

        html { box-sizing: border-box }
        *, *::before, *::after { box-sizing: inherit }
References

From 2012, which started it all: https://www.paulirish.com/2012/box-sizing-border-box-ftw/

Developers are so psyched, border-box has a holiday: "International box-sizing Awareness Day"—https://css-tricks.com/international-box-sizing-awareness-da...

CSS Tricks almanac: https://css-tricks.com/almanac/properties/b/box-sizing/


I’m aware of all the stuff. I just think (and have thought from the start) that it’s wrong and has missed the point, especially in a flex and grid world where (a) the difference should matter much less often, and (b) if the difference does matter, you could probably implement things better (in a way that would incidentally make the difference not matter).


If it bumps it up the queue at all: I’ve been wanting to read someone pitch this way of thinking for what feels like an age.

Personally, I went all in on border-box as agency work is always design-lead. When the work is “make this picture in css”, anything other than border-box will drive you insane.

But it’s been a few decades of us pushing responsive design, so I’m curious if content-box doesn’t have its merits. I still don’t quite grok it from your explanations here (though I will re-read them), so would love to read that essay.


> line-height: calc(1em + 0.5rem);

Even cleaner imho, at least in theory, if you dont use 'em' but 'ex' for the relative sizing, the x-height of the element's first available font.

Good looking leading is often more influenced by the x-height of a typeface than by cap height (try setting Verdana and Times with the same line-height). So especially if your design has more than one typeface, using ex makes it more consistent.

Caveat: If the metrics are not set correctly in the font file, FF on Mac, and the Windows browsers will freak out. Should not be a problem with system fonts, but if you use web fonts, keep an eye on that.

I usually also set a unitless fallback, at least on the html element.


I think you’re misunderstanding what my invocation achieves: reduced line height on larger text.


No, I am proposing you write

line-height: calc(2.5ex + 0.5rem);

instead. The effect is the same, but based on the x-height of the font used, which can be beneficial for the reasons outlined. Adjust the ex to taste, between 2 and 2.5 or so.


Ah, sorry, I missed that.

Hmm, dunno. Interesting idea, but I suspect the uncertainty of actual value might cause me very mild difficulties occasionally. I’d want to play around with it in various fonts. Its failure mode is probably worse than using em, seen in a font with particularly tall ascenders or descenders. But then again, I have a vague feeling such fonts might commonly just extend beyond their box, in which case it’s not actually any worse.

In other news, I really want wide browser support for the lh unit.


I thought that was worth drawing attention to, i hope you and project owner don't mind:

https://github.com/codazoda/neatcss/issues/29


Interesting critique. I'm curious if there's some other nice-and-simple framework you'd recommend?


Sorry, no. For myself, I prefer to start from scratch, and I’ve never been particularly satisfied with any of these sorts of ones that I’ve found.


I'm the same as you. I like resetting and adding styles to all the base UI elements to create a unique design.

I agree to everything you commented above and would have said the same. There's a couple of issues with the font, spacing and other fundamentals.


You should write this as a blog post...


And/or save their css file about an hour into any project and share it!


Author here. Thank you very much for sharing this list. I'll consider each of your points.


This seems a bit hyper-critical and OTT for a HN comment on someone's personal project. Maybe you could take these and raise as issues in OPs GitHub repository, that might be a more constructive way to feedback.


I can't agree. The comment above is extremely constructive, and I'd be glad to receive that much helpful feedback on a project I'd submitted. The advice is both well-informed and actionable. That's not something you usually get for free!


In what way are any of his points not constructive? He obviously speaks from authority and provided alternatives or feedback on all his points. I found it extremely interesting and would have loved to read even more.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: