The Importance of Learning CSS
joshwcomeau.com
joshwcomeau.com
That being said, good skills in CSS are really in deficit imo. If your starting a career in webdev, just being good at CSS is already a big added benefit to a team, especially as a junior dev.
Also, one of the harder things to understand as a frontend developer is knowing the limitations of CSS. It doesn't do everything, and sometimes you have to know when a Javascript-based CSS approach is better. This opens up another can of worms since now you also have to be familiar with alot of lesser known Javascript APIs.
Last note to make is getting good at CSS also requires a good chunk of math knowledge, especially for difficult design-based problems
Though I admit it was difficult for me to internalise originally: I cut my teeth on HTML in 1999 when browsers still rendered each element type differently and they weren’t interchangeable. I couldn’t grok being able to make a <table> and a <h2> interchangeable from a styling perspective.
The other parts of CSS, such as the cascading styles really isn’t that important - and I agree modern features like Flexbox and Grid do introduce more special-cases, but they’re no worse than having to understand how to abuse floats, clearing, and “replaced content” for website layout - I’m glad those concepts are gone.
This is, respectfully, absolutely insulting to people actually working in CSS in real browsers. Okay fine, it's a rectangular box. When and where does it appear? Sometimes it's undefined. What properties does it have once it does? Hoooooly crap this is undefined.
As a just today example: I discovered that two eventually overlapping linear gradients in Safari (checked in iOS) render differently after wake from sleep or dark/light mode switch. One of the gradients doesn't render at all before, and only renders in the portion of its "rectangle" after. Bug? Sure. Common-fucking-place-normal-ass-website-styling-shit? Yep.
Edit to add the real kicker: it has nothing to do with the styles of the thing with the gradients on it! It has nothing to do with accommodating the children of the parent. It's just: one parent is a grid, the other is a flex. Nothing. At. All. Changes the outcome.
If you only have to make it work on one browser with one version, or if the feature is extremely old, or if you can do it outside a larger system of constraints, then you can just follow the step-by-step guides the article is complaining about.
Indeed. You're entirely correct.
But with CSS the basis is that general "everything is a rectangle" model - which makes it easier to adapt to new features when they're introduced - compared to having to basically learn-from-scratch when new layout features are added to other systems.
And, why wouldn’t it just be boxes? You screens are just small little boxes (pixels), and everything you put on it takes up an area of pixels.
Sure, the base primitives are rectangular and like you said why wouldn’t they be? Everything visual starts with x1/y1/x2/y2 in a sense.
CSS absolutely does disagree with our brains because it's trying to take a tree of elements with their own properties that interact based on their tree relationship and projecting that into 2D.
None of that contradicts my point that CSS generates a hierarchy of rectangular boxes from SGML/HTML/XML elements. And every system has some form of margin control, and most have some degree of support for negative margins and margin-collapse. I appreciate it's yet another thing to learn, but it doesn't violate the simplicity of the "everything is a rectangle" model that CSS uses: consider other systems that special-case their layout mechanisms (like how WPF/XAML has `<StackPanel>` for layout and `<Border>` for margin control, rather than allowing any element to have its own margins and any element to control the layout of its immediate children): it's hard to say WPF/XAML's system is "better" because rather than having a simple initial model with special-cases laid-on-top, instead you have a model comprised of only special-cases.
> CSS absolutely does disagree with our brains because it's trying to take a tree of elements with their own properties that interact based on their tree relationship and projecting that into 2D.
There isn't really any feasible alternative[1] that doesn't introduce more complexity. All the other tree-based (or hierarchy-based) systems for representing a visual document that I have experience with, such as WPF/XAML/UWP, WinForms, Qt, and others, all rely on some degree of "inheritance" from parent nodes to child nodes (and ancestor to descendant nodes) in a document (e.g. in WinForms a Control's background color defaults to its parent container's background color. Controls inherit their parents' Font, but only during initilization, thus introducing another "gotcha"), I agree that CSS shares a long list of exceptions and special-cases, but CSS's special-cases are built-on a better general-case.
If there's a better way of doing things - please share!
[1] The alternative would be something that freely translates hierarchical documents into some kind of unstructured or semi-structured "rendered document" in a separate render-space - but I don't see how that frees people from having to deal with complexity, on the contrary: it introduces even more complexity (because now the "stylesheet" is concerned with mapping from one space to another, possibly in a bi-directional manner too), whereas CSS doesn't require any significant space-translation[2]
[2] CSS's `grid` and ability to re-order `flex` elemenets, and the `absolute` and `fixed` positioning schemes do introduce new space concerns, but besides that, 95% of structured document content retains its spatial relationships when mapped by CSS's visual formatting model.
My approach is to limit cascading as much as possible and try to contain the evil that is css to its respective component.
I actually landed my job as web developer because I was good at CSS and ES6 JS.
I loathe having to deal with so much layout building classes in my dom, having to swap them for responsive layouts, etc. My css determines layouts. My html presents data. It keeps my javascript very focused on function.
I love me a nice tight jsx template with maybe one or two classes sprinkled at the top level containers.
Componentize using BEM classes and SCSS and your designers will love you.
Anyone who might conceivably hire me to do anything JS related is likely to want the whole shebang: lightboxes, horizontal scrolling, SPA-like stuff, and I'm never going to be conversant with that. It's enough to be really good at CSS, and to save the JS for when people don't really realize you're writing JS: some little vanilla ECMA6 bumps to site usability, and maybe some tasteful htmx. That's enough. Leave the rest to someone else.
Frontend is just stacked with this form of mistaken understanding, hence the bike-shedding over frameworks. We know we can represent a given app as a function signature, whose implementation would be comprimised of related, derived signatures, and a framework is just a bunch of implementation details between these in a sense. Details that may have profound significance for your project, but you'll be surprised how shallow the discussion resolves around those differences.
This is why frontend is just piles of code on top of code, at least at operations I've seen, the JIRA ticket fest being another contributer, but there's so little engineering understanding being propagated by and large, people mistake these high-level concepts for software engineering proper.
And somehow, the tech managers are usually the least in understanding, so they hire people who are like them and make them comfortable, and the process continues
If a framework is good, it should be friendly enough to people who've got essential coding/algo/data skills that the details of the framework can be picked up as you go, especially if they're familiar with other approaches in the same space.
If utility with a framework demands two years of familiarity before employable productivity with it... maybe it's not a great framework.
Just look at Hooks and React.
How many posts have we seen where people demonstrate the authors could've done something different, without buggering with what the meaning of a call site in a React component is, or even accomodated hooks in the Class API, but React devs can get away with this cause they don't need to prove coherent technical benefits, they just need to make it look like "the next big thing".
Numerous frameworks solve the problem of cross-cutting state concerns targeted at distinct sub-trees in the your UI (see mobx/freactal/etc).
The componentDidMount/componentDidUpdate simplification is nice, but could've been accomodated in the Class API.
Other reasons like "readability" or some shit, I honestly don't give af cause these are subjective statements that aren't at all neccesarily related to a solution's quality per project
The fundamental problem I’ve witnessed in the component composability era is that many people have their own mental models on what simple composability actually is. It’s a difficult topic to broach as many will see nothing wrong with their component architecture.
The thing that makes React powerful is how easy it is to compose components, and as a side effect, it’s allowing every developer (of every mindset, of every background), to come up with what they believe makes intuitive sense.
Case in point, you might think a finite state machine lib makes a lot of sense for a Dropdown component. I’ve seen one asshole actually write a whole blog post about it.
I’m not perfect either, and have certainly gone down the path of making a fucked up component composed of essentially my world view.
Another common example is the wonderful json config that gets passed into this elaborate component or HOC component, and allll you have to do is update the params and it will be suitable for all your fancy needs. A truly precious thing to stumble upon, and usually makes me want to just kiss the precious genius that concocted this world saving contraption.
Mr. Abramov of course, the grandest of psychopaths managed to turn a simple pub/sub into derivatives options trading buy/sell order chain of actions and reducers.
Some people simply do not think clearly, and it’s wearing me down.
Over time, the composability freedom of React has made me utterly hate my fellow frontend developers. I hate how absolutely insane some of your mental models are.
a profoundly compelling, persuasive, expert, pragmatic, accessible, maintainable approach to CSS. It's transformative. I've been doing webdev since the late 90's (ie, before CSS), and this is hands-down the best such resource I've ever encountered. The axioms and some key examples are free; paying $100 for the book and component generator and access to updates was beyond a bargain. No affiliation, just a happy customer.
The first time was like everyone else does. Google tricks here and there. How to center div, how to create columns with divs, how to do rounded corners etc. This will only get you so far.
The second time around, I took a bunch of courses online, lynda, one of by designers, and bought books. Once you understand the fundamentals of CSS, you can work just fine with css2. Css3 is just an added benefit and great for animation.
It’s true, CSS2 is all you need to build any layout. I actually prefer float grids over flexbox and CSS grid. Float grids are so simple to use in comparison, and all it requires is a list of breakpoints and two to three SCSS mixins, depending on how fancy you wanna get.
But no way I’d write it without modern tooling.
Once you need equal-height boxes in your layout, though, it's time to use something else.
Flexbox and grid do not subscribe to this: flexbox shrinks/grows its content to fit itself. Grid is a configurable beast, something in between, and also makes it possible for grid content (not the container) to define how it itself is laid out.
> The CSS specifications are surprisingly user-friendly! I learned a ton reading the [Flexbox spec](https://www.w3.org/TR/css-flexbox-1/).
The CSS specs are fairly intelligible (as specs go) and once you have enough base knowledge to get a foothold while reading them, they force you into thinking about CSS much more systematically, because that's how specs are written.
tailwindcss effectively boils the dauntingly large control plane of every CSS feature down into "utility classes" that you then compose all styling from. So far, it has had a solution for every styling problem I have encountered, and in the cases it didn't, when I really thought about it I was trying to do something dumb anyway.
I swear I am not affiliated with the project at all haha, I just felt such a relief after giving it an honest try on a project and I could very easily see how powerful it would be in many of my past projects had we access to it (and convinced the naysayers)
Tailwind is revolutionary. It has completely changed the way I develop, and I will evangelize it at every opportunity. I've started migrating a major project to Tailwind, and for the first time I'm not horrified by having to deal with conflicting stylesheets, etc. Everything I need to know about how a component looks is kept in the component, where it should be, and the bundle size is smaller than ever because Tailwind can prune the styles down to exactly what I'm using. Tailwind is great, and shoutout to Adam Wathan's youtube channel- very helpful in learning how it works and convincing me to try it.
Adam had success time and again but he always builds profits and abandons. PHP without loops, test driven laravel are two other successful audiences that were built, sold to and abandon. He has seemed to move on from refactoring ui.
It has been a year+ since Tailwinds has been released. How much longer before Adam jumps to the next thing?
The rest of us who like our lean mean HTML and CSS will stick to the old-school way of doing stuff - separating styles from our HTML with clean classes and markup with no need for a build step just to create basic stylesheets.
Frameworks which marry themselves to this ecosystem are OK for those developers who are already in NPM hell. My apologies for your suffering - but the rest of us don't need to join the cult of doom.
I much prefer chakraui approach to building a design system library. It utilized many naming conventions based off of tailwinds
An article that talks about how to overcome this (and that many have found useful): https://planflow.dev/blog/how-to-get-better-at-css
If you have to create web pages by hand, it probably does.
If you have to read CSS created by others, no.
Unfortunately, when CSS was created, constraint solvers were rare and object inheritance was too popular.
Sorry if that comes off as a bit rude (if it's any consolation, I liked your clay figure!), but I honestly prefer reading plain markdown on a white background.
I tried to study a lot of technologies but found that I was spreading myself thing and doing nothing exceptionally well.
Instead, it served me better to work on a few projects, see what I like, pick an area and to just get better and then learn the other things I need to as I go along.
Nobody can be good at every technology. It's not like that in real life so why do we have expectations that it would be like this in software development? A kickass mechanic doesn't need to be also be a kickass plumber and a kickass carpenter. They can but that's not what we expect from them.
I am now comfortable knowing more server side technologies and barely scratch the surface of modern CSS.
My efforts are rewarded more handsomely knowing backend technologies and JavaScript.
If I need to know CSS then I can believe in my efficacy that I can learn it if I have time and to spend on it, and not feel insecure about delegating front end work to people who do it better.
A question to ponder over: expected by whom?
One of the few fraternities I’m ashamed to be apart of.
1. Often times, someone will do something that should be done programmatically with CSS instead, leading me to finally come to the realization of "holy shit the bug was hidden in the CSS!".
2. I've (very cattily) referred to CSS as Cascading Sideeffect Sheets. You can do things to mitigate it, but trying to wrap your head around an application's vanilla CSS declarations and which elements are effected by what is an enormous pain compared to what it could be. My team has switched to CSS Modules, and the scoping relieves sooo much of my aversion to it.
3. The final reason is that CSS proficiency just feels like memorizing a collection of "Gotchas" that don't make sense in isolation. It's not very programmatic, and lots rules aren't grouped or named in a way that you can understand what's going on by reading. For every CSS rule you need to understand for whatever reason, you're going to have to dive into some documentation to figure out exactly all of the effects/sideeffects it will have, and sometimes also have to grok their interactions with other rules.
Especially your last point. I want to do something with B, but I break A and C somehow. Or I change A to fix B but all of A breaks down. I google it, and there is a menu of choices. On week 3 the first one worked, on week 6 it all breaks down, so I go back to A and C, but it breaks A again.
I am really lazy with this.
I feel like no one knows CSS properly, whereas for my previous listed technologies, you can learn it without the "shotgun" approach.
I have always known I am missing something but never been able to put my hand on what that lightbulb is.
Edit! Also due to the "menu" effect, when I do put my trust in someone, it doesn't actually apply. Like an OOP programmer using global constants everywhere! So what I learned was actually incorrect, but now I am polluted by garbage...
Yes, CSS is a study of the arcane. If you do it long enough, you will realize there is no rhyme or reason to critical parts of it.
Me think that anti-virus companies have got their work cutout for them.
Name the culprits who are supposed to set standards, currently Google and Apple, with Mozilla and Microsoft trailing behind, and you will get downvoted into oblivion.
A programming lets you specify initial state, final state, and the commands in the programming language required to go from initial state to final state.
It is a system that enables something akin dividing by zero all over the place as though there is nothing wrong inherently wrong with dividing by zero.
The impedance mismatch between how you describe what you want to see and how to express it in the language is so huge it is insane.
It is part of the ongoing fraud of pretending that tying Javascript to a document layout languages is a sound way to script the presentation of data.
If that was truly the case IBM and Xerox would have invented something close to that combo in the 60s and 70s.
So long as Google and Microsoft earn money from their app stores they are never going to introduce a pragmatic for displaying information in the browser.
It is over 10 years now since together with Apple they deprecated Flash and Silverlight, yet 10 years later with vastly improved hardware they still can't come up with a meaningful system than the same lame HTML5/CSS/Javascript.