Being picky about a CSS reset for fun
chriscoyier.net
chriscoyier.net
One of the first things I ditched was CSS and I switched to tailwind. Apart from making it easier to make stuff look good, it just generally seems to make building layouts so much easier. Maybe I just did not go enough into CSS, but I can not see myself ever going back to vanilla CSS now that I have started using tailwind, so articles like these I always find interesting as they show experienced people not using tailwind so they probably have some good reasons why they prefer CSS.
Re: CSS layout. It’s actually just a very big, complex practice to become proficient in. If you’re ever inclined to go back and relearn it, it helps to accept that from the outset. Once you’ve accepted that it’s a fairly involved learning process, the successes should feel more significant and the failures hopefully more temporary. But!
Re tailwind: if it’s working for you, and you never feel compelled to drop into lower level styling concerns, that’s fine. Great even. You’re getting stuff done that you want to do, with tooling that addresses your needs! I don’t personally love tailwind, and I much prefer to write styles directly… but it’s obvious tailwind solves this well for you and others who don’t share my preference.
Re CSS vis tailwind: probably overly pedantic, but you are still using CSS. You’re just not authoring it directly. I’m only pointing this out because you may find a time when tailwind doesn’t do everything you want/need, and it’ll help to know it isn’t some styling black box. It’s just a very thoroughly robust abstraction around the styles you could write directly if you choose. And if that abstraction, however robust, doesn’t fit your needs, plain CSS is always there to supplement it.
And then one day ... there it is. It all just makes sense. Not as much sense as JS! But enough sense for me to think, huh, I never thought I'd get this.
My one criticism of Tailwind, which I enjoy but do not currently use, is that it's likely to delay if not prevent this ultimate moment. If your long-term goal is to be a proficient front-end developer, I think you should try getting dirty with CSS sometimes.
Not always! Use Tailwind when you have a thing you need to get done. But sometimes.
Really wanted to start from scratch and I'm just using vanilla html/css/js for
Haven't found the need yet for any frameworks.
This is a static page, CSS framework shine for dynamic page where style needs to change beaded on state.
It's just CSS classes.
So they essentially reinvented the style attribute in a less verbose form?
If it's a reinvention it's objectively better at least.
```css
.card {
...
}
```
```html
<div class="card" />
```
RATHER than a reinvention of ```html
<div style="..." />
``` <div class="block">...</div>
<div style="display: block;">...</div>
https://tailwindcss.com/docs/displaySo we've gone from inline styling to separating markup and presentation with CSS but now we've gone back to inline styling.
Because the presentation affects markup. You'll have to add wrapping divs to accomplish any kind of complex layout for example.
Once you can't separate it in your mental space, it doesn't matter that its in two different files.
> You'll have to add wrapping divs to accomplish any kind of complex layout for example.
I don't know about that. I think selectors are pretty powerful. Have managed to avoid littering the HTML with structural nodes by using them creatively. CSS has gained a huge number of features since I first learned it, there's even better ways to do stuff now.
I've used CSS, and Tailwind and not worrying about naming everything correctly and not skipping around different files is a dream for me. Perhaps that's my brain, Idk.
Further I have gone over old code, and haven't had any problem with maintainability
It's not actually the same thing. What you're talking about is inline styling which takes precedence over class-based styling. It's generally considered bad practice to rely on inline styles. The traditional approach is `style="card"` not `style="...a bunch of rules..."`
<div class="block text-black">...</div>
<div style="display: block; color: black;">...</div>
Looks like the same thing to me. Only shorter.<style> .someClass { display: block; color: black; } </style>
<div class="someClass">...</div>
You can do this with CSS variables now I suppose, but this very quickly becomes "CSS classes, but with extra steps".
I agree, but that place is normally the code/templating engine that generates your webpage. So it really shouldn't matter if it's repeated on the wire.
> You can do this with CSS variables now I suppose, but this very quickly becomes "CSS classes, but with extra steps".
Variables are much simpler and easier to understand than selectors.
I see, we finally reached the root of the issue.
Why are CSS selectors a mistake? Doesn't seem that way to me. Why shouldn't I use them?
Isn't this a symptom of the selectors not being specific enough?
> You can't reliably reuse your styling or components between pages, because the exact same element placed in two different pages might end up with radically different styling
Can you give concrete examples of this happening?
I can provide an example I think is a good use case for highly specific selectors: turning HTML lists into file system trees.
https://www.matheusmoreira.com/css/tree.css
ul.tree,
ul.tree ul {
list-style-type: none;
padding: 0;
}
ul.tree li {
margin-left: 1em;
border-left: 2px solid var(--tree-color);
}
ul.tree li code {
display: block;
position: relative;
padding-left: 1em;
padding-bottom: 0;
line-height: 1em;
}
ul.tree li:not(ul.tree > li:first-child) code::before {
content: "";
position: absolute;
left: -2px;
width: 0.75em;
height: 0.5em;
border: 2px solid var(--tree-color);
border-top: 0 none transparent;
border-right: 0 none transparent;
}
ul.tree li:last-child {
border-left: 2px solid transparent;
}
ul.tree li:has(ul) > code::after {
content: "/";
}
<ul class="tree">
<li><code>~/.files</code>
<ul>
<li><code>~</code>
<ul>
<li><code>.bash_profile</code></li>
<li><code>.bashrc</code></li>
<li><code>.vimrc</code></li>
<li><code>...</code></li>
</ul>
</li>
<li><code>GNUmakefile</code></li>
</ul>
</li>
</ul>
That sort of thing feels like a perfect fit for CSS selectors to me. I admit it's not a super complex design (or even a beautiful one, I suck at design) but it does demonstrate the value of selectors.Well, yeah, but that's a "you're holding it wrong" argument. If you make your selectors specific enough then they will apply to the right elements, and if they applied to the wrong elements, well, they weren't specific enough. In practice people resort to only ever using a classname as a selector because anything else is too likely to break; there's no way to find out which selectors apply to which elements or which elements are covered by which selectors (e.g. you can't do the equivalent of "find references" on a variable).
> Can you give concrete examples of this happening?
Only on the level of, like, "my company's whole webapp" (but I've seen it cause real bugs in prod if that's what you're getting at). Getting surprised by which selectors get applied isn't a problem you can show in small examples, because it doesn't happen with small examples; it's only when the selectors and DOMs are too complex to keep in your head that you have a problem.
> That sort of thing feels like a perfect fit for CSS selectors to me.
Why does it need selectors though? It doesn't change based things at higher level (which is the failed ideology that the likes of the CSS Zen Garden were pushing - the idea that you want your component's styling to magically change to fit in with the page it's on or what's happening around it). What are you doing here that you couldn't do with a self-contained component that knew how to style itself?
I also just don't really understand. It adds a complicated build step. I already previously heavily used "utility classes" in my own vanilla CSS projects and so can anyone else without adding a complex build step. This also inherently provides something like tree-shaking. You don't have any css code you're not using since you only define the classes you want. You also get to know all the CSS variable names.
For small projects, Tailwind feels like an overengineered solution to a non-problem (though I respect that it has helped a ton of people bad at CSS make decent looking websites). For large projects, it quickly becomes more of a crutch than a help. For frameworks like React, styled-components already solves issues TW supposedly helps alleviate in a much more elegant way.
It seems like the niches TW is helpful for is medium-sized projects and for people who are just... not that good at CSS and not interested in improving
Why?
I mean, I kinda get this on `body`. But I've never understood why people do this on block level elements like paragraphs and headers where default behavior should definitely be margins.
Closest I've ever come to a rationale is so that you'll see the unset margins and intentionally specify them into whatever design systems you're using. But even that doesn't really make sense: if you've got an off-the-shelf design system, it will do that job, you don't need your reset to do it. If you've got the time/inclination to DIY, you are almost certainly the kind of person who will pay attention to this. And if you're neither of those, your reset should do something sane by default.
Resets should be about standardizing sane cross-browser defaults for quasi-naked HTML. This kind of behavior goes beyond that into nuking sane behavior for naked HTML. Why?
On the other hand not much is lost with this. If css is ignored, cool. If not, other settings will fix layout as needed.
The main argument for #1 is that it's closer to vanilla and lighter weight.
The main argument for #2 is that of you're making a comprehensive style, it's nicer to not have to worry about how for input elements have wierd legacy behavior, or to have to have a list of non standard box-sizing elements and a bunch of other weird legacy style anachronisms open all the time.
I personally, and I've seen this happen to others started out in camp #1 and eventually transitioned to camp #2 after I realized just how weird some stuff is. It definitely didn't mame sense to me until I had a lot of CSS experience.
If it's nonzero, it's always going to be something extremely arbitrary, and will almost never be the value that matches your design anyways.
Best to just nuke it all and make every positioning decision consciously. And when you forget to set something, it'll be quite obvious where it needs to be fixed.
For instance if you settle for 2em margins, all you other margin calculations need to remember that 2em value, and you also need to teach all your new coworkers the 2em value. That's dramatically less needed if it's 0.
For a reset/normalization sheet focused on sane standardized defaults? Seems like we'd be talking about two numbers: whatever vertical margin you want for your block level elements that you'd expect to have margins (most likely 1em) and 0.
Where are the other numbers coming from in the context of a reset?
IMO it’s more correct semantically. An <h1> means the top level of page heading, it doesn’t mean “1em of margin at the top and bottom”. A CSS reset that also resets all margins etc lets you derive your own formatting rules from semantic HTML. In most cases this is all a nitpick but I do get the rationale.
It's typically easier to work out a layout if you use padding in preference so you don't have to worry about them, but first you have to reset the margins the browser gives you.
h1, h2, h3, h4, h5, h6 { margin: 0 0 1em 0; }
which fits with the expectation that headers don't need to kick off with a vertical margin along with overflow containment rules to manage that behavior.
I don't know if I've seen using padding values to do margin's job lead to less pain.
There are even OS differences between the same browser!
This site shows some of the default styles for different elements:
Normalize wants to make browsers have the same defaults. Usually with a particular focus on accessibility and more "invisible" behaviors.
Give me that warm 2014 feelings again
I personally don't use reset css and my web pages look ok. There are so many web pages that doesn't use reset css, they look ok.
I also don't like when people are being picky about things for fun. This is a job that people take seriously.
Put grid/flex on most block elements. Spacing between boxes and their children is always handled with padding, spacing between siblings is always handled with gap. Everything else becomes way easier.
First column ‘fr’ gap ‘15px’ second column ‘fr’ gap ‘30px’ third column ‘fr’ and now you have three equal columns with two different gaps?
Good question. That sounds like you have different groups.
eg: you're thinking of it as:
.items
.item1
(thin gap)
.item2
(thick gap)
.item3
But it's actually: .items
.sale (thin gap)
.item1
.item2
.regular (thick gap)
.item3https://pilabor.com/blog/2021/03/html-and-css-tricks/#normal...
I basically don’t use those elements for UI components, and in the rare cases where I would want to, I could just do a one-off to override them. Or, more likely I’d just do something like <div role="heading" aria-level="1">
I find in applications you eventually need some little places where you have some basic document styles: paragraphs, headings, bullets, and it’s nice to be able to use those basic semantic tags for that stuff.
> -moz-text-size-adjust: none;
> This makes it so iPhones...
Why is a -moz- prefix needed for a Safari workaround?
[0]: https://kilianvalkhof.com/2022/css-html/your-css-reset-needs...
Browser default styles aren't really good enough to be usable IMO; yes they have paragraphs but with zero margin and tiny text they're not exactly readable. Twitter Bootstrap is pretty much a bug report against the browser default style. Given that current browser default styles are half-assed at best, I'm sympathetic to the idea that not having a default browser style at all would be better.
The whole point is to make everything look the same across every browser in existence. Also to remove collapsing margins.