CSS: Unavoidable Bad Parts
Posted by surprisetalk 8 days ago
Comments
Comment by seanwilson 6 days ago
CSS isn't powerful enough by itself to create any layout you want without modifying the HTML. You almost always need wrapper elements to group elements you want to align together for presentation purposes only (e.g. "a vertically centered row containing one paragraph next to two vertically stacked images"), so there often aren't semantic HTML tags that would make sense.
It's similar to how you use numerous groups/frames in design apps like Inkscape and Figma to help align elements, where nobody would suggest you were a bad designer for using groups that don't have semantic meaning.
You can only really avoid wrapper elements for simple Markdown style pages with simple designs, where the CSS for that is straightforward.
I think in these discussions, it needs to be clearer how complex the page designs being discussed are. The CSS advice that makes sense for simple Markdown style pages is very different to what makes sense for a complex web app UI or a highly designed marketing page.
Comment by siddboots 6 days ago
Comment by nicoburns 6 days ago
Comment by seanwilson 6 days ago
> we would all be writing purely semantic html with completely orthogonal and swappable css. And today literally no one designs web sites that way - html today is mostly specific to presentation
I think of HTML + CSS as the presentation layer now, and the data lives in your e.g. database and Markdown files, so the data and its presentation are still separate enough.
The idea of just swapping out the CSS to completely restyle a complex site is nice, but people need to accept this hasn't worked out (and not because devs are bad at CSS) and move on.
Comment by DarkUranium 5 days ago
It would avoid the whole mess of block vs table vs float vs flexbox vs grid (and also absolute vs relative vs fixed) positioning.
Basically, it feels like 90% of CSS is it trying to fix its past layout mistakes & limitations.
Comment by fragmede 6 days ago
Comment by littlestymaar 6 days ago
> completely orthogonal and swappable css.
You're talking about having a single CSS and HTML page for multiple layouts, there aren't the same thing at all.
Comment by micromacrofoot 6 days ago
Comment by nicoburns 6 days ago
This is true, but the better you are at CSS the fewer wrappers you'll likely have. It's also easier to manage styles with fewer wrappers, otherwise you often end up having to put things like height:100% on every wrapper to avoid messing up the layout.
Comment by bastawhiz 5 days ago
I agree with the approach you are suggesting, but the reason I find these wrappers pop up: it's VERY hard to make components composable without them.
Let's say you want to have a block that adds spacing between each item within it. Easy: it's flexbox with a gap. Oh no, but a child is displayed inline, and has weird vertical alignment. And another child has an unexpected align-self. Now you get wrappers on the children.
Maybe you want a button. It's got an icon with text. You need a wrapper on the text, because without a wrapper you basically can't get anything right (you can't rather bare text with CSS).
How about a checkbox? Should be easy. You want the component to have the checkbox on the left with the text on the right. You want to allow two rows of text, with the first being in bold (the label) and the second row being a description or help text. You wrap the whole thing in a label element because you care about accessibility. But you need a dummy div to render the checkbox, because you can't reasonably style checkboxes. And each row of text needs a wrapper, because bare text. And maybe another wrapper around the two rows, because while you can use CSS grid to position the two rows above each other, lord only knows what the checkbox is inside of and whether it's flexbox or grid, and the height of the label might be weird and jack up the positioning of your text. God help you if any of the rows have text that doesn't wrap and is wider than the width of the checkbox's container.
The unfortunate truth is that you probably don't need the wrappers, but there's an element of defensive coding that just makes it infinitely easier to get things right all the time with wrappers.
Comment by sjs382 5 days ago
I'd argue that a lot of times those groupings are meaningful.
Comment by WorldMaker 5 days ago
Comment by grebc 6 days ago
As you mentioned sometimes there are unavoidable things you need to do in markup to make it work visually. Although lately grid & flex solve 95% of the problems that crop up for me fortunately.
Comment by matt_kantor 6 days ago
Challenge accepted: https://codepen.io/editor/mkantor/pen/019eb65b-5b17-70cc-872...
You aren't entirely wrong, but I think I'd change "almost always" to "often" or even "sometimes". A lot of the specifics come down to how you want stuff to reflow when the content and/or viewport sizes change.
Comment by seanwilson 6 days ago
In the code from the link, the <body> element is serving as the wrapper element, that gives you a hook to get the layout you want. But when you're not lucky enough to have a semantic wrapper tag like that, you've usually got to add a generic tag help. Or write CSS that's closely coupled with the HTML, so they aren't really separate anyway.
Comment by matt_kantor 6 days ago
The latter probably would need an element for each row to be maintainable/scalable, but depending on the content, `<article>` could be a semantically-meaningful container. Or (again, depending on the content) it could make semantic sense to put the `<img>` elements inside the `<p>` elements.
Comment by seanwilson 6 days ago
Visual design involves a lot of grouping and aligning elements, and there isn't always semantic reasons for it. Grouping is usually best done in the HTML, so it's hard keep this part of the visual design out of your HTML.
Comment by matt_kantor 6 days ago
Sparingly-used non-semantic grouping elements only inserted when absolutely necessary is a pretty different story from the "layers and layers of wrapper elements" that the article mentions, though.
---
> you need to modify HTML to modify the presentation in practice
If you're e.g. grouping together content that was previously unstructured, arguably that's a semantic change as well as a presentational one.
Comment by lawnmowed 5 days ago
No group HTML: p text /p img img No group CSS: p:has(+ img) {...} p + img {...} p + img + img {...}
Valid, semantic, easy to target.
Comment by littlestymaar 6 days ago
Pet peeve of mine: there should really be `<grid>` and `<flex>` elements, as well as `<fi>` (flex item) and `<gi>` (grid item) for the child element instead of relying on a div soup with CSS attributes everywhere.
Comment by nicoburns 6 days ago
grid { display: grid }
will work in every modern browser.Comment by yencabulator 2 days ago
Comment by littlestymaar 6 days ago
Comment by FelipeCortez 6 days ago
data:text/html,<grid><p>A</p><p>B</p><p>C</p></grid><style>grid{display: grid}</style>
afaik to create a CustomElement you need to use dashes, yes, but in this example `<grid>` is an HTMLUnknownElement, which renders just fine. some discussion here: https://stackoverflow.com/a/22545622/2393963Comment by littlestymaar 5 days ago
Comment by assimpleaspossi 6 days ago
Comment by icedchai 6 days ago
Comment by assimpleaspossi 5 days ago
Comment by icedchai 5 days ago
Comment by littlestymaar 6 days ago
Comment by assimpleaspossi 5 days ago
Comment by littlestymaar 4 days ago
Nope. It's a html tag to lay out data in a table form!
> but it's probably the only element that does such a thing.
<pre>, <b>, <i> all come with an associated layout implication. But the worst offender are <div> and <span>, which carry zero semantic meaning and just means “I'm a block element” and “I'm an inline element”, those are pure layout element. In fact are the ones I'm using as template for my demand of <flex> or <grid> elements.
And html isn't just tags, it's tags and attributes on these tags, and things like hidden, height or width are indisputably related to layout and not to data.
The idea of HTML as a pure semantic layer with no layout consideration may be a general design philosophy for the language, but that's by no way a faithful description of what HTML actually is in practice. And pretending it is, isn't helping.
Comment by jkrejcha 4 days ago
With that: <table> is really only meant for actual tabular data and not about layout. It really isn't about the layout. It got abused for layout because it was the only thing that worked in a lot of cases (especially amusingly enough, email)
<b> and <i> I think I'd agree, even if they did eventually get retconned to be "bring attention to" and "idiomatic text". Same with <strong> and friends. This happened with other elements too.
I think it's fair to acknowledge the realities (people who are writing HTML a lot of times use <b> to mean "bold") of usages but ideally the semantic meanings are useful. I have seen cases where "<strong>" emphasizes it by doing something other than bold for example
Comment by littlestymaar 4 days ago
That's what I'm saying, it's a general design principle for new developments, but that's it. (And I don't think that's a good one)
> It really isn't about the layout. It got abused for layout
It wasn't abused for layout, it was all about layout in the first place. If it was about data it would never have been possible to “abuse” it for layout, because an heterogeneous table with nested sub tables makes no sense from a “data” point of view. The fact that this was supported from the beginning shows what it was built for.
> but ideally the semantic meanings are useful. I have seen cases where "<strong>" emphasizes it by doing something other than bold for example
But I agree with that. I'm not saying we shouldn't have semantics elements in HTML, I'm saying that pretending that HTML “is only about data” is silly in a world were something like 80% of HTML tags in web apps are <div> and <span> that are here only for layout purpose.
Comment by dnlzro 6 days ago
Perhaps less nesting is better in that it is more readable. But if you compensate by writing more complex CSS, then I don’t see how that’s an improvement.
Comment by pathartl 6 days ago
Yes, it's a bit fuzzy now with modern displays (especially when display scaling is not at a whole number haha) but it just kinda feels like searching for something to complain about. If your browser and OS doesn't get in the way you can get exact measurement. This also applies to almost any UI framework that has some integration with the OS.
Comment by interstice 6 days ago
Spoken like someone that hasn't been handed designs and expected to 'just figure it out' for a living.
Comment by hexasquid 6 days ago
Comment by gucci-on-fleek 6 days ago
[0]: https://en.wikipedia.org/wiki/TeX
[1]: But it does work on WEB :) [2]
Comment by srdjanr 6 days ago
Comment by gucci-on-fleek 6 days ago
There is actually a TeX extension that supports viewers arbitrarily changing the page size of documents [0], but it's fairly new, and as far as I'm aware it has essentially zero adoption.
Comment by hexasquid 6 days ago
Comment by gucci-on-fleek 6 days ago
Comment by ozim 6 days ago
The web stuff mostly uses licenses such as MIT, Apache 2.0, and BSD. GPL-licensed projects exist, but still many more on permissive side.
Web is based on open standards developed through organizations and specifications are publicly available, royalty-free, and implemented by multiple independent browser engines rather than being owned by a single corporation.
Comment by tiborsaas 6 days ago
Comment by granra 6 days ago
Comment by bazoom42 6 days ago
But for simpler scenarios (like fixed-sized paper, desktop displays before super-wide screens), you can have both simpler and more precise layout systems.
Comment by micromacrofoot 6 days ago
Comment by themafia 6 days ago
flexbox. You can literally recreate any fully responsive desktop style GUI with it. You just need to layout your elements the same way you would in a GUI designer like QtCreator or Glade. Which means thinking in terms of divs with flex-grow set on them to get the automatic container expansion you get with "vertical boxes" or "horizontal boxes". These divs will sometimes be empty if you want a simple "expander" box.
Once you have it down you can look at any desktop GUI and just inherently understand how it maps into this flexbox model.
Comment by edoceo 6 days ago
Comment by pramodbiligiri 6 days ago
Comment by vladde 6 days ago
https://css-tricks.com/inheriting-box-sizing-probably-slight...
Comment by alwillis 7 days ago
> Let's start with the basics: if you write`font-size: 16px`then `16px` is the size of what? Sadly, the answer is "nothing in particular" -- this is a size of a virtual box around the glyph, but the box isn't tight, and the size of the glyph varies, depending on the font. Luckily, `font-size-adjust` property can fix it, and make `font-size` consistent across fonts.
All modern browsers default to 16px, but for accessibility and sanity reasons, we shouldn't use pixels.
By default, 16px = 1rem. You don't need to declare it; it just is.
Also by default, 16px = 100% if using percentage for font-size.
See "The Ultimate Ideal Bestest Base Font Size That Everyone Is Keeping a Secret, Especially Chet" - https://adrianroselli.com/2024/03/the-ultimate-ideal-bestest...
> Can you just set `font-size: 18px`or whatever works best for your chosen font? I think the answer is yes, but there are some caveats to keep in mind.
If you want to manually increase the base size, using relative units is the answer: `html { font-size: 1.125rem }`. Since by default, 1rem = 16px, 1.125rem is 18px.
> Setting `font-size` in your CSS disables that second approach.
Setting `font-size` in pixels disables changing the browser's default size; works fine with relative sizes.
If the goal is not having to learn the intricacies of CSS, just use the built-in type scale:
| CSS absolute-size values | xx-small | x-small | small | medium | large | x-large | xx-large | xxx-large |
| ------------------------ | -------- | ------- | ----- | ------ | ----- | ------- | -------- | --------- |
| scaling factor | 3/5 | 3/4 | 8/9 | 1 | 6/5 | 3/2 | 2/1 | 3/1 |
| HTML headings | h6 | | h5 | h4 | h3 | h2 | h1 | |
By default, medium is 16px which is 1rem.You can write `p { font-size: medium }`.
BTW, the main use case of `font-size-adjust` is for changing the font size of your fallback font incase your primary web font doesn't load or if it takes too long depending on what `font-display` is set to. You want the metrics of the fallback font to match the primary font so the text doesn't shift [1].
[1]: https://www.w3.org/TR/css-fonts-4/#font-size-adjust-prop
Comment by LoganDark 6 days ago
> All modern browsers default to 16px, but for accessibility and sanity reasons, we shouldn't use pixels.
That's not what that means. font-size specifies the size of the font's em box, but the correlation between the em box and the visual size of the font is not consistent across fonts. font-size-adjust can adjust how a font-face responds to the font-size so that the sizing is consistent with other fonts of that size. For example, capsize is easier to implement that way.
https://seek-oss.github.io/capsize/
(I agree that specifying font size in pixels rather than rem is bad practice.)
Comment by elxr 6 days ago
Comment by sheept 6 days ago
If the user is on a phone and has a larger default font size due to vision difficulties, making padding scale with the font size takes screen real estate away from the larger text the user needs.
Comment by elxr 6 days ago
Also, not having ridiculously oversized margins, like so many 2019-2022 websites trying to look "modern" used to use.
old.reddit.com is one example where the paddings still look good when magnification is set to 150-170% (which I have to do because of the tiny default font size). I think doing it that way but with better readability at 100% zoom, would be a decent solution.
Comment by TonyStr 6 days ago
Comment by elxr 6 days ago
I want to use those as references to fix my UI (on increased font-sizes on small screens) before releasing an app I've spent 4+ months on.
Comment by CableNinja 5 days ago
Comment by bryanrasmussen 6 days ago
Comment by Joker_vD 6 days ago
Comment by Jaxan 6 days ago
Sure if you are a designer and want to follow trends, you’ll have to keep your css skills up to date. But for most websites, you can use css from a decade ago.
Comment by TonyStr 6 days ago
Comment by Joker_vD 5 days ago
> Writing CSS today has gotten significantly easier with flexbox, variables and now nesting.
Which, you know, are not some technically complicated ideas that simply could not have been done thirty years ago. Heck, <table> existed, and so did the algorithm that laid it out, from the outset yet getting flexbox to replicate that functionality took literal decades. And nesting is in no way more complicated to implement than cascading.
> BEM is not part of the CSS spec, that's just a design methodology.
Yes, and it existed for a reason, to paper over the deficiencies of the built-in functionality.
Comment by micromacrofoot 6 days ago
Comment by llbbdd 6 days ago
Comment by micromacrofoot 6 days ago
Comment by matt_kantor 6 days ago
Comment by bryanrasmussen 5 days ago
Comment by lelandfe 6 days ago
I view nesting as a footgun. I recommend trying to restrain all CSS to one selector, and to instead view additional qualifiers as an escape hatch where needed. Death to specificity.
Comment by camillomiller 6 days ago
Comment by lwilld 6 days ago
I'd say this disclaimer at the top speaks for itself!
Comment by cbold 6 days ago
Comment by reverseblade2 6 days ago
Comment by bryanrasmussen 6 days ago
I had thought about writing some things about this, but I will put a quick observation here
>restrict yourself to using only markup-meaningful semantic tags, and then figure out CSS which works with the markup you have.
this used to be the best practice advice about 20 years ago. If you've been around long enough in programming, especially in web development, you will see cycles of best practice advice where the thing you were told as the best practice at one time becomes the worst practice later.
For example at one time it was considered "best practice" to put script tags at the head of the document.
Anyway this guy really isn't the person to give you best practice advice, as he notes.
The semantic tags advice is dear to my heart and I wish it were so, but it is wrong, unless the site you are working on is the online representation of a textbook or something highly structured like that, in which case it is spot on.
The reason why it is wrong is that most of the web is a design focused medium, as opposed to a meaning focused medium. In a meaning focused medium the semantics are the most important thing, because semantics are how we convey meaning. That's pretty much tautological there.
In a design focused medium obviously semantics of things are important, but so is arbitrariness. To see that arbitrariness is important, pick up any highly visual magazine that has been applauded for its design aesthetic. Obviously no magazine is completely arbitrary but even more structured ones like The New Yorker need to do somewhat arbitrary things with the layout and design to enforce the rules of taste which guide it.
It is not impossible for a design focused publication that in moving between articles that the look of headlines change (although always recognizably headlines), the necessity of splitting things up with visually arresting details that delight the reader is common place, typography and images are there to delight the visual sense, not to clarify a point being made in the article, as a common rule.
If you were to try to semantically describe all these effects and things with meaningful class names you would end with lots of drivel, essentially, or things that mixed presentation description with semantics like ".ArtDecoHeading" perhaps, and that is because the difference in presentation of many of these things communicate absolutely not semantic value but only that it looks cool or nice or whatever way you want to describe the effect of design on the target of the design.
This relates to lots of CSS frameworks where the names of classes describe not what the element is or means, but rather what the class does, because when design affects are placed in a somewhat semi-arbitrarily manner this is really the most sensible way to describe a lot of classes.
Again, as nothing is completely arbitrary you will find things that are a mix of semantic classes like ".productTitle"
Semantics and Presentation mixed
".bigHeader"
and pure presentation that is trying its best to seem semantic somehow
".sideBoxSlideIn .upDownJumper"
I mean definitely you have to identify what parts of your application have semantic meaning, where the design will not arbitrarily affect them, such as .productTitle, but I believe in most modern web development much of what you will be doing is not semantic styling, but design styling.
And when you are doing design styling you might find you're creating layers and layers of wrapper elements, because making wrappers is often one of the easier ways to solve arbitrary layout problems.
On edit: this was partially prompted by the guy claiming never to have written production CSS and saying he is not really the person to be giving advice here, and I agree because he does not understand the actual needs of web development as a design based medium. Which is why he suggests such previous best practices as don't use classes and stuff like that which just doesn't work because to be able to do arbitrary layout without classes we would need to have millions of element types to play around with and then you have just recreated the problems with classes, only worse.
on edit2: added note at beginning.
Comment by sfn42 6 days ago
Personally I like to try to use semantic HTML where possible, as it helps with a11y and is nicer to read and work with. But I don't mind using some container/wrapper divs to make things look right.
Comment by pathartl 6 days ago
I feel like something in the CSS camp that could be highlighted in a "great idea, okay implementation, poor reception" that the OP is going for is print stylesheets. Those are incredibly underused.
Comment by al2o3cr 8 days ago
Comment by camillomiller 6 days ago
Comment by marcomezzavilla 6 days ago
Uhmmm, ok
Comment by chrismorgan 6 days ago
Comment by HelloNurse 6 days ago