the "it" you have to learn has constantly been a moving target. That's its biggest problem.
It's not. It's a declarative language where the declared intents are extremely high-level and can interact in surprising ways (credit where it's due: modern CSS has almost all those interactions well-defined and considered; it was much worse when the answer to how two pieces that were independently designed interacted was "However the browser feels like they should interact"). As a result, to really be deeply fluent in it you have to keep abreast of design trends (dialog boxes! scroll state! custom corner shapes!), and that's not every programmer's cup of tea.
(To be fair: there are really good tradeoffs here. Especially around accessibility: a declarative language where high-level intent is the main element is much easier to answer questions around, say, "How will a screen reader interpret this" than a low-level atoms-and-transforms language. Othewise, your screen reader has to be able to guess things like whether that set of SVG commands and transforms is supposed to be the corner of a dialog box or a very fancy letter 'C').
You are either a full-time front-end dev and have a chance to keep on top of it, or you do not know CSS, and are now blamed for it sucking.
To garner that, many people just want a simple UI that is not ugly -- not everyone wants a web design masterpiece, thus they 'don't bother learning it'.
Yes, it will work as it used to 15 years ago. You will get laughed out of a tech interview for it though.
> do you consider yourself a person who 'knows CSS'?
Sure. They know an older version of CSS. They don't know the latest version. Shrug....
> You will get laughed out of a tech interview for it though.
I've never laughed at anyone in an interview. Can you share some more nuances here? What's the role and expectation? How good is their code? Did they just not learn some modern designs, but can learn it quickly? What have they been working on the past few years?
Web components have helped here, but in practice I don't ever use them; I either use one global style.css file (for personal projects that fit in my brain alone) or I use a system that supports local CSS classes via a compilation-and-name-mangling step.
Layers take care of things you'd used to use `!important` to try to hack around much more systematically based on the specificity of the `@layer` the CSS is coming from. (More specific layers override more general ones as if they were more "!important".)
Layers don't entirely save you from naming conflicts or CSS specifiers that are too broad, but Dev Tools give you increasing ways to isolate which layer a conflict is coming from, at least, and that can help you decide on ways to fix the conflict.
I think `@layer` is a closer hint to what the "CSS-native" approach to "CSS modules" is going to start to be than just CSS class munging at compile time.
If I understand what you're saying, that's more about how you use (or don't use) combinators.
It's almost always an inequivocal mistake to use a feature that was released last year.
Why do you think the padding as a percentage is relative to the width of the parent? Do you think it was a happy accident? I don't think so, it was purposefully put there in the specs so that we could have boxes with fixed aspect ratios. This is just the tip of the iceberg.
The good thing is that all the hacks together make a working thing. And if you know them you can do a lot of stuff.
I understand why people hate Tailwind, but it largely solved this problem for me.
Where do you see CSS being global mutable state?
There are solutions/workarounds to this. First following a convention like BEM, then enforcing that at build time (CSS Modules), and now (potentially, i haven't checked in with it) the language supports @scope.
on edit: a downvote on that, really. because I don't think class names are anything like a variable!
Absolutely the worst kind of variable.
One very obvious example is browser defaults.
You literally have no idea what they are. You can override them, but not until you find a list so you know what to override.
Did you know the default browser margin for body is 8px?
Insane.
Frankly I tend to find analogies not very useful, I don't think my analogy of CSS as a db is very good, but as bad as it is I feel it makes some sense as opposed to talk about classes as if they were global mutable variables.
I will take my analogy slightly farther.
I will say the browser ships with a DB system called CSS, and a toy DB called BrowserDefaults implemented in CSS, the same way MS Access used to ship with Northwind. The especially sucky thing about this system is that when you want to create your own DB you have to extend BrowserDefaults. This is why a lot of specific DBs have what are called resets that basically delete all of the BrowserDefaults setup so it is not messing with your DB.
The browser also ships with two languages with the ability to query CSS, one is JavaScript and that is a pretty straightforward language it can read and write to CSS using an API called the CSSOM. The other query language is a tree based query language called HTML (actually there is also another tree based language called XML in there but nobody talks about that anymore, let's just say it works almost the same as HTML only when you use it, it automatically clears all the data out of the base BrowserDefaults DB)
(We can see what I mean about analogies suck right about here)
This tree based query language is crazy as shit! Because it is not just a query language but also has some weird transformational capabilities.
And also the thing that is weird is that the HTML query language can be changed by the JavaScript language!
Let's look at an example
Let's suppose we have a tree structure like this
<div class="one"></div>
<div class="two"></div>
and the JavaScript holds a tree fragment <span class="myspan">text</span>
and the CSS says
.myspan { color: green; } .one span { color: red }
.two span { color: black }
the JavaScript reading that fragment css properties will see that "color" = "green"
but placing it inside of the parts of the HTML tree gives different values for the color property. Some people will mistakenly claim at this point that the is mutation of the global state but that is obviously incorrect. The CSS state has not been mutated at all, what the HTML query has done essentially is run a transformation and output an object, the CSS state remains unchanged because JavaScript can use the CSSOM to query what the data in the myspan class is.
JavaScript can mutate the value of the CSS classes, but HTML cannot. HTML essentially copies all the classes, runs a transformation, and outputs the result.
This is actually a pretty interesting situation, I don't feel that there is any similar architecture anywhere. I don't feel it really fits with DSSL or Latex (because of how JavaScript works with HTML)
Now although I don't feel that I have ever really had the problems that other people of undoubtedly superior programming ability seem to have with this, I can see how this unique and somewhat accidentally arrived at architecture can be irritating to people.
Note - when I say I don't have any problems I mean sure, I can create bugs with this, I can find bugs impacting me with this, but I've never really had long running hard to resolve bugs due to CSS/HTML. Bugs that are generally hard to resolve I find are in the JS stack.
Going back to the browser defaults thing - again not really a good example of either of our analogies, more an example of how every programming language has its idiosyncratic and stupid things you just have to learn about it and keep in mind or they will bite you on the ass.
on edit: obviously I am not making any claims as to internal implementations in browsers and how they do it, I am just discussing the external experience of these languages working together and how to think about them.
JS with CSSOM can read what the value .myspan, .one span and .two span all are.
because this is the point where CSS breaks down as a db holding properties, it is here that it is instructions for the HTML language on how it is to run transformations.
.one span {color: red}
.one span {color: purple}
inside of a CSS file.
Again I don't think I could consider that as mutating state.
This is mutating state
let color = "red";
if (x} { color = "purple"; }
because it mutates the variable value at run time based on something else.
The variable at different parts of the program have different values.
If you read .one span with the CSSOM in the above example it will always return color: purple.
That is not a mutated value, that is poorly written code that has been compiled down.
Give your element a class. Now show me the CSS that styles it. Good luck because it can be literally anywhere.
You can do this in TypeScript and Ruby too.
It ought to be possible to compose HTML documents the way Ted Nelson wanted to compose documents in Xanadu, it's a PITA to do because the classes are all in the same namespace although now we have Shadow DOM to manage this and you can even do it without JS with Declarative Shadow DOM.
It's a source of stress to add a class to the system with a simple, short and readable name and have to worry it is used someplace else. There is BEM but I despite it (not simple, not short, not readable)
I work on a React application that uses more than one plain-CSS framework and also Emotion and some other JS frameworks that generate more CSS properties. These are all leaky abstractions so if you aren't happy with the defaults the way I am with my boostrap-based RSS reader, you have to understand the abstractions of the framework and still understand the underlying CSS. Probably the worst time was when I had to get an application to run inside the Shadow DOM and vendorize some components to patch them accordingly.
One saving grace is that that LLMs are good at both coding CSS and answering questions about how it works.
That is the whole point of CSS classes: re-use. A CSS class is not meant to be used in only one very specific place. For that, you can select an element's ID or an elements HTML path, to style just that one thing.
It's like saying Rego[1] should just be done in a procedural language when in fact it also wouldn't be useful in that context.
CSS is about rules, selectors and cascading, hence Css.
Abstractions matter, and using procedural programming abstractions on a declarative styling language only gets in your way.
Writing CSS is not programming.
It's just not one based on states, mutability, and variables. Even the things that use the `var` keyword are constants, not variables.
(But then, don't read that as being against scoped rules. The fact that all rules are global to the document is bad. We can emulate scopes with specific selectors, but that's the kind of thing a language is supposed to help with.)
Constants which you can redefine/shadow in scopes, and change the values of at runtime via JS.
They seem like variables to me.
No, you can't. You can set a new value and reevaluate everything.
elem.style.setProperty(‘—var-name’, newValue);
… will set a new value for the “constant”. The element will rerender with the new value. You can animate/automate these changes and the element will continue to rerebder with the updated value.To me, that justifies the name “variable” from the perspective of the CSS.
It's our fault we pack all the rules in one file and ship it to all our pages.
"Shadowing" is on purpose it's the cascading part of the cascading style sheets. There are rules around which rule has priority read about selector specificity.
We've heard that one before, haven't we? HTML was supposed to be a declarative language, not a vanilla programming one. And look where we are... the biggest mess of a programming language the world has ever seen.
What's the wisdom of randomly inserting cutesy "declarative" bits in a world infused with programming-oriented infrastructure... It doesn't make any sense.
HTML5 doesn't refer specifically to HTML, rather it's "HTML + JavaScript + CSS". There's hardly a website nowadays that can be used without JS.
By using the name HTML5 as an umbrella name for a programming language API plus some declarative bits, the W3C tacitly admitted that the declarative push has been a mistake - I explained "why" in my previous comment.
The fact is, JavaScript is ubiquitous in web programing and the web is unthinkable without it, it's so pervasive on the front end that it's been repurposed for backend use precisely because it makes a lot of sense to use one programming language for one project. Pure HTML is unsuitable for backend use and it sticks like a sore thumb in the front end.
Younger developers are likely missing on the history of the entire web endeavor but in order to get a feel for it, I'd recommend to focus on practical meaning rather than on trivial semantics.
The big point I was driving at is this: The damage has been done, instead of a clean rendering API we've got this hybrid monstrosity which locked us to a couple / triple browser rendering engines which, due to cutesy BS, are complex beyond comprehension, beyond security analysis or normal competition. This is what an obsession with fancy names leads to.
Granted, when you add CSS to the mix, HTML+CSS is programming if you get fancy about it.
2. Custom properties can be scoped to a particular part of the DOM [1].
3. @function has shipped Chrome; custom properties defined inside of an `at` function are local custom properties. So are the parameters.
4. Local properties stay local unless the outside explicitly references them (which it can't without knowing they exist)
[1] Limit the reach of your selectors with the CSS @scope at-rule -- https://developer.chrome.com/docs/css-ui/at-scope
Tailwind is built on top of CSS. It is basically a library of hundreds of tiny "global", documented CSS classes.
This is how it works for me:
https://media1.tenor.com/m/QWdPngpHxZ8AAAAd/family-guy-css.g...
This is what got me. I exited development about eight years ago. Came back and was like, "WTF is going on with CSS now?" Completely lost and took me a few years working as an accessibility engineer to find my way back.
Its very hard having people telling you constantly how to "properly" use CSS, then learning all those techniques and approaches. Using those for a few years, then suddenly you have to completely unlearn it, then relearn it "the right way" again a few years later.
Completely maddening where front-end development has gone and continues to go.
I don't think that css evolved with specs, the HTML/CSS specs were descriptive rather than normative, and they came after the browser wars and the organic clusterfuck.
In my experience "CSS sucks" right up until you try to do a tenth of what it offers in something else. Cross-platform, device-neutral UI is hard. Then allow user-provided alterations?
It sucks and it's very powerful and flexible.
The serious answer is:
1. Many early web engines used `display: content-box`. So the padding was actually considered to be outside of the box itself.
2. Early web engines were strict about height-can-depend-on-width, but width-cannot-depend-on-height to avoid circular dependencies.
Padding top and bottom could be relative to parent height and padding left and right could be relative to parent width. They would not be the same. But it would still make sense. It would arguably be more logical than the selected behavior.
But the specific example does not even invalidate my point there is a whole website about css quirky behaviors and how to use them to your advantage, https://css-tricks.com/.
IIRC this was actually the spec, and IE decided to ignore it and do something saner, while the box-sizing attribute to pick what you wanted came later. Designing for content-box and IE displaying using border-box (or whatever it did) was one of the reasons it got the nickname "internet exploder" - everything ended up positioned or sized wrong. Until box-sizing came along, it was common to use various hacks / bugs in the browsers' CSS parsers to make certain rules only apply to certain browsers to fix this.
That's actually a little unfair on IE. This behaviour predates there even being a spec. IE and Netscape did it differently, and as a general rule Netscape's behaviour tended to be what ended up in the spec. This was mostly a good thing, but not so much in this case.
It’s because you cannot do a percentage of a height unless your parent’s height is fixed - something that happens naturally maybe 1% of the time. You’d be missing vertical borders in almost every case with your suggestion
Which is the actual issue. Learn CSS and treat it as part of the web stack.
I will give the people who work on CSS props though, they are the only ones interested in advancing browser's capabilities as something more than just a JS runtime, that is to be commended.
There are too many good features that aren't being added to CSS because browsers don't want to slow down on bad sites.
Look at MDN, the gold standard for web docs, on Grid: https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Grid...
That's just the basic concepts!
Now look at how easy MUI's Grid is: https://mui.com/material-ui/react-grid/
Atomics vs Usability. Everyone needs CSS. No one needs to *write* CSS.
I think you can replace nearly every use of Flexbox (and Tables for layout) with CSS Grid and have overall better dev ergonomics. The `grid-template-areas` tool and named areas can be great dev ergonomics far better than anything that came before it in CSS, especially if you have highly responsive layout needs and/or desire to decouple HTML source order with layout order (for better, cleaner accessibility, for one instance; or for cleaner streaming order on slow pages, as another reason).
It has a learning curve more than the simpler "Bootstrap-era" Grid designs, certainly, but I think it's an easier learning curve than Flexbox (but esp. if you've already learned Flexbox, because they share a number of concepts).
> It uses CSS Flexbox (rather than CSS Grid) for high flexibility.
- Linus Torvalds.
Source of the quote above -
https://youtu.be/o8NPllzkFhE?si=8vIMSR9qjVuFlvtt
If you don't want to watch the whole video, here's the exact part about the UI -
https://youtu.be/u4cI71pnFUc?si=DZqOaj6SE9yIh7Re
Transcript -
https://terence-xie.medium.com/linus-torvalds-the-mind-behin...
We have an entire design org that produces pretty UIs. FE developers are then expected to know the CSS rules to build that design.
The very first thing I teach new FE developers is how to build from Figma designs.
It is a feature, not a bug, that when the design and specification work is being done by the same person, the designs tend to be ones that are relatively straightforward to specify. It makes it a conscious choice to budget more specification effort towards elments that are more important to the designer.
Nobody said split design and specification. Specification is not development.
Anyone should be able to follow a recipe. And UI design generally follows recipes. Because UI’s simply suck when they don’t follow conventions.
Any good source of design recipe to share?
"Anyone should be able to follow a recipe" is far from reality, especially since the vast majority of recipes are not written for the kitchen illiterate.
Slightly less facetiously, "anyone can follow a recipe" makes about as much sense as "anyone can follow a README". Is it some arcane black magic that only a select few can decipher? No, but at the same time if you don't recognise that there is a baseline level of technical literacy needed to actually follow your average README then you might have your head stuck too far in a bubble.
Have you looked at a typical recipe recently? Here's an example (https://www.bbcgoodfood.com/recipes/oriental-egg-fried-rice) from the "quick and easy" section of BBC Good Food, a site that's regularly in the first page of search results for various recipes. Never mind that it expects you to have procured cooked chicken breasts from somewhere (and oh boy are those easy to turn into a bland, dry, rubbery mess if you don't know what you're doing)...do you honestly think there is no room in those instructions for someone who does not already know how to cook to screw it up?
Here's a recipe (https://urbanfarmie.com/instant-pot-jollof/) for a more complex dish that I am intimately familiar with, which is how I can tell you for absolutely free that if you just "follow the recipe" as described you will very easily end up with a soggy mess at best and burnt rice at worst.
Or - since you seem to like patting yourself on the back about onions - the next time you're following a recipe and it tells you to "sweat" or to "caramelise" onions or "sauté until golden", maybe spare a thought for how likely it is that someone who is actually new to the kitchen will get the correct result.
Talk about bubbles
My kids learned to cook from age 9. Now everyone can cook in this household.
I can’t take any adult who says it’s hard seriously, especially since I grew up in a culture where I heard a myriad of excuses from ‘manly man’ who think of it as a woman’s job.
It’s lame and it says a lot about them.
I don't know anything about tracking.
You can read all the programming books in the world. Actually writing a hello world program will teach you far more.
If you want to learn to play guitar, you need to start practicing simple chords long before you ever learn theory.
on edit: yes, HN cleverboots et al, I should not have written "language specification", you got me! However I challenge anyone of the especially clever people here to go write a hello world in some programming language that you know nothing about, without first looking up how to do it.
That is to say that while hardly anybody "learns the language" to write hello world, they do learn exactly enough of the language to do just that, and continue from there, until they get to some point at which they may feel to get deeper into the language. Thus the parent comment about people not learning the language was not exactly correct either.
Even as a developer with 30+ years experience, I'll write a dozen simple programs before I ever read a specification...
I'm looking for examples of basic control blocks, not esoteric edge cases for advanced features I don't yet care about.
The vast majority of what we learn is in a professional environment. I can't build a hobby app with hundreds of millions of active users. We learn at work, and that means sometimes it sucks. But that's why we have blameless cultures, because we all realize you can't learn unless you first do it in a shitty way.
It's also why AI replacing juniors is terrible. Juniors need to make mistakes and figure things out. That's how they become experienced seniors.
Not every tool out there has the same educational requirements. And there's no reason why they should.
1) Why is it using an NIH format instead of using XML or INI or something?
2) Why does it use symbols instead of words for selectors? HTML calls them "id" and "class", why does CSS call them "#" and "."? Yes you learn that quickly, but terseness isn't really defensible when the verbosity already exists in the other file that you download and edit more frequently.
3) It's too global. This is good for consistent styling but bad for modularity.
4) It's too much of a moving target. Best practice for html+css+js changes constantly.
5) The long history of stuff like "centre a div vertically" shows how it fails the "easy things easy and hard things possible" test.
6) Pseudo-classes are ugly and weird and were a way-too-late NIH thing.
I mean there are good reasons for it to suck. Anything that has grown organically since 1996 with no coherent versioning or deprecation strategy is going to be a hot mess. But it is what it is.
AFAIK, CSS syntax is inspired by the syntax of STTS, and STTS intentionally didn't use XML because it's a pain in the ass to hand-write and hand-read. I cannot argue with that assessment.
So CSS's syntax was based on an existing syntax, but it happened to be a syntax that didn't catch fire (which is so often the history of such things): it made plenty of sense at the time when the devs were looking at the options and maybe went "Well, we know XSLT and... It sucks and is hard to use, so what alternatives are there?" And STTS was apparently billed as an XSLT that human beings could write and read.
2) doesn't seem to be a very big issue, this kind of stuff is very common in many programming languages as well. I don't remember struggling with this even as a beginner, and it's the first time I encounter a complaint about this as well.
3) Fair point, and the inheritance and specificity rules are very complex as well
4) On the other hand, backward compatibility is stellar (and I guess that it's your point in your last paragraph). Your 20 years old CSS file still works today and doesn't even feel really out of place. We could wish the web platform didn't evolve so rapidly, it makes it very difficult to implement.
5) It's very easy to center a div vertically now. Therefore, it can only be a critic of old versions of CSS, not the current one. Do you have another example of basic things that ought to be easy but aren't, or aren't possible?
5) Doesn't seem to be a very big issue. I wish the double colon syntax didn't exist and we'd just use single colons, but as you say, it is what it is
Single-colon is a pseudo-class, for targeting elements based on some external state. I learned these as "pseudo-selectors" but it seems that's not the right name.
Double-colon is a pseudo-element, for targeting inner parts of an element that themselves aren't actually an element in the document.
CSS 1 & 2 apparently conflated the two, and CSS 3 allows one column for CSS 1 & 2 pseudo elements. I never noticed it wasn't all of them. Since I learned CSS right before CSS3, my situation kinda makes sense I guess.
Single colons everywhere have felt easier and more regular to me, so I've written basically everything with single colons except maybe the odd CSS 3 pseudo element here and there. But it seems the two colons will be mandated going forward.
I guess I'll have some edits to do, though I do hope and kinda expect they won't break backward compatibility.
https://stackoverflow.com/questions/17684797/should-i-use-si...
The original suggestion was LISP-like or X.11 configuration file syntax (https://www.w3.org/Style/CSS20/history.html) - XML was still too new (but look at https://www.w3.org/wiki/Xsl-fo if you want to see what the W3C came up with for "styling, but in XML format for XML documents"). My guess is that the declarative shape imitates SGML with a C syntax to make it easier to understand.
> It's too global. This is good for consistent styling but bad for modularity.
Yeah, that was an explicit design choice - one that we're now asking for (and getting) more control over as the web continues to expand, but it's not like it wasn't considered, it was considered and rejected for MVP as it were.
> Pseudo-classes are ugly and weird and were a way-too-late NIH thing.
https://www.w3.org/TR/CSS1/#pseudo-classes-and-pseudo-elemen... were in CSS 1 released as a specification in 1998. Ugly-and-weird-and-special-cased ... sure, but what would you replace them with?
It gets painfully clear if you want pixel-perfect layout on every desktop screen, mobile screen, and browser. YMMV, and PDFs will be around forever now... =3
"Print length : 1126 pages"
Ok, I'd say it's legit.
If you can fully explain JS (an inexplicable bodge built on a tower of inexplicable bodges) in less pages then CSS almost definitely sucks.
But yeah, many people learn the intended syntax, but don't learn the actual clusterfuck of its backwards compatible standardless behaviour. I'm convinced you can do almost anything with just html,css and maaybe a tad of vanilla js.
This really isn't about CSS, it's about screen hardware - and the thousands of constantly evolving products in the market.
I think this is best evidenced by our constant innovation of news ways to undermine the "cascading" part of CSS and introducing scope wherever possible.
The solution is a careful consideration of scoping: most programming languages encourage the developer to carefully consider whether a variable should be local and global, and a similar amount of care must be taken in CSS too. The programmer needs to have a high awareness of which rules should apply to the whole document and which should apply to this particular component.
That's one very strong indicator that you are doing it wrong.
Good luck.
.container {
display: flex;
justify-content: center;
align-items: center;
} .container {
display: grid;
place-items: center;
}The analogy with learning programming languages is helpful to get the point across but pretty inaccurate. Most of us should treat css more seriously (I for one just want to get done with it as soon as possible), but it's not realistic to compare it to programming. It's like comparing building a sandcastle with building a house.
If I have an element with a class on it, there are multiple selectors that can affect it.
It can be because it is contained within another element, because it is an element, because it has a class, because it is an element with that specific class, because it is next to an element, and many others.
And deciding which rule gets applied is work.
Not that this cannot be overcome with some kind of spaced repetition or daily practice over a period of time; it's just more effort than most programmers will bother with.
Relatedly, too many factoids and gotchas are the reason why I gave up on C++ after nearly a decade of reaching significant expertise with it.
And what really made me hate frameworks is that as soon as you decide on which framework to use, it's now out of fashion, and the wider community is laughing at you for choosing the wrong framework.
Still, anything that lets you get more done with less toil for Work Stuff is probably a good thing. Yes, this even includes Tailwind Font Tags 2.0.
there’s a deeply elegant language hidden in there with unbelievable support for generic programming, however it is practically impossible to do that in a component system and the current state of CSS editors
i find it hysterical we design component libraries where the only acceptable way to extend the design of a component is add a prop when CSS has a perfectly elegant way to do this without muddying up the component source
not to mention the dark arts of encoding show/hide/position/more logic that is often done in js
it is the saving grace of the web, but never has been realized
You have to be able to visualize, from outside-in, the Matryoshka doll of naked structural elements that make up the component, page section, or entire page you're styling, ensure (or hope and pray) they have sane identifiers (id, class, attributes, etc), then start to write out properties like you're writing a recipe.
This was the whole point of CSS Zen Garden [0] -- offer a static, common structure and challenge people to reskin the same thing 1000 different ways.
Now, I do recognize that I'm coming off a little dismissive of the complexity of CSS, and that's not my intent.. I'm one of those people who is a good graphic designer, good developer, and often conceive, design, implement and deliver projects end to end, so when I'm in Photoshop I'm also mentally laying out how these designs will be structured in HTML to then be able to be implemented.
Naming conventions between markup and styling are also important to be able to translate from bitmap to browser without losing context, and I know we're "post-Sass" by a lot of opinions, but I still find writing nested SCSS far more manageable and readable than plain CSS.
Break everything up into discrete components and files, name them well, use box-sizing: content-box to make sure your borders and padding get included in dimensional calculations, imagine in your mind the physical structure/skeleton of the markup, then fill out each part, piece by piece. Browser dev tools to inspect and modify styles in realtime is critical to playing around until you get what you want.
That said, IMO the only way to really get comfortable with all of that is to do actual projects, not just tutorials. There are 1001 ways to achieve most things in CSS, and the sheer scope of the spec is impossible to grasp without constantly looking up what property does what, but it really does just boil down to taming all the boxes on the page one by one.
Just one example most people already know. If I set a height or width on an inline element, it's ignored. So, obviously there is a limitation in the renderer that can't do it. But wait, make it inline-block and suddenly it works! So why the f*k didn't it just honor the width and height to begin with? It's quite literally a rule for the sake of having a rule.
I don't doubt there is some deep dark reason for why it is the way it is, like optimizations, or backwards compatability, but it doesn't matter to the end user. It's an implementation detail they shouldn't have to bother with.
It's like wondering why this grape doesn't taste like fried catfish. They're both food. Why don't they taste the same?
Width and height are meaningless for inline elements, but automatically changing the display would be more confusing, not less.
Really not sure what you're trying to get at there, obviously any element that displays will have a width and height. Maybe you meant a user specified width/height, but the entire point of my post is an inline-block is an inline element with a specifiable width and height. And we've always had the IMG tag, which is also an inline element with a specifiable width and height. The obvious and intuitive choice would have been to not put artificial limits on inline elements.
You could even do something crazy like `* {display: block;}` if you really want, and then go from there. Nobody can stop you. The freedom is yours.
The abandoned ideas I have in mind were all around user stylesheets. I know some folks are going to dig up an amazing demo. In the wild, this just never materialized. Remember back when browsers would give you a built in way to manage your own stylesheets for sites?
The bad idea, to me, is the whole recursive concept for sizing. I legit cannot think of a good reason to have a constantly recursive application of sizes. Which, I think if you stuck with the standard elements when CSS was started, you could argue that this makes a lot of sense. As soon as we all accepted that a tree depth of 20+ divs is just normal, that went out the window.
Which, fair that you could blame the latter on HTML going off the rails with how we explode things into a DOM. Doesn't change the fact that trying to set relative sizes is almost certainly going to bite you in the ass.
Edit: I should also add the hilarious fight between the different browsers on default box-sizing. Or how we spun our wheels for a long time before adding flex/grid to the standard. How many years was the recommendation not to use table for layouts, without having a good alternative for the times when it was the easiest to reason way to design something?
Nested widget heirarchies that are 20 deep are a dime a dozen in native desktop development. If you want to argue that this reflects poor UI/UX design, be my guest, but that's the way it has been for 30 years or more. Web design wasn't like this in 1995, but as the platform has evolved to support almost any kind of UI-driven application development, it has also picked up these long-utilized models from that world.
What CSS has added, which I view as an entirely good thing, is to extend the notion of rule-driven box packing as the fundamental underlying layout model. GTK realized the sense in doing this when the development of GTK3 began, and other desktop toolkits on all platforms have picked up either all or most of the same fundamental model for layout.
Native and web-based UI implementations are ever converging on the same models, and CSS has been the crystalizing force in that convergence, along with its recursive, fundamental box packing (sizing & positioning) concepts.
I remember learning the different Java Swing layout managers back in the day. Again, being nested was fine. That said, if you were doing a large layout, you were probably reaching for GridBagLayout. Back in 1999... (And I recall that SWT layouts were even simpler?)
I'm willing to concede that many of the ideas in CSS are good. At the least, benign. User stylesheets were just flat out a rake in field, though. And I stand by the claim that percentage sizes is largely a massive foot gun.
Edit: I should say that I find native interfaces took a massive nose dive in many ways when we abandoned so many interface builders. I have no idea how nested your typical MS Access form was or was not. I know that designing and wiring them up was far easier than what I typically see today.
Shared library components is where this could work - each individual application would be able to scale the component's size to what it needs.
But the native toolkits have learned from CSS in many ways, and that is just accelerating as we see what new wonders get cooked up in a web context that people used to say "you just can't do this in a browser with HTML+CSS".
Where web development sucks is when we try and rube goldberg getting an icon where we want it, or anything sized the way we want it. It is akin to forcing yourself to play mouse trap every time you want to align something. (With some common alignments still just not supported? Or can we decimal align numbers easily finally?)
Vertically aligning a set of decimal numbers with the separator the same place would be challenging in GTK and Qt and several others, unless you make some not well-supported assumptions and simplifications.
And reflow is generally being handled much better in most web apps than it is in native ones, if the latter actually allow it at all (more likely, they set a minimum window size that handles the expected layout just fine).
Also interesting to note that the the much lauded arrival of constraint-based layout across all apple GUI toolkits about 10 years ago (driven in large part by the needs of iOS) has not revolutionized layout APIs or algorithms in general.
At least in something like GTK and Qt you would be more than justified in just punting on the semantics of the receipt and formatting a fixed width set of numbers to call it a day? In HTML, doing that feels extra wrong. (But, indeed, you can do the same "fixed width" with non collapsed whitespace, even in HTML.)
And it isn't like this isn't a somewhat solved thing in long existing layout engines. Aligning to variables and such is very common in math texts. And largely not doable in HTML.
Reflow is one that always strikes me as largely misguided. No amount of reflow will make most websites look good on a gigantic monitor. Same as no amount of reflow will make most documents handle someone's name that is actually a novel. It just doesn't make sense, for many reasons. And yet we will put forth herculean efforts to maintain "reflow" based on content in so many places.
Even in Firefox, the dream of meaningful styles across sites is largely dead, I thought.
There are people who read that?
> Everywhere else? Good luck.
Same as with alternate stylesheets or a reasonable line of death. For all the annoying things Mozilla does, Firefox is still a great browser and for some measures the only shop in town.
> meaningful styles across sites
You can also modify the browser chrome with it, and I think UBlock Origin uses it for modifying the page. Also some settings are exposed via a UI, so also lawmen not knowing about user.css might still use the user (agent) stylesheet.
That is, there is no nested reusable unit.
The number of CSS pre-processors that have been invented to fill this gap is obscene.
I use HTML and Modern CSS for frontend. I sprinkle htmx when I want interactivity and a tiny amount of plain JavaScript. That gives me a mostly declarative frontend.
On the backend I use Haskell, which is also declarative unless you opt into other things.
The challenge with web development is that we’ve learned over the years that asynchronous, stateful programming is the most bug-prone programming yet we reach for it first. We should reach for those things last and where they are appropriate.
The thing about cascading style sheets is that it all cascades by default. A web page naturally resizes. It’s when we add all this other stuff that things start breaking and becoming rigid. The key to CSS is knowing when to let go.
I recommend Josh W Comeau's CSS for JS devs [0]. If you've seen his other articles on CSS and on web dev in general [1], you know that he's a great teacher of complex topics.
The course is priced for corporations to buy via their employee development budget, which is how I took it, so for individuals it is steep, but if you can convince your employer to pay, I don't think there's a better CSS course out there.
If you want a completely different menu on mobile, well, you're going to have at least two menues.
Should images keep their aspect ratio or be stretched? Minimum size in pixels or as percentage? Should the image container constraint the image or should the image push the container's boundary?
I often ask people what they want to happen. Rarely can they describe it in words – how do they expect to write CSS? Of course they're going the explorative route.
I didn't spend any time learning Python. I just started using it and was fairly effective immediately.
I already knew programming in general of course, and several languages with similar features. It takes years to get good at programming, but adding a language that doesn't contain any major new concepts shouldn't take a long time for a proficient programmer.
There are things that are hard but have gold at the end of the rainbow, like SQL. CSS isn't like that. Idk about R, I ragequit it too fast.
Web frontend as a whole is a dog chasing its tail.
@scope only works for selectors you add, but there are a ton of properties that even break through closed shadow roots.
Just as one example, there are now, by my count, at least eight[0] layout models (column, anchor, positioned, flow, float, table, flex, and grid), plus several things that sit in some ambiguous middle place (the inline versions of block types, sticky positioning, masonry grid layout, subgrid, `@container`, paged media), each of which is different and each of which interacts with the others in various confounding ways. Flow collapses margins; table elements can’t have margins at all, but tables can have `border-spacing`, which is like `gap`, but different. Flex has a different default `min-inline-size` than flow, and `flex-basis` overrides `inline-size` if it isn’t `auto`, which is its initial value, until you use the recommended `flex` shorthand, at which point it becomes `0%`, unless you redefine it explicitly. Table layout[1] uses a special shrink-wrapping algorithm, which the CSS authors noted back in CSS 2 might make sense to add a way to work more like a regular block-level element, and then that just never happened. Grid is a mix of implicit and explicit placements with competing ways to do the same things (named areas, number ranges, templates on the parent, properties on the child) and a bunch of special sizing algorithm keywords like `minmax` and `fit-content` which only work in grid, some of which also work in flex, most of which don’t work in flow, but some of them do now, but they didn’t before.
You can select your elements with the old CSS 3 selectors, or `:where`, or `:is`, or `&`, or `:has` (but not if they’re nested), or `@scope`, or `@layer`. Definitely don’t try to put trailing commas on your selector lists, though, since that’s not syntactically valid in CSS, until it is, in some future revision.
To make sure your site works correctly with all scripts, all the directional keywords now have logical versions with `inline` and `block` keywords. Unless it’s a transform[2]. Or a gradient[3]. That’ll probably eventually be fixed, just keep checking the spec periodically until you have to re-learn something that used to be false is now true. Which is how “learning” CSS works. There is never an end.
And this is just the tip of the iceberg. There are also all the CSS units, colours, the whole animation engine, forms, pseudo-classes, pseudo-elements, containment, paints, filter effects, environment variables (yes, those are a thing), maths functions, overflow, scroll snaps, backgrounds and borders, feature queries, font features, writing modes, the different-but-not-really CSS of SVG, the half-forgotten weirdo things like `border-image` and `clip-path`, or the half-dozen other major and minor CSS features which I am not even thinking of right now.
CSS doesn’t suck “because we don’t bother learning it”. CSS sucks because its core strength is its core weakness. It is infinitely flexible and extensible, and that means it has been flexed and extended to fulfil every design trend and address every edge case. Then it needs to support all of those things forever. Making CSS do what you want as a web developer has probably never been easier, but “learning” CSS has never been harder.
[0] Please, for my own sanity, resist the urge to pedantically nitpick in the responses about whether everything in my list is actually a “layout model”. I am aware that some of these things overlap more than others. This is just my list. You can make your own list. It’s fine.
[1] Tables also create their own anonymous layout block such that a child `<caption>` element is drawn outside the putative `<table>` in the actual layout. Framesets do a similar thing with `<legend>`. These are all things that are the result of having to retroactively shoehorn weirdo features into CSS in a backwards-compatible way, but that doesn’t make it any less insane to learn.
That said, I'm not a pro. I asked ChatGPT for some layout primitives which it gave me and I then I probed for things that stood out as strange to me and it gave me lots of background and why things are as they are as well as why they can't automatic.
One that stood out was this:
Me: No native UI framework in existence has the equivalent of min-width: 0. Somehow they all get by with just layout primitives
ChatGPT: native UI toolkits do not expose anything equivalent to min-width: auto (intrinsic min-content) as a default constraint. They get away with pure layout primitives because they made a fundamentally different architectural choice than CSS.
This isn’t accidental, and it explains exactly why CSS feels broken here.
The core difference (one sentence)
Native UI frameworks treat content as flexible by default; CSS treats content as authoritative by default.
Everything else follows from that.
What native UI frameworks assume (and CSS does not): Across Cocoa, UIKit, WinUI, Android, Qt, etc., the default assumptions are:
1. Text is allowed to truncate
2. Containers decide layout
3. Content adapts to constraints
4. Overflow is normal
5. Intrinsic size is a preference, not a hard constraint
In other words: Layout constraints dominate content.
What CSS assumes instead: CSS’s default assumption is the opposite:
1.Text must remain readable
2. Content dictates minimum size
3. Overflow is an error
5. Intrinsic size is a hard constraint
In other words: Content dominates layout.
That single inversion is why min-width: auto exists — and why no native toolkit needs it.
After that I asked it could it give me CSS primitives that work like native layout. It did, and it came with all of the issues brought up.
But to the point of the article, it’s a technology one has to learn. There are name spacing solutions in css (layers) and around css (css modules, panda, tailwind, etc).
I think another challenge folks may have with CSS is thinking visually. It’s not automatic. In art school one learns both how to see and how to render, and generally learning how to see clearly is a bigger challenge than learning how to render.
Practice your craft.
Some simpler webgl based grid layout would be much nicer imo.
Pretty easy to have a concept of grids and subgrids...which is pretty much what people abused tables for (still required for email clients shudder)
nailer•1d ago
A card with a top image, some text and a button - which should be...
- A card
- A top image
- Some text
- A button
ie 4 HTML elements, ends up being about 10 HTML elements with various strange hacks in the div-soup HTML the models have scraped from Github.
Then someone else comes along and uses tailwind, because naming 10 arbitrary HTML elements (rather than .card, .card img, .card p, .card button or similar) is hard. They're right, but the problem is they didn't need that many elements in the first place and wouldn't if they'd just learnt CSS.
moi2388•1d ago
icedchai•1d ago
Tomte•1d ago
nailer•1d ago
h_ko•1d ago
CPLX•1d ago
Levitz•1d ago
CSS has gotten much, much better, which is why it doesn't suck so much these days, but come on now, using a div with a background image was a common practice. There were like, what, 3 different hacks to center an element inside another?
People don't just opt for a plethora of different tools to deal with it "just because".
nailer•1d ago
Claude and Grok output garbage:
https://claude.ai/artifacts/fc5ef98b-a9f8-48c9-b0ea-b60c778d...
https://grok.com/share/bGVnYWN5_a5cab471-1c3a-42ab-a25e-c491...