I do continue to find it weird how CSS is just relegated to this second class citizen when it comes to web development and huge numbers of folks seemingly have little to no interest in learning it beyond what they can copy and paste.
For me a big part is that global CSS doesn’t match component based web applications as well. Coordinating global class names becomes a pain quickly. Then you move to scoped CSS and suddenly CSS doesn’t add much anymore.
Better not to think of it as global variables and more like annotations for cross-cutting concerns.
That said, don't blame CSS just because React treated it like a second class citizen. Try Svelte. Matches the components there perfectly. It really is amazing to use a web framework that doesn't hate the platform it's written for.
As more web development (in JavaScript) moves away from anything resembling inheritance, the cascade in CSS starts to feel annoyingly out of place. It’s perhaps subtle but a noteworthy distinction in my mind.
I struggled with letting go of old school CSS for this reason. I’ve written it for literal decades at this point and know it like the back of my hand, and it increasingly just feels like the odd man out in the front end stack.
> As more web development (in JavaScript) moves away from anything resembling inheritance, the cascade in CSS starts to feel annoyingly out of place.
I am puzzled by this statement. The cascade is the algorithm for resolving conflicts when multiple rules apply to the same HTML element (based on css rule position, specificity, origin, and importance). Inheritance in CSS is a different topic, where a subset of properties defined on the parent are automatically applied to the children. Without inheritance, you would have to redefine the same properties on each of the children (e.g. the body font-size, or font-family, or color would have to be repeated on each of the children elements). Without cascade, the browser wouldn't know how to resolve conflicting rules. How is any of this out of place?
Yes, both the cascade and (CSS) inheritance are valuable and necessary.
Not the commenter you responded to, but I'm guessing they meant "inheritance" as a programming practise, not the CSS-specific meaning.
Inheritance of CSS rules down the DOM tree is indeed essential for CSS to work, even if you are using some sort of scoping.
Scoping is about limiting the DOM subtree that a CSS rule applies to, so sure it is related to CSS rule inheritance.
But even if you use tailwind, (Vue) scoped styles or styled components, you still need CSS inheritance.
Nobody aims to apply CSS per-element only, although large parts of it are exactly that.
In other words, Tailwind authors stil expect "text-red-500" to be inherited down to child elements.
so much for inheritance, regarding the cascade:
Point of maintable CSS is to keep the cascade flat and avoid multiple levels of overrides or very specific selectors.
Often when non-web based UI frameworks leave out CSS they don't elegantly fold it into their UI markup and/or language, they just don't have the features CSS has to begin with, or force you to declare it in the programming language which imo often looks ugly (especially if they try and make some kind of declarative DSL in an imperative programming language).
I'm wondering if we'll ever see Houdini make its way into browsers. The idea is that instead of modern CSS, the browser provides a bunch of hooks for various parts of its layout engine. You can then provide custom code that uses those hooks to implement any layout system you want.
CSS is big and complex, and it still needs to support the whole legacy of web applications going back forever. Most applications just use a tiny subset of CSS. Houdini could allow smaller, faster layout engines with none of the legacy stuff. And because your app ships its own layout engine, if there's a feature you want, you can just add it to the layout engine and it'll instantly work in every browser.
I have no idea whats happened with it though. Now that flexbox, grid, sticky and a few other things are in all browsers, CSS feels good enough. But maybe I'm lacking imagination.
The one thing I'd really like for web layout is a "stretch unit" that works similarly to CSS Grid's fr units in that it would be defined as "taking up a proportion of available space after other siblings have been sized" except:
- It would have no automatic minimum, so it would actually be equivalent to minmax(0, 1fr) (this would make it much more performant, avoiding the exponential time complexity of many existing CSS layout modes.
- It could be used for the width/height properties (and potentially other places such as margin/padding/inset)
If you had that along with a simplified 1-dimensional display mode (i.e. like flexbox except with the flexing disabled) then I think most people probably wouldn't want much more in most circumstances.
Houdini is interesting, but as someone who has spent a lot of the last year implementing a web layout engine [0], I'm a little skeptical that JS is ever going to be fast enough to really compete with built-in layout modes. It could be an interesting use case for WASM if the problem of passing data into the WASM VM cheaply (perhaps by reference) can be solved.
> It could be an interesting use case for WASM if the problem of passing data into the WASM VM cheaply (perhaps by reference) can be solved.
WASM Reference Types should hopefully solve this. The WASM working group seems to have some good momentum - so I'm hopeful this (or a similar replacement spec) will land sooner rather than later.
>"taking up a proportion of available space after other siblings have been sized"
and
>- It could be used for the width/height properties (and potentially other places such as margin/padding/inset)
this to me is essentially what clamp does, although it can't take up size after siblings have been sized.
If at some point clamp can start taking values like inherited then it would be pretty cool, but that would be pretty difficult unfortunately.
> although it can't take up size after siblings have been sized
The key things about the proposed new unit are:
1. That it takes up space after siblings are sized (i.e. a dedicated syntax for what 90% of flexbox uses are trying to do)
2. It prevents that same node from being "auto" sized (i.e. sized based the size of it's children). This is an important optimisations which greatly improves layout performance.
Taken together this could both significantly simplify layout code and significantly improve layout performance.
hmm, yeah a guy I know recently wasted weeks trying to do a design that was actually undoable if all the ideas implicit in the design were given equal weight, and this would have allowed him to achieve what he was trying to do.
I honestly hope Houdini never makes it into a final spec. The demo use cases are interesting, but the last thing we need is more complexity in web development.
Browsers today already act more like operating systems than document viewers. Houdini basically takes it a step further allowing every app to bring its own renderer. Linux leans heavily into this today and it makes mundane tasks like global theming a huge pain in the butt.
> the last thing we need is more complexity in web development.
Thats one way to think about it. Another is that Houdini lets the browser be more simple - because CSS (as it exists today) can be moved into a reusable library that can be shared between browsers. In theory, if all the browsers supported houdini, they wouldn't need to maintain their own CSS implementations.
As an internal implementation detail for sharing code across browsers, that sounds compelling enough. Web developers would never need to no about it though, as its just part of a browser's rendering flow that happens to be shared by browser vendors.
In reality though, I don't see browser vendors playing well to that level. Sharing specs is slow, sharing rendering code would be a nightmare.
Beyond that, I've usually seen Houdini demoed with developers focused features, effectively adding small bits of your own logic into CSS rendering. That pulls it out of the shared library and into userland.
Can you share some examples of CSS features that could be deprecated if it weren’t for legacy websites? I have a use for pretty much every CSS feature I know, but I only know them because I looked them up when I needed them, so maybe I’m missing some features.
I don’t think you need even that to have a reasonable compact layout system. There might be an opportunity here for a kind of subset of css that covers all modern needs, documented, and with a linter to enforce it.
Yes only thing missing is full support of the web animation specs. For example scrolltimelines is missing in ios and firefox. That one is really needed to get similar performance in web app compared to native.
> It [Firefox] was quick, it was simple, it was much more standard-compliant, and absolutely none of that mattered.
>
> No, Firefox really got a foothold because it had tabs.
The article doesn't mention it but at this time, equally attractive along with tabs, was the pop-up blocker! Truly the first ad-blocker like thing. And it was awesome too :).
Kind of reminds me of my thinking (back in 1995) that I wanted to write a browser that would have a menu option to show what the output would look like with different browsers (this was back before writing a browser was essentially writing an operating system). I remember some really awful attempts at styling before CSS, the worst being
<font size=+1><ol></font> item text
to change the size of the list bullets (which, of course, only worked on Netscape and broke rendering entirely on other browsers).
> Let’s say you wanted all your <h1>s to be red, across your entire site. You had to do this: <H1><FONT COLOR=red>...</FONT></H1> …every single goddamn time. Hope you never decide to switch to blue!
This was never a big problem for me because in those days I wrote Perl scripts to generate my pages. I just defined $h1_color = 'red' and ran the script to crank out the static HTML pages. Boss (me :) wants to change the color to blue? Just change 'red' to 'blue' and re-run the script.
I personally loved CSS3PIE for times like that. Of course then there would sometimes be complaints about rendering performance, and my answer was usually, "You can have working, pretty, and fast, but for IE you'll have to choose two out of the three."
I remember “feathering” the curves in Photoshop for a smoother finish to the rounded corners. My team, especially the new ones, would go -- heck, the trick, the trick, we learn a trick. ;-)
The struggles were real, and the fun was short and intermittent but worth every moment.
there was a way to use package image in a non-standard way (iirc using Offsets in Photoshop) and use negative background position to emulate 3x3 grid image with less elements. Was an advanced technique.
Yes, it's another technique. I can't find it right now (it's old masters technique). It's different from spritesheet or border radius, in a way that it requires image to be pre-proceed in photoshop via Filter->Offset, that basically acts as negative background position. This is to shift top-left pointer of an original image to its center. After that in CSS, you can use negative background-position to negate the image manipulation. Effectively it helps creating the right edge of a flexible element, which was difficult before background-position could be anchored to the right.
You'd still need multiple elements, but you'd have a single image (which is better for http latency/compression).
I'm using "display:flex" on almost everything, and as you said, flexbox is suitable for almost every situation. Also, for anyone struggling with flexbox - I use this tool to streamline the process: https://flexboxcss.com
I only dabble in HTML, but for the kinds of layout I find myself doing, grid comes up more than flex does. Subgrid is needed for some tasks, but poorly supported still.
Container queries are a less-limited alternative to media queries.
When writing custom rules for other people's websites (using the Stylus extension), elem[attr=value] and variants (^=, etc) are very useful. :has() is useful for styling the parent of the actual element with the attributes but not in all browsers yet.
Last I checked it is still not possible in the wild to implement fully automatic dark-mode (etc.) theming (using HSL) even though colorspaces are in the spec for the relevant functions.
> I only dabble in HTML, but for the kinds of layout I find myself doing, grid comes up more than flex does.
It depends on whether the content is fixed to desktop monitors or responsive to mobile screens. Grid doesn't give the same responsiveness flexibility when the page is displayed on mobile.
In my experiments with grid vs flexbox, every single time I used grid, I had to switch over to flexbox the minute I needed the content to display on mobile screens.
My usage of grid turned out to be simply a different form of tables, which don't work well (or at all) on mobile screens.
What I did with grid was use media (or container, easier to debug at top level and necessary when nested) queries to do a completely separate layout for the same DOM when the viewport (or parent) was too small horizontally. The problem with flex is that it means "adjacent" elements can randomly wrap anywhere even if they really belong close to each other, whereas with grid I could arrange for closeness separately for each available horizontal size.
> The problem with flex is that it means "adjacent" elements can randomly wrap anywhere even if they really belong close to each other, whereas with grid I could arrange for closeness separately for each available horizontal size.
I don't put down a flex and leave it at that; I use media queries to change it between flex-horizontal and flex-vertical. This means that I either wrap at particular width for desktop, or "wrap" at every cell for mobile.
Granted, it's not perfect as it only supports two classes of screen size - desktop or mobile :-)
I recently started at a new job where I need to do a lot of stuff in the frontend (sadly).
Flexbox is a lifesaver, except when it isn't (I didn't know grid was a thing until last night, but it really solved a usecase I struggled with quite a bit with a flexbox)
Not as many as you'd think. Chrome's automatic update a decade and a half ago really changed the game from when folks had to manually upgrade. IE 11 installs are getting real small and typically have enterprise IT teams to help them out.
I'm sure there's some poor souls out there still using Windows XP, best wishes to them, but I'm not devoting any engineering hours on their behalf. Just like folks running a 57 Chevy, you're welcome to it, but you're responsible for its maintenance, upkeep, and road-worthiness from here on out. If that's how you want to spend your time, all the best. Just don't go complaining that the Bluetooth doesn't work.
It's not about IE11. :has() is not available on Safari before 15.4 and Firefox before 121. Nor Samsung before 20. That's all reasonably new, and many people, especially on mobile, can't update.
Variables are not mentioned. What if you want to use the same color for backgrounds here, border there, and text there? CSS can do that today with something like var(--my-color).
To me, that makes a CSS build unnecessary. Sorry, sass and co.
Custom properties are great until you need to access them from JavaScript and realize it’s impossible and are sent back to the drawing board.
After building countless design systems with CSS/SCSS/Tailwind/Svelte/SASS/PostCSS/etc, I’m convinced that CSS as a separated language in separate files needs to die.
I’m building an experimental design system in pure Typescript and I feel like I’m finally able to free my UI from the Stone Age.
I’m sure I’ll be back to the drawing board again soon enough.
God bless CSS. I mean just look at the alternatives. There's really nothing else in existence with such power and flexibility. Any time I spend in native land it's always a feeling of pure freedom and enjoyment coming back to the web platform.
Flutter is a nice alternative I found in that a lot of thought really went into how to design a UI framework from the ground up using everything we now have learned over the years about what works, what is important and without having to worry about backwards compatibility but could take a greenfield approach.
With that one exception I otherwise agree, CSS especially in 2024 is actually very nice to use for the most part.
It's hilarious to me that even with 25 years of engineering hindsight, you can only point to one framework that has executed well enough to be considered superior to CSS.
With 20 years of prior art to look at, new options should be better by default. What does it say about our industry when the vast majority of "replacements" are not?
Interestingly, both IE and NN had `box-sizing: border-box;` as default behaviour, and at least for me that was sensible behavior. Probably a better decision at that point would have been to update spec and add a quirks mode other way around.
border-box was the original behaviour in an early draft of the specification, but it was changed to content-box before final publication. Browsers that jumped the gun and released with draft behaviour got it wrong. And it wasn’t default behaviour so much as the only behaviour – the box-sizing property that allowed web developers to control this came a long time afterwards.
> Oh, and everyone wrote HTML tags in all caps. I don’t remember why we all thought that was a good idea. Maybe this was before syntax highlighting in text editors was very common (read: I was 12 and using Notepad), and uppercase tags were easier to distinguish from body text.
The use of uppercase HTML tags in the early days wasn't primarily due to memory concerns. It was more about readability and consistency. As HTML evolved, lowercase tags became the standard for better readability and compatibility with XML.
Another point that in the early days of computing, memory was a precious resource, and every byte mattered. Some developers believed that using uppercase characters could save memory because uppercase letters have simpler representations in ASCII, occupying fewer bits. However, this difference was extremely marginal and hardly made a noticeable impact on memory usage.
Some developers today think CSS-in-JS is a good idea. Web devs also wanted HTML to look and parse like XML. Backend devs also thought RPC with XML envelopes (SOAP) was the path forward.
Developers in all time periods have held curious ideas that appear ludicrous with hindsight.
As someone who always used uppercase for tags back in the day, it wasn't about saving space; it was to improve human readability. All caps tags stood out better against the backdrop of mostly lower case prose. Also the DOM APIs case-folded to upper when inspecting an HtmlElement object's name.
To be honest, this is the first I heard that folks thought it had space advantages.
In the early days of computing ASCII was not universally used and often character spaces were less than 8 bits and lacked lower-case, or were mixed charsets like PETSCII that had upper-case letters and the extra charspace were filled with graphics. For a text-only system you could store the doc with 6 bit chars since you could ignore the upper charspace populated with graphics.
Layout has always been easy to learn but difficult to master. This has been true since long before the advent of CSS and the web. You think the folks working at newspapers of record never had to hack something up to make it fit right above the fold? And their output targets were static!
Does anyone know the history of the Space Jam website? I’m curious who created it and which blessed souls have kept it up for so long. (May its existence never be relegated to the Wayback Machine…)
> A year and a half later, in mid ‘98, we were gifted CSS 2. (I love the background on this page, by the way.) This was a modest upgrade that addressed a few deficiencies in various areas, but most interesting was the addition of a couple positioning primitives: the position property, which let you place elements at precise coordinates, and the inline-block display mode, which let you stick an element in a line of text like you could do with images.
inline-block was actually introduced in CSS 2.1, which came a few years after CSS 2.
> Generating CSS with JavaScript was a possibility, but boy oh boy is that ever a bad idea.
lol.
As a backend developer that pretends to be full-stack, I enjoyed the hell out of reading this. CSS is such a mosh pit that it's just about impossible to find a summary of why things developed as they did. Plus I feel curiously reinforced about the times I've come at this with fresh backendy ideas, asking frontend devs "uh, why are we doing it this way?" and they only make strangled noises in response.
As someone who was doing frontend development since before CSS existed (I jumped in somewhere around when the <center> tag was introduced), I can probably answer any of your questions.
Most answers—especially for those early features—boil down to folks from the desktop publishing world wanting features they've always had, using terminology few programmers had ever heard, and looking to use layouts everyone in their community was already intimately familiar with.
Some things got lost in translation, but a lot is just an artifact of desktop publishing not having the same goals or desire for algorithmic elegance that developers were used to. Then of course were the tradeoffs. Remember that when CSS was first introduced in Internet Explorer, 16-32MB of RAM was typical if not advanced. The user had a 512MB hard drive on a good day. There were no GPUs as we think of them today. There were some 2D accelerators (good ole Diamond video cards) that took ridiculously slow rendering up to the level of very slow rendering. 800x600 target resolution was typical for web development.
No one really knew what they were doing, but everyone had an opinion, and a lot of those opinions were incompatible with one another. A lot of temporary stopgaps were put in just to solve the problem of the day only to end up part of our technical debt today.
ActiveX and Flash (and <applet>) solved real problems, but were never architected as a cohesive part of the whole. SVG took way too long and progress was crushed under the weight of committee. XML touched everything and was universally agreed upon as the glue moving forward… until it wasn't. We still call them XHR calls even though they rarely fetch XML resources anymore.
And layout is hard. Damn hard. Ridiculously hard to get right, and that's when you have a well-thought out plan and universal agreement. Which Microsoft and Netscape most certainly did not have. Neither really had a solid reference point. Correct behavior mostly boiled down to "how it renders in that browser version right now".
We really have come a long way. One should expect warts and scars. All things told, I'm really happy with how modern CSS turned out. It may be complex, but so are the outputs it is meant to produce. Those who pine for something substantially simpler I believe have a diminished understanding of the problem space.
As a mostly front-end person who knows CSS pretty well, it’s still baffling as to why things developed the way they did and why there are so many ways to do certain things like layout. The sheer number of layout options and their inherent quirks make designing any site or app from scratch a nightmare. This is why most modern applications use layout engines like Bootstrap or foundation (especially because it does most of the responsive design for you).
Is there anything in specific you can point to in terms of layout? IME Most of the time you can just `display: flex` or `display: grid` (and then tweak the necessary properties on the children) and it generally works well.
As a full stack dev that wants to be backend: Fully agree with you there. Frontend is so much more of a pain for me than backend because so much of it just seems bad in terms of usability for no real reason.
On the frontend, the users control the execution environment. On the backend, developers control the execution environment. It had to be this way for the web to scale the way it did.
Most developers are control freaks. "I put in input, and the computer does what I say." Far more so than the general population, I think. That lack of control on the frontend will predictably not be looked on highly by many in our profession. I think those who are more comfortable having a more loose grip on their environment tend to be more comfortable with front end development—more accepting the state of how things are, not some elegant and provable state that can be verified to the nth degree.
We've molded and shaped our world in the backend to be as predictable and controllable as possible. Arguably, the frontend is more representative of the real world and its compromises.
The Netscape 4 "missing closing table tag of doom" whereby omitting a closing table tag would cause the whole document not to render. https://www.webmasterworld.com/css/234.htm
Especially cromulent because in the absence of ANY other layout or styling control, the common mechanism were to effectively play nested games of tic-tac-toe with tables, valign=center (you never had it so good!), and if you were lucky, html-tidy on the command line for debugging.
...references are tough to find, but I believe Mozilla/NS attempted to push (and had a short-lived branch) for JS-based styling language. ie: body.style.background = "white" and using that as THE language for writing "stylesheets".
IIRC: Microsoft basically outright refused because they had the MS-Word people who envisioned the "CSS-as-books" universe (and had effectively infinite senior programmers to work on implementing "the cascade") while Netscape was smaller, scrappier, and more interested in an _effective_ web, not a _perfect_ web.
Very tough to find original sources for it as it was before search engines and with web-decay, sites aren't referenced.
Microsoft held the web back by at least a decade by EEE (embrace, extend, extinguish), but launched it forward (accidentally) again by forgetting that they'd implemented XHR, which allowed AJAX and the rest of the interactive techniques.
You haven't lived until you've had a convicted monopolist with rooms full of lawyers who sat in a room debating whether to arbitrarily snuff out your company by suing you into oblivion for making something compatible with their browser (once you've grown juuust big enough, and seen your peer companies destroyed after crossing a threshold). THAT's why there's such a lingering, smoldering distaste for Microsoft. They intentionally broke the interoperable internet, and intentionally smashed innovative technology with dual clubs called "legal" and "finanacial".
The other fun bits as competitor technologies in the proto-internet era were: BBS's with ANSI graphics, then "RipScript" as proto-SVG. Followed by Prodigy, which was effectively a proto-browser (with its own vector-like rendering capabilities).
Even gopher, a more text-based browsing experience, was a competitor to Mosaic 1.0, as nobody knew what the internet was supposed to be back then. Along with lynx, and links, which are conceptually awesome, except that CSS (layout vs hierarchy) and JS (interaction vs declaration) have rendered (har har) them obsolete.
Can't forget to mention AOL-server (with TCL), and NSS... Netscape Secure Server, which invented(!) SSL and for a while was the only way to serve secure traffic. Absolutely unavailable to the hobbyist, as it was a very expensive product.
There's few alternate outcomes, but open source, and monopolist financial capture have skewed the web we have now.
If I could have a magic wand, I'd shoot for 402-Payment-Required, and would be hesitant to encourage truly global (universal) aggregation of content for searching.
We're in a duality where "only google" can download and index the whole internet every day and "only facebook" has access to "the facebooks".
Facebook having a business incentive to trap event data, and merchant/for-sale data behind a login requirement is a huge loss for the open internet.
Google being "the gatekeeper" to navigating (omni-box + advertising replacing DNS) is also a loss for the open internet. Don't believe me? Try and set your browser homepage in chrome. It'll only ever open it up ONCE, when the browser opens for the first time. Not for new tabs, not for new windows, not without a janky extension.
> but launched it forward (accidentally) again by forgetting that they'd implemented XHR, which allowed AJAX and the rest of the interactive techniques.
In fairness, Microsoft introduced an ActiveX control that could load external resources without leaving the page. A few versions in fact that were not compatible with one another.
It was the Netscape/Mozilla folks who gave it its own fixed API independent of ActiveX that Microsoft and others later adopted years later and would become a standard, complete with wacky capitalization.
It was implemented and delivered by Chris Blizzard shortly after I had asked him for it at the Mozilla Developers Conference in 2000. (To be clear, I did no work on it and am not trying to take credit. The team was asking for feedback from attendees, and we were a relatively small gathering back then. Just establishing I was an eyewitness to the events.)
> <H1><FONT COLOR=red>...</FONT></H1> …every single goddamn time.
is in fashion again! Only now it’s called class="text-red-500" :o)