108 comments

[ 2.9 ms ] story [ 196 ms ] thread
Assembly is not trivial lol. The instruction set is easy to learn yes, but the kind of bit manipulations that occur at ASM are not easy or simple. Look at optimized division sometime. Try reverse engineering, it's an art that takes decades to learn. I do agree with "Anyone who can learn CSS can learn assembly" though, anyone can learn pretty much anything with enough time and effort.
"Anyone who can learn, can learn."
I mean.. technically it's still a simple, easy to learn language,... but doing stuff with it, requires a lot of knowledge about 'stuff' (mostly math in your case).

To steal from some other comments here... a (wood) chisel is an easy tool to learn and use.. a lot easier than a CNC machine... but building a wooden boat with a chisel is still hard.

sensationalist title, ASM is much more complicated than CSS
Right. At least there's only one CSS specification isn't there? There's a whole heap of different assembler languages for different ISA's out there.

It's like comparing one apple with a bunch of oranges.

Please forgive me for straying off topic a bit, but:

- I just picked up Jeff Duntemann's newest Linux assembly book, x64 Assembly Language Step By Step —get it from your local indie bookseller

- I want to get Dennis Yurichev's book Reverse Engineering for Beginners, a.k.a. Understanding Assembly Language, at https://www.beginners.re/

I'd rather spend the rest of eternity doing CSS nonsense than have to look at another line of AT&T syntax. I have several percent signs permanently seared into my retinas.
Advanced results require advanced skills.

CSS is one of my favorite languages. And the only way I can consider CSS to be difficult is if you have no experience with HTML. If you try to do HTML by hand, then doing CSS by hand on top of HTML by hand is really easy and wonderful. And this is truly where you gain the fundamental framework for "getting CSS".

My experience was completely the opposite. Learning HTML was effortless, and I had a great deal of fun writing pages by hand, easily creating whatever I could imagine through a straightforward hierarchy of nested tags. When CSS came along, it added a slippery, inconsistent layer of confusion where spooky action at a distance was the order of the day; nothing ever worked completely right, no matter how much time I spent grinding on it. I never could get comfortable with CSS and eventually gave up web development rather than continue fighting with it.
Yeah CSS is a complete nightmare. Nothing works and you never know why. The only thing you can do is to randomly change attruibutes randomly until something happens. I remember working on a simple website and i had to do a gradient banner. The gradient was relatively simple but the true challenge was making it stretch edge to edge. No matter what i did there was always a little bit of padding or the layout was completely off. I don't even remember how i solved it.
Handcoding/server-generation HTML running CSS via SCSS with no frameworks is a truly fulfilling experience. Especially if I get to mix in some SVG. I'm one of the few that outright hates JS, so I'm always glad when I get a chance to get back to my favorites.
nah doing the same exact thing in CSS is like different every other year because someone invents a new attribute to solve the old friction

and its like what

and its like how is everything so compatible so quickly now

and why do I have to do it this way

and why does the interviewer expect this answer instead of last years solution to the same problem

I currently like tailwinds.

but dont ask me to set it up from scratch in a typescript project, but fortunately the bun runtime makes that simpler now, for now

I have yet to find a frontender (and I have worked with 100s over the past 30 years) that can do any significant css without trying it out in a browser; if there is something off or needs to change on the frontend, very often the most experienced senior frontender can guess (and often a little bit right) what it is but to actually fix it they have to try a few times.

To me (someone who likes logic) that is a sign it’s all not very good. I can write a bunch of code on paper in several programming languages and even non web frontend frameworks and it will work after I type it in first time ; when it comes to web frontend, it has to be tried out to know it works as it likely will have issues (unless it has no css layouting of course or absolutely trivial prototype stuff).

It seems like you're not comparing apples to apples. Investigating someone else's code to alter it is always going to be harder than writing new code, even on paper in several languages.

I do think that CSS has enough footguns to say that arbitrary CSS is not very good; well-written CSS is a very small subset of CSS in general. It joins many other languages in that regard-- C, C++, Javascript, PHP, Bash, the list goes on and on. As in all of those languages and more, with some basic familiarity it's not hard to sling some fresh code together and have it do what you want. Making it scale maintainably is the hard part.

(For my 2 cents on the matter, the way to write Good CSS(tm) is using CSS modules to limit scope, using flexbox or grid for all layout, and being rigorous about creating stacking contexts when you need to modify z order. Application of these three rules has made my life as a senior frontend engineer generally quite easy.)

Great design is precisely what allows lifting the requirements for advanced skills. Poor design resorts to manual editing of ugly markups
What does learning assembly language mean?

So right now, learning CSS is pretty difficult. But luckily CSS specs have gotten pretty similar over different browsers, so its not terribly difficult even though some things are not exactly perfect.

But Assembly Language is rather straight forward, but the difficulty is that "assembly" is really a hundred different languages that depend on the specific processor architecture you are running on, and how that platform operates.

They are really orthogonal issues in the end, and comparing them is like comparing apples with automobiles.

Pedantic nit: CSS specs are consistent across everything, because there's only one spec. (ignoring previous versions)

Specs generally aren't the problem. It's implementations. But those are mostly pretty good now too.

When I started in webdev around a decade ago I remember having to work around all sorts of annoying cross-browser inconsistencies (floats, margins, box-sizing, etc). I haven't kept up with all the latest updates (need to brush up on grid layout) but I feel like I rarely if ever find myself in those situations anymore.
Yeah, I've authored assembly and CSS professionally (not at the same time) and would choose CSS all day long.
I've never written assembly but would assume CSS has better tooling available? browser dev tools for example
In many, many ways, assembly is more straightforward, but I went with CSS just because of the ability to see the results and to poke & prod with browser tooling.
As a counterexample, I have also authored both assembly and CSS professionally (not at the same time), and I chose to completely abandon web development after endless battles with kludgey, inconsistent CSS vacuumed all the fun out of it.

(I imagine the situation may have improved over the last 15-odd years, but I'm not going back in to find out.)

I still enjoy assembly programming, though opportunities to use it have become a very rare treat.

I've done both CSS for about 26 years (since its first release) and Assembly language for about 35 years, and I love both of them - for different uses and different reasons. They are both great for the job they were meant to do. I even once wrote a JSON parser/serializer in 8-bit Assembly so the embedded device I was building could easily communicate with the browser front-end I had built. It was all pretty fun to me.
This feels kind of like arguing that python is more difficult than brainfck because most people couldn't name all the ways to mutate a python object, and brainfck only has a handful of operations. CSS isn't (that) hard*. Modifying someone else's CSS and tracking down what selectors apply what styles is hard - but that holds true for any language, understanding code is harder than writing it.

*(other than positioning, that still kind of sucks, even with flex/grid)

I don't understand the CSS confusion. Maybe because I've been doing it for 15+ years but it's extremely intuitive to me and I love working with it. Tailwind annoys me because it removes some of that flexibility / freedom for me to just solve a problem immediately with a new class or something.
The point wasn’t that CSS is necessarily confusing but that if you can learn CSS you can learn assembly and by implication write better performing software.
It's because of the inconsistency.

For example, `margin: auto` expands left/right margins but not top/bottom margins.

....and 50 other such cases.

Not a CSS guru but I'm pretty sure that's because display: block (the original document layout strategy?) grows vertically, so it doesn't really make sense to have an auto value for top/bottom. And I believe margin:auto only applies when there is a width constraint in the element.
There are Reasons(TM) for it.

And yet when flexbox was created, there was no horizonal/vertical difference.

I'm not sure about that, flexbox has a major and minor axis, which you can define with flex-direction.
As I said, there is no inconsistent treatment of horizontal and vertical.
I never thought of that as an inconsistency, but rather of a feature. My thought is: Layout is left-to-right so why should something work top-to-bottom? Same as text-align: center will center horizontally, and (/s) vertically centering something is impossible.

But I agree with the basic sentiment. The small irregular things [1] make it really weird to get, but once you'll get it, it's crazy cool. However, that does not make a language great.

[1] https://stackoverflow.com/a/17468803

Same sentiment here. The way margin works makes sense to my brain that lives in an HTML/CSS world.
That’s not inconsistent, that’s just reflecting how our writing system works. CSS was designed around the idea that there is a document consisting of text, which implies the X and Y axes work differently – because they work differently for our writing system.

Text goes from left to right, then wraps back around to the left moving vertically down (obviously this is for RTL languages; adjust for different writing systems). So this means that there’s a left and a right edge, which means that centring something horizontally makes sense – the mid-point between those edges is the centre. But it also means that there’s no real bottom imposed upon the text – the text starts at the top and just keeps flowing downward until it runs out. So centring something vertically isn’t the same sort of thing as centring something horizontally.

Or to put it another way, the horizontal edges are imposed by something external to the content (often the viewport), and the bottom vertical edge is defined by the length of the content. The two axes are treated differently by CSS because they are fundamentally different.

If our writing system were turned 90° on its side and we wrote downward until we reached the bottom of the page then moved back to the top and right one line, like some traditional Asian writing systems, our browsers would scroll left and right by default and you would be complaining that `margin auto` expands top/bottom margins but not left/right margins. It’s the writing system that works this way, CSS just does what is sensible for that writing system.

Later on, more layout systems like grid were introduced by CSS that weren’t based upon the flow of text, but things made logical sense before then as well.

This doubles as a perfection explanation of why the web is such a terrible technical platform for rich client applications. All of the assumptions baked into the foundational design of HTML & CSS were based around the idea these would be used for creating lightly styled documents.
> that's not inconsistent it's just inconsistent

> later other systems were introduced that weren't inconsistent

I don't understand either. I understand that CSS can be tricky sometimes, but more difficult than Assembly? Well, admittedly I have no idea of assembly or pretty much anything outside of your typical web stack, but it seems more difficult to me from the distance.

Not to mention game devs doing GPU stuff. I regret committing to programming with 30yo, in my 20s I probably would have the time and energy to learn much more.

I can do working assembly on paper or in my head, css I cannot. So yep, easier. I have similar amount of experience with both, I just don’t consider css logical. While most assembly is (there are exceptions of course, but talking about pure assembly).
I think Tailwind is nice when you're applying to-the-element but as css continues to grow and include more relational selectors I think we'll start seeing a more definitive line drawn in the sand where we just use css/css modules for the more advanced/relational parts and Tailwind for the to-the-element bits.

As for why it's confusing, I think it's due to the inconsistencies of the language. https://wiki.csswg.org/ideas/mistakes

Also, you have to know the rules of the game to be proficient at css, and the rules will change from underneath you based on context, and unless you're in this space often it will often feel like voodoo and a constant search of "why isn't this working here when it works there... oh, because the parent is using position x". Also messing with css for over 15 years I know most of the rules of the game, and it has definitely gotten easier over time, but every now and then something will still surprise me.

> maybe because I've been doing it for 15+ years

yea, that's about right, except the maybe part

Anything anyone's been doing for 15+ years starts to feel easy, because any component that takes a year to learn how to do (which is, by any measure, something quite difficult to learn) you've known for 14 years.
I saw your user name. Wink, wink

I knew about HTML/CSS around 2004, and knew about C++ in late 2005 - so kind of about the same time, almost 20 years ago.

Both of them have evolved and have had substantial additions since then, but I can't imagine that I'd say "C++ is easy!" if I kept putting my nose on it all this years - even back then the pointers thing (and pointers to pointers, to be more specific... won't even think about all its new stuff) was absurdly difficult to understand for me. Whereas the concepts behind CSS were much easier to understand, the difficulty I found about it (and what I suspect people say it's "difficult") was in its implementation - styling for IE was a living hell, and after that all the gibberish we had to do to support -moz, -webkit, -o, -ms and co, and now all the platforms, modes, layers, medias and all of that we have to take care of. But I repeat - it's not that the core of what CSS does or how it works is the difficult part.

For a long time, simple things like vertically centering dynamic text were impossible to do except with JavaScript or weird hacks. Or how do you push a page footer to the bottom of the viewport on pages where the content is only a few lines? Or create a two-column layout where the left column has a different background color that always stretches to the bottom of the viewport?

There have always been a ton of common, simple things that CSS just didn't support, or required bizarre hacks for -- like reusing "floats" intended for inset images as the basis for layout. Over the years it's gotten better, but if you've been doing this for 15+ years, surely you remember the old horrors. I don't want to have to insert "clear: both;" at the start of every new section ever again...

Not to mention that back in the day, browsers weren't nearly as standards-compliant, so your designs would just show up wrong in some browsers, and you'd rip your hair out trying to write CSS that would work in all of them.

For sure, the stuff 10+ years ago was pretty goofy and the amount of hacks required even further back to make it work across 4+ different browsers was super annoying. I guess I'm not thinking about all those growing pains today.
(comment deleted)
>Maybe because I've been doing it for 15+ years but it's extremely intuitive to me

I mean... yeah?

That's the benefit of doing something for 15 years, it's intuitive and no longer confusing.

Ok here’s one. If you have two inline-block divs with no border or margin and you give them both 50% width, they should evenly split their parent div, right? Wrong! You need to set the font size to zero on the parent otherwise the html formatting adds extra space after the first div.
I’m sure experience is part of it, but having worked with CSS since roughly 1996 I’ve noticed that there’s a heavy respect gradient where a lot of developers thought it’s beneath them, not a real language, etc. which is also shared with HTML, the layout model, etc.

None of that is universal, of course, and it’s not like CSS is perfect but the worst code I’ve seen was written in near-contempt by, for example, some dude who wrote many thousands of lines of … not brilliant … code to make a Java display framework because he refused to learn how CSS works. I was called in to that for performance reasons because if you don’t understand classes, you can end up with 20MB HTML responses with the same inline styles everywhere. That was an outlier but I’ve seen a lot of similar attitudes where someone shipped 4MB of JavaScript to avoid learning CSS positioning or tried to get a designer to edit their code because they thought adding IDs or making semantic, accessible markup was beneath them. One interesting social dynamic there has been the guys who simultaneously refused to deal with front end stuff but also didn’t think it should pay well, often with more that a whiff of sexism given how designer was coded female at those places.

That’s improved in some ways as front end work became more central in the SPA era but it’s still pretty easy to find people who’ll deploy enormous amounts of code to avoid using a builtin browser feature or whine about how “the DOM” is too slow as if it’s the browser’s fault they’re using React.

Same here, it's like a weird language where I've spoken and seen all the edge cases. Still remembering hacks for IE6 and still felling good not doing them
Listened to this episode the other day. I can recommend, its funny and gives a fresh perspective, even if I don't agree with everything
Ok I dont have time to listen to the podcast, and could not figure out which one it refers to. But I'll bite on the headline.

CSS is difficult because it was not designed with logic as input as a programming language.

It was designed from expected print output.

"I want to do this thing that is popular in New York Times magazine".

Floats, run-in, first line, multi column.

Static papers that were never meant to move around. And you were never meant to have floats in a float or first line with a different font size inside an auto width table.

This is why it is so riddled with edge cases.

This is a really interesting perspective. It does seem like CSS is "reverse engineered" from expected output rather than the other way around.
That's not at all true - it took ages before CSS added multi-column layout.
Both can be true. It took long to make it into the specification yes.

But I am certain it was part of the original drafts. Just hard to implement so it got no extra push from the implementation side.

If you are trying to "learn" a living language cover-to-cover, so to speak, you are doing software engineering wrong.

Is the tome of CSS more pages than the tome of x86? Maybe, but I'm not gonna read either cover-to-cover.

This just in: learning to use a CNC is more difficult than learning to use a saw.

---

> Learning CSS is dramatically more difficult than learning assembly

And styling with assembly is dramatically more difficult than styling with CSS.

(comment deleted)
The point of Casey's rant in the OP is that CSS is incredibly complex with a poorly defined spec, and yet at the same time its also a terrible layout engine.
(comment deleted)
there's CSS and there's CSS.

macro layout stuff with complex component structure, shape changing web components, multiple scrolling divs, sticky footers, animations, lotta state changes, cobranding, 5-10 year old code base?

Yeah it starts to take a dedicated expert vs a dev who "knows CSS"

That contributes to the overall difficulty.

Where do you draw the line between CSS and CSS?

I think the fundamental lesson for me was to utilize the cascading nature in small, very clear logical units of tags. And don’t try to implement a grand unified theory of style for your website where everything is based on a brittle chains of selectors. It’s okay to give tags ids and select by the id instead.
CSS definitely gives you plenty of rope to hang yourself with if you aren't careful about how you choose to apply it! I've been in a few codebases with lots of !important overrides and deeply nested selectors which quickly becomes unmanageable.
Eh, as someone who's used both I'd probably disagree with that. CSS is at least a hell of a lot easier to debug than assembly, depending on the device you're writing the code for.

But it's a weird comparison anyway. The difficulties in CSS aren't using it to begin with, they're about all the edge cases, browser compatibility issues (for the more modern stuff) and its limitations for handling layout setups other tools have handled for years. Meanwhile, assembly's challenges are often that you have too few tools, and a lot of the language patterns you're used to in modern day programming languages are nonexistent.

Like the type you write for the SNES lacks for/foreach style loops, so something that's a two line piece of code in Java/PHP/JavaScript/Python/whatever can be like 15 lines in assembly there.

I cannot look at a UI design and intuitively know what CSS attributes would generate that exact output.

I think part of it for me is that I do not have an intuitive understanding of the box model and how layouts are calculated. On top of that, since CSS cascades, you have to be able to mentally keep track of all the parent attributes to understand how they affect a specific element on the page.

I was working on a React Native project the other day and I could just not get flexbox layout to do what I wanted. I ended up just playing around with putting attributes on various components until I found what worked.

I have an ADHD brain that quickly discards information I don't use frequently, so since I don't use CSS often, I never remember it well enough to be good at it.

> I ended up just playing around with putting attributes on various components until I found what worked.

It's sometimes hard for me to wrap my head around flexbox as well. If you haven't already seen it, this page [0] is imo the flexbox bible. There's one for grid [1] too.

[0] https://css-tricks.com/snippets/css/a-guide-to-flexbox/

[1] https://css-tricks.com/snippets/css/complete-guide-grid/

(comment deleted)
Box model + flex box + the display modes + "positioning" (stacking contexts) are typically the most confusing parts of CSS, I feel.

Add maybe margin and padding, and how they interact (margin collapse, no margin collapse in flex or grid context, box model again, auto values).

But then, that's basically all the hard conceptual parts. But they are mostly intuitive and well-designed! I know I'm alone with this opinion.

Naming + global scope is the rest of the problem, but even without this, here is where the problem of creating design system shows up, too. Harder than CSS probably :)

Something I don’t like about the way grid and flex has been implemented is the seemingly random application of naming conventions. Memorising the differences between justify items and align items, the argument order for repeat including min and max content variables. The odd naming convention for grid area.. There’s a lot going on.

Oh yeah and debugging a broken sticky because some parent has stacking context stuff going on, also fun.

> Box model + flex box + the display modes + "positioning" (stacking contexts) are typically the most confusing parts of CSS, I feel.

That's like 90% of UI. Saying they are the most confusing parts of CSS is basically admitting that CSS is awful to learn and use.

Yeah but I'm not sure if that's primarily a fault of CSS.

I just wanted to enumarate the "hard parts".

But even if I were to agree, what layout and "styling" language or API is the easiest, most logical and well-designed one in your opinion, that still covers the same variety of use cases? From print-like simple layouts to all complicated, nested application UIs for all imaginable screen sizes?

Just curious, I'm not writing that much CSS anymore and I have cursed at it as well.

But I feel it is also powerful and sometimes, yes, even beautiful to use.

Often things that bother people are a feature at the same time, e.g. visible overflow by default.

whose fault is it then?

We had desktop UI's in far simpler forms years before. Yeah, sure, there are new requirements, but those requirements didn't actually need the complexity of modern CSS.

modern CSS came about because people like to be fancy. You value the wrong thing, you get the wrong thing.

I've found people have the most trouble taking full advantage of the cascading feature of css.
> I ended up just playing around with putting attributes on various components until I found what worked.

I think that's what everyone actually does when doing CSS.

Even as a pretty experienced front-end developer I would often times ask myself “how the heck will I do this”. A lot of that changed with flex box and then css grid. “gap” especially has made is easier the formulate a plan without just poking at CSS and hoping it works.

That said, pretty basic things like truncating text and making sticky components still trips me up every time.

If you have the liberty to limit your team to a subset of modern CSS features that have predictable behavior and patterns of applying styles (like never putting margins directly on a component, always spacing things from the parent; along with a laundry list of other conventions); and your site is designed to not do weird painful stuff (eg masonry layouts, though that should become a native CSS thing soon!) then I find it’s pretty predictable to do 95% of layouts, and only the weird outliers require special sauce. But then again I do a B2B SaaS that doesn’t need to look shockingly sexy, with lots of standard CRUD dashboards so maybe our use case is light on weird CSS tricks required.
Not a flex —and that wasn't an intended pun— but when you've been doing it 20 years, all you see is layout-modelling options.

Getting good takes practice. Lots and lots of practice.

I can imagine it's very hard if you don't know how to use browser dev tools to see the style properties being applied to elements.
All of CSS may or may not be more complex overall than x86 assembly, but learning CSS is waaaayyy more immediately accessible and simpler. Write a bit of code, immediately see results in your browser and play around/iterate.

To be an effective assembly programmer you need to understand computer architecture to a decent extent, be familiar with assemblers and related toolchains, be able to debug and reason about code execution, etc.

slightly OT but can someone recommend how to learn CSS in 2023 for a backend web developer, who 30ish years ago grokked mainframe Assembly reasonably well (and since then developed in c, php, python, ruby, bash, etc etc)?

Can/do I start with tailwind? Do I start with old-school CSS or jump straight into flexbox? Do I need to care and learn about BEM, Sass, etc? Do I start with an empty page and build it? Do I need to copy a design? Can I jump into an existing page and tweak it?

Not trolling. It’s the kind of stuff that stumps me. Or am I just making excuses to myself why I can’t figure CSS out? (beyond tweaking margins, padding and maybe background-color and the real basics)

I would probably start by opening the browser dev tools on web pages and use inspect element to see how an element in the page has been made to look the way it is. You can edit properties to see what effect they have when changed.

The domain of styling html is so large that there's no chance of learning everything in theory then applying it, I think it's best to learn by doing.

I’ve been doing that for over a decade, without making tangible progress.
You've probably accumulated a lot of relevant html knowledge which will help you.

I presume you have some css-related projects/tasks in mind that you'd like to be able to tackle yourself. I would pick one of those and jump in at the deep end. Although a small goal like restyling something that already works is probably better than starting from scratch.

For a completely abstract task, you could try developing a stylesheet for markdown html output.

Vanilla CSS is good enough (and browser support consistent enough) now that you don't need to use any compilers/frameworks to get started.

If you find yourself struggling for design inspiration, try to re-produce an existing design without seeing how they did it.

Colt Steele is my favorite web dev teacher. He has taught web development in an actual in-person classroom environment, so I find he has a better understanding on how to get people to learn things than most online instructors.

He has a new for 2023 HTML and CSS course that is a fantastic intro to modern CSS. You can probably skip over the HTML section and jump straight into CSS. Even with skipping the HTML, there is 30+ hours of CSS content in the course. It regularly goes on sale for less than $15.

https://www.udemy.com/course/html-and-css-bootcamp/

I haven't read each section, but just from the outline this appears to cover everything you need to know to do 99.9% of modern CSS development. (And then some, for good measure... I don't think I've ever used blend modes, for instance.)
Do not start with Tailwind. If you have no grasp of CSS beforehand, Tailwind will be completely incomprehensible. At the basic level, Tailwind is giving you shorthand CSS properties. You need to learn CSS first.
Personally, I wouldn't mess with tailwind until you have the fundamentals of CSS sorted out. To use a PHP example...Whereas you're actively writing a lot of PHP when using frameworks like Laravel or Symfony, and can learn from that process, you're not really writing a lot of CSS with tailwind. You're mostly just adding classes to elements and supplementally adding some styles on top of that.

I would jump right into modern things like flexbox and the grid system as the old ways of floating are basically useless. I mean they still work, but I can't remember the last time I had to use a float to create new layout. Start with flex, as it's a bit more beginner friendly than grid is. I've been doing this for nearly 20 years now and I still struggle to wrap my head around grid sometimes.

You can ignore BEM until you've got the fundamentals sorted. BEM is just a clean standardized way to organize class/id names, it's nothing functional.

Sass helps streamline things a lot via nesting and variables to begin with. More advanced features can also be useful, but until you've got the fundamentals it may not be clear where those advanced features can be applied. And Sass requires substantial more initial setup than plain CSS (you'll need Webpack or gulp or something to turn the Sass into CSS). Not to mention that Sass's biggest draw is variables and nested styles, which CSS now supports natively (albeit with really weird syntaxes, imo). So I'd skip Sass for now.

And yes, you can jump into an existing page and tweak it. That's how I learned it initially. https://csszengarden.com is a good resource for that. It's the same basic HTML site with different CSS themes you can load. It's a good showcase of how powerful CSS is what you can do with it without touching the underlying HTML. Dev tools are very useful there as you can turn individual styles off, change their values, etc.

Lastly, I'd just start with a blank page and try to create a simple 2-column layout. Narrow left column with a basic navigation in it and a wide right column with a few paragraphs of text in it. Then build off of that -- add a header and a footer. See if you can get the header to "stick" while you scroll down the page, etc.

I'd start with learning the layout model and the selector rules to get the mental model right. A lot of things clicked into place once I had a good mental model.

The main idea for layouts is that the CSS layout properties like width or margin are interpreted based on which layout mode you're in. Some html tags (<span>, <a>, <img>) default to the "inline" mode, where they are put side by side horizontally and wrap to the next line. Some html tags (<p>, <div>, <h1>) default to the "block" mode, where they are put one after the other vertically and "wrapping" doesn't mean anything. There's "inline block" which is inline on the outside but block on the inside. There's also "flex" and "grid" and "table" layouts, and their inline-on-the-outside variants. Each layout mode is useful for different things.

So when I'm frustrated about <span> not honoring width, or margin-auto not working for <img>, it's because the inline layout has word wrap. When there are 2.5 lines of wrapped content, things like width and margin work differently than in block layout mode. Instead of tweaking width/margin, I found it more useful to go back to understanding why it was not doing what I want, and then switch the layout mode to the one that matches my needs. Recommended: https://www.joshwcomeau.com/css/understanding-layout-algorit...

Selector rules are a pattern matching system to assign CSS properties to HTML elements. They also have priorities, so some selectors will have a higher or lower priority than others. These are sometimes useful, sometimes frustrating. I don't have a good reference at the moment, although I see that MDN has a page https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_...

I think of BEM, tailwind, sass, etc. as ways of using CSS once you know what CSS you want, rather than replacing having to know CSS. It's like how React is a way to constructing HTML, but you still have to know what HTML you want to construct. So I wouldn't start with them.

BTW it is a lot of fun to right click on a page, inspect the css, and start tweaking it!

To join the chorus: I have learned assembly on the Z80 still behind the Iron Curtain. It was long ago. It's logical and as such it's real easy. Sure, it's a bit more tedious than higher level programming languages but oh well. Now, what little I know of CSS made me very firmly refuse to work with it. I do backend work, I let the frontend people make their magic.
CSS is difficult because the complexity and inconsistency of mixing the intrinsic styles of HTML tags and CSS styles.

For example, width can be set on <div> but has no effect on <span>. You have to set its display to inline-block.

Another example, <a> has its default colors. Setting CSS colors on the parent element has no effect on the <a> colors, which defeats the CASCADE nature in CSS. You have to apply the styling on <a>. But some styles like font-size does get through from parents.

Another example, text overflows out of bound by default. You have to do the trick of turning off overflow. It feels like setting the bound has no effect.

CSS just has lots of inconsistencies and requires knowing many little tricks to use it effectively.

> inconsistency of mixing ... width can be set on <div> but has no effect on <span>

One of these is a division of layout, one of these spans the thing it wraps. The <span> should span the span of the content.

The affordance of an anchor hypertext reference <a href> was supposed to be consistent for usability, and the <a> is on the link aspect, not on the text. The text that's inside the <a>here</a> is part of the text on either side of the anchor, and should of course reflect the font size etc., because the font applies to the text, while the <a> style applies to the indication/affordance of anchorness. And, you can pick what you want the a to be given which division or span of content it's in, and the most specific style will apply:

https://jsfiddle.net/mD5us/4/

Arguably, both of these are not just consistent, but the way it should work in principle given the apples and oranges you're comparing.

Yes. All these are "supposed" to work the way they are and they are given good reasons, but it still doesn't negate the facts that the same CSS style has different effects on different tags.

The <span> tag is a good example. As a user of CSS, when I apply a width to a span, I want its width set. I don't care it spans items. If I want span to have no width, I would just leave it alone. The fact that setting the width spells my intention clearly to restrict its width.

In regarding to the selective application of colors and font-size on <a>text</a>, both the colors and font-size are styles that affect the text of the link. Why does one go through and the other doesn't? Don't you want consistent appearance of the link both in colors and font-size, in the name of affordance?

Semantics and context matter.

Width is a lovely word for things that have width, and meaningless if applied to things that don't.

Consider “Set your emphasis width to 12 points.”

None of that is applicable even though there are 3 CSS keywords in there and you can make sense of the sentence.

> Don't you want consistent appearance of the link both in colors and font-size, in the name of affordance?

Speaking for me, no. All words in the sentence, both inside and outside the anchor, should be consistent font, but the anchor has both state and behavior that can include color, underline, etc., to set what's inside the anchor to be inconsistent from the surrounding text, for attention and information.

Generally, font size is not one of those things that would vary (Mac dock icon mouseover as a counter-example).

There's a decent chance much of this makes more sense if you were making sites before these capabilities were developed and were along for the progression.

It likely does seem like a chaotic mess when picking it up for the first time in present state, so I think it's a fair reaction.

Here is the thing.

In declarative languages, you generally specify what you want, rather than how you want it calculated.

Not so in CSS! It's thoroughly declarative, but in a way where you're fiddling with a whole lot of "how", whereby the "what" disappears in the fray.

Differential equations are declarative too, but likely a bad way for most users to be asked to specify how something should move across the screen.

How do you create a mouseover effect for every third child of some element in assembly language, and is it as easy as CSS? :)
As with any other technology, difficulty is relative and a function of experience.

For me, CSS is easy even though I rarely work with it professionally (I mostly work on backend and infrastructure these days). Yes, there are scenarios where I get stumped but a vast amount of literature and helpful community gets me to places I need to be, just like many other technologies.