dev.css: tiny, simple, classless CSS framework inspired by new.css
26 points by op
26 points by op
Some review from skimming.
:root {
--dc-font: "Geist", "Inter", ui-sans-serif, system-ui, sans-serif;
--dc-font-mono:
"Geist Mono", ui-monospace, "Cascadia Code", "Source Code Pro", Menlo,
Consolas, "DejaVu Sans Mono", monospace;
}
These are bad defaults. There’s a little nudge from the README about Geist and Inter, but there’s limited guidance and they’re not there out of the box, so it doesn’t make sense for this to handle them out of the box. As for ui-sans-serif and system-ui, they’re controversial and I would recommend removing both.
In the monospace list: drop Cascadia Code, Source Code Pro, Menlo, Consolas and DejaVu Sans Mono. monospace will resolve to something no worse than these (I think Firefox was the last to ditch the irredeemably-bad Courier New, four years ago), and quite possibly better. ui-monospace is bad in a similar way to ui-sans-serif and system-ui.
Quite seriously: try just leaving sans-serif and monospace.
:root {
--dc-cs: light dark; /* light and dark scrollbars, inputs, etc */
color-scheme: var(--dc-cs);
}
Don’t do variables like this. Drop --dc-cs and just write color-scheme: light dark. If someone wants to override it, they can write color-scheme rather than --dc-cs too. There’s no advantage.
*, *::before, *::after {
margin: 0;
}
‹list of 33 elements› {
margin-bottom: 1rem;
}
I never much like total margin resets. For applications I concede there can be merit. But this isn’t that. This is a simple content web page stylesheet. I reckon this is the wrong approach.
Subsequent margin-bottom declarations show a fundamental unsoundness in how this stuff is being used.
#root,
#__next {
isolation: isolate;
}
This has no place in such a stylesheet. Read why Josh suggested it, and realise why it doesn’t make sense here. Also the balance has shifted a lot in the five years since Josh put that in, and the top layer is a useful concept.
a {
text-decoration: none;
}
This was never a good idea. The underlines are a valuable affordance. Personally, I’ve been using something approximately equivalent to :any-link:not(:hover, :focus-visible, :active) { text-decoration-color: color-mix(in srgb, currentcolor 30%, transparent) } almost everywhere (including in a user stylesheet to fix others’ websites) for about eight years.
@supports not (color: light-dark(#fff, #000)) {
a {
text-decoration: underline;
}
}
Can’t make any sense of this. Why would you want to restore the underlines specifically for browsers from roughly 2012/2015–2023/2024? This also suggests you want things to work if light-dark() isn’t available. I’ll say: they don’t.
::selection {
Please don’t.
body {
overflow-x: hidden;
}
Please never do this. Never. If it is useful, then you were probably doing the wrong thing (e.g. width: 100vw—viewport units are broken by design and Firefox’s fix was killed by the others for no good reason, so make sure you can use 100% instead), and it runs the risk of cutting content off so that the user can’t access it at all, especially on smaller displays. There are a few cases where you do genuinely need something like this: mainly, when you’re deliberately clipping something, or when you’re using a 3D transform that happens to make the bounding box overflow the viewport although nothing is actually lost visually. In such cases, I recommend applying the overflow-x to as small a part of the page as possible, and using clip instead of hidden because you probably don’t want vertical overflow to make the element scrollable, you want it to still overflow.
*:last-child
(And the likes.) The * there is not actually necessary. Just write :last-child. You only need * if there’s no tag name/class/pseudoclass/pseudoelement.
aside {
position: absolute;
}
Ouch. That is going to bite some users. Consider using float instead, or making the parent a grid (more involved, better in various ways but more limiting in others).
a button
Links should never contain interactive content. If this selector ever matches, it shouldn’t have. Did you mean .button like in the subsequent ones? Not classless, by the way.
details:not(aside details)
I was going to comment on complex selector support in :not() being fairly new, but… I think it might actually be early 2021 now that everyone had it. Huh. How time flies.
There are a lot of magic numbers in margins and gaps, a lot of which don’t end up feeling very nice to me. Lots of arbitrary choices, many of which are too small.
(Meta: hmm, should contribute a patch setting tab-size: 4, possibly down to a smaller value on narrower viewports.)
I agree on the vast majority of these. However, could you link to why system-ui, ui-monospace, etc., are not preferred?
(Also, why tab-size: 4? Well I guess I could change it to 8 with custom CSS and it wouldn't bother me much, but I'm still curious.)
They’re the system UI fonts, designed for short strings, not long-form content. Are you making a user interface that should match the local platform? Go ahead, use ’em. Are you making general content? Why on earth would you choose them? The only real reason people try it is as a proxy for better defaults, but that has become somewhat less valuable over time as browsers have updated various of their default fonts (most notably monospace). It’s also concretely problematic around languages, especially on Windows: the system font may not support your content language properly. Hence things like https://github.com/w3c/csswg-drafts/issues/3658 and https://github.com/mdn/content/issues/41244. I believe system-ui was a mistake (they should have left it at -apple-system, no other platform had a useful equivalent concept, and it was evident from well before the time of standardisation that almost all use of this stuff was abuse working around the fact that browsers weren’t updating their poorly-considered, ancient defaults for the existing generic families), and ui-{serif,sans,monospace} was a stupid idea which should still be ripped out.
For tab-size: 4: 8 is just so wide, I don’t think people often actually want it at 8. Especially not on narrow viewports. Feels like the default of 8 is more a historical inconvenience. Hmm… I wonder if there would be any way of convincing CSSWG to reduce the initial value from 8.
On system UI fonts: makes sense, thanks!
On tab size: maybe it's just a personal habit, but I really value large and clear indentation and 8 is a good default for me. I'd wish browsers could expose this to make the default customizable like how editors do
viewport units are broken by design
Where can I learn more about that?
They don’t take into account a viewport scrollbar. Thus, if you have a vertical scrollbar that’s 17px wide (traditional on Windows), 100vw is equal to what a normal person would call the viewport width plus 17px. Same deal for media queries, (min-width: 1000px) will match on a viewport that is effectively only 983px wide.
Long ago, Firefox implemented the sensible thing: if you apply overflow-y: scroll to the root element, guaranteeing a vertical scrollbar even on short pages, then 100vw will now be sensible and exclude that viewport scrollbar. (These days, you’d expect scrollbar-gutter: stable to achieve the same effect.) But for inscrutable reasons, no other engine ever got round to matching Firefox, and so Firefox dropped the feature in 2017 (never porting it to Stylo).
Some links:
https://www.smashingmagazine.com/2023/12/new-css-viewport-units-not-solve-classic-scrollbar-problem/
https://github.com/w3c/csswg-drafts/issues/1766
https://github.com/w3c/csswg-drafts/issues/6026
And… huh, apparently in 2023 they decided to go back and adopt Firefox’s approach after all. Except in brief testing, Firefox hasn’t implemented it again and Chromium is getting it wrong by a pixel (possible rounding error due to fractional scaling?). Sigh.
You mean that 100vw = (width of viewport) + (width of scrollbar) sometimes? So, essentially, the size of the "window"?
What should I use instead of vw/vh when I want to size things in terms of the viewport?
I’d say always rather than sometimes, except for this overflow-y: scroll thing which Firefox formerly had and Chromium seems to have recently but possibly buggily.
Depending on the scenario, you may be able to use percentages (%), flex units (fr), or even container query units (cqw/cqb/&c.).
In other places, you don’t actually need precision, and the maybe-17px doesn’t actually matter, you’re just getting something that’s approximately right.
Amusingly, the whole thing isn’t as big a deal as one might have imagined due to rounding. Sure, sometimes people do width: 100vw and such and we who use traditional space-occupying scrollbars suffer for it, but the more common thing in the past was actually having five 20% children, and the fifth one wrapping because 5 20s might be a little more than 100. So people already shrunk their values a bit for safety. Or switched to flex and let the browser handle it.
dvw perhaps? https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/length#relative_length_units_based_on_viewport
I was incensed by the addition of those new viewport units: they fixed an entirely self-inflicted mobile-only problem where iOS had, essentially, done something dumb and deliberately broken everyone’s pages in 2015, and Android had followed suit in 2016 (and by the time they made the units the workarounds to get what you needed were well established, so you didn’t exactly need the new units)—but they didn’t fix the scrollbar problem that had been there from day one, and which Firefox had previously fixed. It showed that they genuinely don’t care much about platforms that use non-overlay scrollbars.
dvw is just exactly what vw was until Apple decided to unilaterally change it, against spec, to be what would later be known as lvw (which caused far more problems than it fixed).
I have a list of pretty good (subjectively), small CSS frameworks, some of my favorites are:
And some fun ones:
No mention of pico.css?
This one’s “tiny”. Pico CSS is in a different weight class, well past even “small”: https://cdn.jsdelivr.net/npm/@picocss/pico@2.1.1/css/pico.min.css is 83 kB. (It does compress better than most, which arguably emphasises structural problems in it. Brotli-compressed, it’s 13.6 kB over the wire.) And it slowly grows.
By contrast, https://cdn.jsdelivr.net/npm/@intergrav/dev.css@4 is 5.8 kB. Brotli-compressed, 3.1 kB.
"small" @ 5.5kB? huh? for the given use cases, I think I'll always prefer a basic CSS reset and custom CSS as I need it.