After so many "I hate CSS" articles, how is it that CSS is still so successful?

If you've ever googled "why do developers hate CSS", you know there's a flood of complaints waiting to be found online. Thousands of forum posts, tweets, memes, and long blog entries lament CSS’s "incomprehensible behavior," its "not-really-programming" nature, or the idea that it's "just for designers." It almost feels like one of the unspoken rules of developer culture is that CSS is a necessary evil—something you use only when you absolutely have to, and preferably as quickly as possible. But if so many people hate it this much—why hasn't it disappeared? In fact, why do we see more and more non-web UI platforms adopting CSS-like semantics?

Of course, frustrations with CSS aren't entirely unfounded. Most of the complaints trace back to a few core issues: the unfamiliarity of the declarative approach, the context-sensitive behavior, the complexity of specificity and the cascade, or the challenges of breakpoints and responsive design. The fact that a margin: auto works perfectly one day and then does nothing the next understandably raises questions—especially for those used to imperative logic. CSS doesn’t explain itself, doesn’t give feedback, doesn’t "throw errors"—it just silently fails to look the way we intended.

But this kind of silent resistance isn’t purely technical. CSS is a strange hybrid: not code in the traditional sense, but not a mere configuration file either. It sits at the intersection of visual and technical thinking, which makes it difficult to define whose “job” it really is. Some feel it belongs to designers; others believe it's a space where developers can express real creativity. But here, creativity doesn't come from algorithms—it comes from typographic rhythm and visual hierarchy, which, for many, lies outside their comfort zone.

Perhaps it's this discomfort that drives much of the aversion to CSS. The tool is treated like a “magic layer” hidden beneath browsers—much like JavaScript used to be in the early days of cross-browser scripting—except now CSS has become the new scapegoat. Debugging is hard, results aren’t always deterministic, and success often relies more on visual intuition than on logical reasoning. As a result, CSS is seen as something to be tolerated, rather than as an equal part of the development process.

And yet, despite all the complaints, CSS persists. In fact, it’s spreading. More and more systems outside the web are adopting its syntax, its model, its way of thinking. This isn’t just nostalgia or inertia. For some reason, developers keep returning to it—grudgingly, perhaps, but consistently. Maybe it’s time we started asking why.

What is the secret behind CSS’s success?

Despite the frustrations surrounding it, one fact is undeniable: CSS is a success. Not only successful, but it has evolved into a powerful standard that extends far beyond web-specific solutions. Many technologies that were not originally web-based—such as JavaFX, Qt, GTK, Avalonia, or Unity—have chosen to model their own styling systems on CSS. But why?

The key to its success lies first and foremost in the fact that CSS is not just a language—it is also an approach. It offers an abstraction layer that separates application logic from presentation—a separation of concerns long considered ideal in software development. The structure of a webpage or application (HTML, XML, component trees, etc.) can function completely independently of how it looks. This enables parallel development: designers can focus on the look and feel while developers work on functionality—and this holds true not only for the web, but for any platform.

A second important factor is the declarative nature of CSS. It’s a language that doesn’t describe algorithms, but rather states and rules: we define what something should look like, not how to achieve it step by step. This kind of descriptive model is highly intuitive—even for those who are not traditional programmers. As a result, CSS-like styling languages are easy to adopt in environments where not all contributors are developers—for instance, designers, UI specialists, or documentation writers may also influence the appearance.

The third factor is flexibility and adaptability. CSS was designed from the beginning to adapt to different devices, screen sizes, media types, and user preferences. Today, this adaptability is just as crucial in desktop and mobile application development, where it’s essential that a UI be easily themeable, scalable, and even customizable at runtime. CSS essentially provides a ready-made solution: external stylesheets, inheritance, overrides, theming—all of which are easily reusable in other environments.

Last but not least, CSS’s success is also due to its robustness and tolerance of errors. If a rule cannot be interpreted, it is simply ignored. This allows for incremental evolution and backward compatibility—essential not only on the web, but also in desktop UI toolkits where consistency must be maintained across systems, versions, or themes.

These principles—clean separation of concerns, declarative syntax, adaptability, and forgiving error handling—are not unique to the web. They are broadly useful patterns in UI development of all kinds. It’s no coincidence, then, that JavaFX, Qt, GTK, and even Unity have introduced CSS-like styling languages. All this suggests that CSS has not survived widespread criticism because we stubbornly cling to it, but because it has become functionally indispensable.

JavaFX and the CSS Approach

JavaFX was one of the first non-web UI technologies to consciously adopt the CSS approach—not just as inspiration, but by actually incorporating a CSS-like language into the framework. JavaFX CSS may at first glance look familiar to web developers, as its syntax closely resembles W3C standards. However, it wasn’t designed for browsers, so in many ways it differs from what we’re used to in the classic HTML + CSS pairing.

In JavaFX, stylesheets are defined in .css files, but they apply to Java objects rather than HTML DOM elements. A Button or Label, for example, is not a markup tag but a class instance in the scene graph, so CSS selectors target Java class names, IDs, and style classes. Property names are also more verbose: the -fx- prefix clearly indicates that these are JavaFX-specific declarations—e.g. -fx-background-color, -fx-font-size.

JavaFX CSS has a unique strength in its tight integration with the JavaFX API. Declared styles map directly to the setter methods of components, so the stylesheets function as a kind of reflective configuration layer. This makes it possible to change styles or add new ones at runtime (getStylesheets().add(...)), which is especially useful for dynamically changing UIs, such as theme switching.

JavaFX CSS inherits the key behaviors of classic CSS: cascading, specificity, inheritance, and pseudo-classes (e.g. :hover, :focused, :disabled) are all supported, though their implementation details differ. For instance, within a JavaFX UI, :hover doesn’t track mouse events in the DOM but relies on JavaFX’s own event handling system.

What’s particularly noteworthy is that JavaFX CSS isn’t a mere copy—it’s a deliberately adapted system. It recognizes that there is no browser, no DOM, and no HTML; instead, there is a Java-based scene graph where each element is an object. The goal of the stylesheet is not DOM manipulation, but declarative configuration of object instance properties. This makes it easy to style individual components and even assign stylesheets to entirely new elements.

All in all, JavaFX CSS demonstrates that the CSS approach is not tied to the web—a UI toolkit can benefit from it if adapted thoughtfully. The advantages of familiar syntax and declarative design are clearly visible here: interfaces are easy to redesign, styles are easy to reuse, and the separation between designers and developers is supported. JavaFX has thus become not only a follower, but a meaningful extension of the successful CSS model.

Qt and QSS

The QSS (Qt Style Sheets) used in the Qt framework is another excellent example of how the CSS approach can transcend the web environment and successfully establish itself in an entirely different type of UI system. QSS is not merely "CSS for Qt," but a carefully adapted, CSS-inspired styling language that makes the appearance of Qt-based applications just as easily customizable and redesignable as a web page.

QSS’s biggest appeal lies in its familiarity. For those who have worked with CSS on the web, the syntax of QSS will feel immediately recognizable. Selectors, properties, values, pseudo-states—it’s all there, only applied to Qt widgets instead of HTML elements. A QPushButton:hover rule behaves just like an a:hover rule on the web: we describe declaratively how the appearance should change in response to certain interactions. This familiarity is not just convenient, it’s also efficient—developers don’t need to learn a new language, only the specific nuances of Qt.

Of course, QSS is not a one-to-one copy of CSS. Due to Qt’s internal widget and event handling model, some differences are inevitable. For instance, inheritance does not always work automatically: color and font styles in QSS do not necessarily propagate to child elements, so developers must explicitly indicate if that is the desired behavior. While this requires more effort, it also gives finer control over the look and feel.

What makes QSS particularly interesting is that it’s not limited to static theming—it can also be applied dynamically, even at runtime. One stylesheet can easily be replaced with another; for example, switching between light and dark themes can be done without redrawing existing widgets. This not only simplifies development but also provides users with a responsive, customizable interface in real time—exactly what we expect from a modern application today.

The decision to bring CSS-like semantics into the Qt world was not mere imitation, but a strategic reuse of a proven model. The result is a flexible, declarative styling language that supports the separation of logic and appearance, enables parallel workflows between designers and developers, and results in scalable, maintainable user interfaces. All of this further reinforces the idea that CSS is not just a web technology—it’s an approach that has become a fundamental building block of modern UI design.

Avalonia Styles

The styling system of the Avalonia UI framework, known as Avalonia Styles, is conceptually similar to CSS used in web development—but in reality, it’s a completely different, XAML-based solution tailored specifically to the needs of .NET-based, cross-platform desktop applications. The main similarity lies in how styles are declared: Avalonia also uses a selector-based syntax, allowing visual attributes to be applied to classes or types—just like in CSS.

In both Avalonia and CSS, the classification of elements plays a central role. The declaration <TextBlock Classes="h1 blue">, for instance, is the Avalonia equivalent of <div class="h1 blue"> in HTML, and allows multiple styles to be combined. Inheritance and overriding (or cascading) of styles are also key features: globally defined rules can be locally overridden, enabling a flexible and scalable approach to user interface design.

However, the differences between the two systems are equally significant. Avalonia Styles does not use a standalone styling language; instead, it defines properties directly within XAML markup using Style and Setter elements that target the .NET property system (e.g., FontSize, Foreground). Additionally, Avalonia natively supports advanced features such as ControlTheme (for reusable, "lookless" control rendering) and triggers for conditional logic—capabilities that CSS can only approach to a limited extent through features like :hover or @media rules.

All in all, Avalonia Styles is a CSS-inspired yet completely unique system, purpose-built for the desktop. Developers familiar with web-based CSS will find it relatively easy to pick up, but they should be prepared for platform-specific differences in both syntax and functionality.

Conclusion

The success of CSS is not due to universal admiration—it’s because it provides practical and scalable solutions to problems shared by all UI systems. Its declarative nature, clear separation of presentation and logic, flexible theming, and tolerance to errors make it valuable not just on the web, but in any environment where UI design plays a role. JavaFX, Qt, and Avalonia did not “copy” CSS out of a lack of alternatives—they adopted its principles because they simply work.

CSS may seem difficult, unpredictable, or even frustrating—but that perception is more a result of its unconventional approach than actual shortcomings. Once we stop thinking of it as imperative code and start seeing it as a language for describing visual behavior patterns, a clearer and more predictable system emerges. At that point, CSS is no longer just a “necessary evil” of the web—it becomes a universal toolkit for designing visual systems.

So CSS hasn’t just survived the hate—it has outgrown it. 

Share this post
According to Replit's CEO, AI Will Make Programming More Human
The rise of artificial intelligence is transforming countless industries, and software development is no exception. While many fear that AI will take over jobs and bring about a dystopian future, Amjad Masad, CEO of Replit, sees it differently. He believes AI will make work more human, interactive, and versatile. He elaborated on this vision in an interview on Y Combinator’s YouTube channel, which serves as the primary source for this article.
A new era in software development
Over the past few decades, software development has fundamentally shaped our digital world, but the latest technological breakthroughs are ushering in a new era in which computer programming is undergoing a radical transformation. According to Andrej Karpathy, former director of artificial intelligence at Tesla, software development has accelerated dramatically in recent years after decades of slow change, fundamentally rewriting our understanding of programming.
Google Cloud Run Adds GPU Support for AI and Batch Workloads
Google Cloud has officially launched general availability of NVIDIA GPU support for Cloud Run, marking a major step forward in its serverless platform. This update aims to give developers a cost-effective, scalable solution for GPU-powered tasks, especially those involving AI inference and batch processing. It addresses the rising need for accessible, production-ready GPU resources in the cloud—while preserving the key features that have made Cloud Run popular with developers.
Gemini Advanced Strengthens GitHub Integration
There is no shortage of innovation in the world of AI-based development tools. Google has now announced direct GitHub integration for its premium AI assistant, Gemini Advanced. This move is not only a response to similar developments by its competitor OpenAI, but also a significant step forward in improving developer workflows.
Apple Plans Its Own “Vibe-Coding” Platform in Partnership with Anthropic
Apple has encountered several challenges in developing its own AI solutions recently, so it’s perhaps unsurprising that the company is turning to external expertise. According to the latest reports, Apple has decided to join forces with Anthropic to create a revolutionary “vibe-coding” software platform that uses generative AI to write, edit, and test programmers’ code.
Jakarta EE Web Profile 11 Has Been Released
A bit later than originally planned, version 11 of the Jakarta EE Web Profile—maintained by the Eclipse Foundation—has officially arrived, bringing major improvements over previous releases.