Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consider a version without forcing box-sizing #48

Open
rjgotten opened this issue Apr 12, 2021 · 10 comments · May be fixed by #56
Open

Consider a version without forcing box-sizing #48

rjgotten opened this issue Apr 12, 2021 · 10 comments · May be fixed by #56

Comments

@rjgotten
Copy link

rjgotten commented Apr 12, 2021

Counter to the common trend, it is not always 'awesome' or 'FTW'. It wreaks havoc with expectations stemming from normal browser defaults, which makes it harder to integrate into existing properties and makes it harder to integrate anything created by third parties that are not operating off of the same opinionated principle.

It's also a total pain in the ass to selectively undo with override rules, as it's reapplied on every element. At the very least you could use box-sizing: inherit I'd think, which makes it at least somewhat easier to selectively cut this awesomely annoying behavior out?

@franktopel
Copy link

franktopel commented Jul 7, 2021

Really, Chris Coyier has improved the code that is currently being used in modern-normalize.css back in 2014.

Instead of

*, *::before, *::after {
  box-sizing: border-box;
}

we really

should be getting this:

html {
  box-sizing: border-box;
}

*, *::before, *::after {
  box-sizing: inherit;
}

I can't explain better than Chris, so please take the time to read his reasoning why this is a much better version: https://css-tricks.com/inheriting-box-sizing-probably-slightly-better-best-practice/

Even Paul Irish, who in 2012 came up with the code you're currently delivering, has agreed and edited his original article to reflect the improvement: https://www.paulirish.com/2012/box-sizing-border-box-ftw/

@franktopel franktopel linked a pull request Jul 7, 2021 that will close this issue
@franktopel
Copy link

I've created a PR for this improvement. #56

@nuxodin
Copy link
Contributor

nuxodin commented Jul 7, 2021

This is also an option, but I dont think its always the better one.
In most cases I want box-sizing:border-box.
But there is also the situation that I want content-box for a certain element, but not inherited to the contained elements.

Both have advantages and disadvantages, for me not inheriting is the better solution.

@rjgotten
Copy link
Author

rjgotten commented Jul 8, 2021

@nuxodin
Both have advantages and disadvantages, for me not inheriting is the better solution.

Even when inheriting, your use-case can still be supported.
Just reset back to border-box on the direct children.

Personally, I would just pre-process whatever form of box-sizing normalization is present in a normalization sheet and rip it out, because after having run up against problems with it numerous times, I've come to believe it to be a theoretical ideal but a fallacy in practice...

@sindresorhus
Copy link
Owner

The current version was intentional: #37

// @jamiebuilds

@jamiebuilds
Copy link
Contributor

Yeah, I think the advice in css-tricks is only better if you only consider one pattern of building UIs.

Compare these two snippets:

Islands of widgets:

<widget-one/>
<widget-two/>
<widget-three/>

Trees of components:

<component-one/>
<compontent-two>
  <component-three/>
</component-two>

Both of these have their place on the web, and really almost every webpage will be a mix of both of these in different places. So given the goals of a generic reset/normalize stylesheet, they should both be considered.

The idea behind applying box-sizing: inherit to every element is that it creates a simpler mental model when marking an entire sub-tree as box-sizing: content-box.

That's great if you're only considering the "islands of widgets" pattern, but then it shifts the burden onto the "trees of components" pattern. And you start getting snippets like this:

component {
  box-sizing: content-box;
}

component::before, component::after, component > * {
  box-sizing: border-box;
}

So really we just have a tradeoff here, if we make it easier for "islands of widgets" we make it harder for "trees of components", if we make it easier for "trees of components" we make it harder for "islands of widgets".

So the question becomes: Which is the easier mental model for people to apply in the real world?

*, ::before, ::after {
  box-sizing: border-box;
}

Developer: "I want to make this entire tree content-box sized because that's what its expecting"

widget, widget *, widget ::before, widget ::after {
  box-sizing: content-box;
}

That's it, they are done.

<component-one>
  <component-two>
    <component-three/>
  </component-two>
  <component-four/>
</component-one>
:root {
  box-sizing: border-box;
}

*, ::before, ::after {
  box-sizing: inherit;
}

Developer 1: "I want my component to be sized with content-box"

component-one {
  box-sizing: content-box;
}

Developer 2: "Wait why does my component suddenly look wrong. Oh its inheriting content-box now, I guess I need to reset my component, and I'll make sure nothing inherits content-box again":

component-two, component-two *, component-two ::before, component-two ::after {
  box-sizing: border-box;
}

Developer 3: "Wait why does my component suddenly look wrong. Oh someone added a higher specificity selector overriding my content-box. I'll just add !important

compontent-three {
  box-sizing: content-box !important;
}

Developer 4: "Wait..."

I've seen all of this chaos play out all because Developer 1 forgot to reset the styles back to border-box for <component-one/>'s children. I've also seen it play out that Developer 1 reset the styles incorrectly and broke the inherit behavior for everyone.

Overall, I think a generic reset/normalize stylesheet is better off pushing the burden on "islands of widgets" because a lot less can go wrong there.

@rjgotten
Copy link
Author

rjgotten commented Jul 12, 2021

@jamiebuilds
That's it, they are done.

You're conveniently leaving out the case where .widget nests something else which needs box-sizing:border-box and which is styled using best-practice short class-only selectors, e.g.

<div class="widget">
  <div class="nested-widget"></div>
</div>
*, ::before, ::after {
  box-sizing: border-box;
}

.widget, .widget *, .widget ::before, .widget ::after {
  box-sizing: content-box;
}

.nested-widget {
  box-sizing: border-box;
}

That will break and will require the site author to pinpoint target their own dedicated CSS rules with higher specificity to fix it.
Moreover; it may require the site author to do so, each and every time the nested widget structure changes and those changes may be out of their control if they are dynamically including a third party widget from another web origin not under their control.

This is the reason both implementations of 'border-box all the things' are flawed, btw.
And the reason a version without it should exist.

@jamiebuilds
Copy link
Contributor

which is styled using best-practice short class-only selectors

That problem is only difficult because you decided that this was a best practice. Maybe re-evaluate that.

@rjgotten
Copy link
Author

rjgotten commented Jul 15, 2021

That problem is only difficult because you decided that this was a best practice. Maybe re-evaluate that.

Oh yes; let's force site authors to needlessly write higher-specificity selectors to cater to the whims of forcing non-default behavior on box-sizing. And then let's cover up that mess by saying those site authors should re-evaluate their position on the practice of managing selector specificity to keep it low.

Now there's a clear-cut case of "I reject your reality and substitute my own."

@nuxodin
Copy link
Contributor

nuxodin commented Jul 15, 2021

With css variables you could have the advantages of both variants, but maybe that's too mutch overhead.

html {
  --box-sizing:border-box;
}
*, ::before, ::after {
  box-sizing: var(--box-sizing);
}

.elementNeedsContentBox { /* but does not inherit */
   box-sizing: content-box;
}
.widget {
  --box-sizing: content-box; /* will inherited */
}
.nested-widget {
  --box-sizing: border-box; /* will inherited */
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants