Hacker News new | past | comments | ask | show | jobs | submit login
In defense of functional CSS (mikecr.it)
206 points by sebst on Sept 27, 2018 | hide | past | favorite | 240 comments



How is this any different from saying "don't write functions, just repeat the same 10 lines the function would have in each place you'd use the function"?

The real kicker:

> "I don't want to have to repeat the same 20 classes on every single button." That's understandable. I will say that there's a chance that repeating those 20 classes can actually be somewhat valuable, because when you get into a situation where one of the buttons needs to have slightly more margin-top than the others, then it's easy to fix.

That's just... bizarre, sorry.

It's infinitely better programming practice to use a "button" CSS class, because then every time you want to tweak all buttons on the site, you tweak it in one place. With 100 buttons in different places, can you imagine the maintenance nightmare?

The author suggests creating button HTML templates instead... but why? That's what CSS already does. And when one button needs more margin or whatever other unique tweak... you just add an additional class so it becomes e.g. class="button button-extra-spaced".

For the life of me I can't see any advantages to the "functional CSS" described here at all -- it looks like a nightmare programming practice.


Disclaimer: we have been using functional css for about 2 years.

Let's review the main use case you present "I want to tweak all buttons on the site, I tweak it in one place":

- How many times do I have to change all the buttons on my app?

- Does changing one class work to change all buttons in practice? Don't I end up having the color overloaded 3 times, cascading over and leaking in 5 others spots?

- Are most of my edits in CSS tweaking existing rules, or piling up more CSS? Usually, in a large codebase, I end up just adding a class instead of tweaking one and figuring out if I broke anything anywhere.

- If I use a component-based approach, like Angular or React, do I really have to change classes everywhere with functional css, or just in the button component?

- Is styling "functional"? Can I always change the styling of a class without changing its semantics - like if I put the primary button the same as the secondary, did the naming help?

Your case may be different and our point of view may also evolve. With functional CSS + component-based approach, I rarely have to use the style inspector - and produce beautiful, maintainable app with 14KB of CSS and no styling bug. All my other attempts using CSS "the right way" lead me to 1MB+ of CSS.

The benefits of CSS to factor style by function seems very infrequent compared to the problems they introduce.


> - How many times do I have to change all the buttons on my app?

When making a styling change like this, it's typical to change it app-wide.

> - Does changing one class work to change all buttons in practice? Don't I end up having the color overloaded 3 times, cascading over and leaking in 5 others spots?

I can change the border-radius on all of my buttons, and they will all change, and still have their color-specific classes.

> - Are most of my edits in CSS tweaking existing rules, or piling up more CSS? Usually, in a large codebase, I end up just adding a class instead of tweaking one and figuring out if I broke anything anywhere.

This is unfortunately quite common in practice - because maintenance is hard and practices are bad. But it is definitely possible to have robust, reusable css.

> - If I use a component-based approach, like Angular or React, do I really have to change classes everywhere with functional css, or just in the button component?

Phew! A component just for a button. What a twist! I don't think most people are making components for each html element. In fact, I'd say this is pretty redundant and overengineering things in a bad way. Guess what - html has these nifty components called buttons too, and you can also style them. Wouldn't any minor change to your button component require then passing in props (just like classes)? <Button propName={"danger"}><button></button></Button> doesn't really seem better than <button class="btn--danger"></button> to me.

> - Is styling "functional"? Can I always change the styling of a class without changing its semantics - like if I put the primary button the same as the secondary, did the naming help?

Not really sure what you're getting at here.


> Phew! A component just for a button. What a twist! I don't think most people are making components for each html element. In fact, I'd say this is pretty redundant and overengineering things in a bad way. Guess what - html has these nifty components called buttons too, and you can also style them. Wouldn't any minor change to your button component require then passing in props (just like classes)? <Button propName={"danger"}><button></button></Button> doesn't really seem better than <button class="btn--danger"></button> to me.

We use custom components like this at work, and it actually works quite nicely because you get to see all the different "types" of buttons at a glance by looking at the prop types. Using the component looks something like this:

<Button label="Click me!" primary />

I've found that it's helpful for enforcing consistency, so that you have to go out of your way to apply custom styles to a button (which isn't required 95% of the time). Plus, it helps abstract things that don't have anything to do with the <button> HTML element but are often tied together, like being able to automatically make a button a link without having to wrap it in an <a> tag:

<Button label="Home" href="/" />

It's all minor stuff, but it enforces consistency and keeps you from having to think about CSS classes at all most of the time.


> Phew! A component just for a button. What a twist! I don't think most people are making components for each html element. In fact, I'd say this is pretty redundant and overengineering things in a bad way.

Welcome to the world of web components. This is actually really common, especially in React with css modules - this way you can use your custom button without even having to think about the CSS (or any extra complexity like tooltips and accessibility), even from a common library used across projects.


I want to call this "transverse encapsulation."


Hey! I'm using basically a Bootstrap-like syntax for my own "framework" at work. We've been running it for almost 4 years so I'd love to respond to everything your saying:

1. it does actually happen but more often than not, individual buttons need some changes.

2. absolutely but that's why we use SCSS to help "cascade" those changes. Unfortunately, those large changes, again, require individual tweaks in some tricky areas.

3. adding classes is always the safer approach. One thing that has helped us is to make sure classes hold little (but valuable!) responsibility.

4. this is an awesome question. So, for us, those little adjustments specified in the post (small margins and so on) were tweaked at component-CSS level while large-changes were kept to our SCSS framework

5. It's basically CSS-in-HTML

So my own experience has taught me a general approach of my own:

1. create a framework for your site in SCSS. This includes basic styles for buttons, input boxes, colors, typography, tables etc. but stay away from more complicated styles (like trying to create CSS for a "profile card")

2. keep "component" CSS inside a component. Profile card CSS goes in profile.component.scss

3. overrides/hacks belong to where those overrides/hacks need to happen.


I've been working with the front end for over a decade now in small and big teams, with different approach to CSS. I've seen things go horribly wrong for all the seemingly good reasons. Bloated CSS, people fearing to make any changes to existing "semantic" classes, people making changes to existing classes and introducing unforeseeable bugs in remote parts of the application, you name it. In my view nothing beats functional CSS. It's simple, pragmatic, easy to read and understand. And most importantly it'd hard to introduce hidden bugs with this approach.


> Usually, in a large codebase, I end up just adding a class instead of tweaking one and figuring out if I broke anything anywhere.

It's very easy to just make another CSS class everywhere, but that defeats the point of CSS and you might as well just use inline styles.

Clean well maintained CSS makes a huge difference. The problem is your CSS needs to map to semantic meaning of what's going on, and you need to maintain the effort to keep it clean.

> How many times do I have to change all the buttons on my app?

How about how often do you need to change all your 'submit' buttons? The HTML element type is again vastly less important than what each element means.


I'm not sure why that was suggested. Our team has migrated to utility css (Tailwind) and we never do this. The basic approaches are either to create a component or template for the button and put the utility class there or use Tailwind's `@apply` utility to create a `.button` class with the utilities applied to that class.

I had some reservations at first but in practice it's been pretty much universally agreed to be great for us. It removes a huge amounts of css cruft that happens over time (unable to determine which classes are still being used, where, etc), keeps colors, margins, etc. standardized through a centralized config file and prevents you from constantly bouncing back and forth between style and markup files.


First line of the first example you get in "what is Tailwind":

  <div class="bg-white
Just accept the fact your HTML contains your styling and go with:

  <div style="background:white"
There was a time when people thought CSS could be used to style some logical HTML:

  <div class="card-wrapper"
So the day you want to change the color of your card-wrapper from white to green you can change a line in some CSS and not have to go around all your HTML or end with a <div class="bg-white"> with a green background.

CSS frameworks feel like a "let's get all the shit CSS was meant to help remove and just put it in divs".


Yeah, think that's everyone's first reaction (you shouldn't mix style and markup) but with a component centered development pattern, those concerns largely become non-issues. `card-wrapper` becomes a component and you update your styles there.

I will just say theory aside, in practice, this has worked out great for our team. In my 5+ years experience, I've constantly run across the issue of legacy code with thousands of classes, referencing potentially non-existent markup and countless one-off tweaks. You can start with the best intentions and organization in your SASS files but eventually things start to get really crufty. Keeping everything in components and keeping styles in the markup alleviates a lot of that.


On that note, would love to see developer tools in the major browsers complain with warnings about missing CSS classes :/


> CSS frameworks feel like a "let's get all the shit CSS was meant to help remove and just put it in divs".

You just made me realize this is why I always have a hard time every time I try a CSS frameworks.

It always goes the same way. I'm first amaze by all what they offer, how simple and quick a great UI can be made. Then when I try to use it, there's always something wrong and I hate how it goes and I always stop and goes back to the logical ways to do it entirely in CSS.

I guess I should try some CSS preprocessor, they must support heritage of CSS class I guess.


You should, you can have mixins, class inheritance, the whole shebang.


We do this with less + bootstrap. So we'll have have something like

.button-critical{ .btn .btn-red }


This has essentially been my experience with using this. I don't see how it even comes close to 'functional' in style, it just feels like it makes CSS even more painful to deal with than it already is.

Working with CSS is fairly unglamourous. These functional frameworks don't really appear to be a solution to me. What they've done is basically take CSS and create a DSL that has to squeeze into a `class` attribute, without actually adding any extra value than what you would get from writing raw CSS. You don't really get consistency out of it. Just terseness.

This becomes even more bizarre when you see these frameworks used with preprocessors like postcss, because what you end up with then is basically spaghetti.

    .some-button {
      @compose mt-2 my-4 p3 border-radius flex align-bottom;
      margin-right: 32px;
      border-radius-bottom-right: 2rem;

      &:disabled {
        display: none;
      }
    }
At what point did all of this become an advantage?


Yeah, I really don't get it. As for this part:

> when you get into a situation where one of the buttons needs to have slightly more margin-top than the others, then it's easy to fix

You can have this with semantic classnames. In fact, that's exactly what the "cascading"[1] part of "cascading style sheets" was intended to solve.

[1]: http://cssspecificity.com/


Cascading is bad and creates more problems than it solves.


This is definitely the opposite of my experience.


It breaks encapsulation, leaks styles, you have to fight specificity and it makes it hard to change markup and many more.


You’re 100% correct on the cascade being bad and causing incidental breakage. The people downvoting have clearly not run into these problems yet or it would be obvious to them that your reply is in no way wrong, lol


I see the downvotes already coming. Cascading is bad, it makes it hard or impossible to restructure things and move markup around. And then you have to fight specificity. An example from my work where someone put a bunch of tags under `.new-style` like `.new-style h1` and applies to every container which needs those new styles. Now if I add my component to that container, it completely breaks encapsulation because `.my-component-title` gets overridden by `.new-style h1`. And then you fight that with something ridiculous like repeating classes `.my-component-title.my-component-title`.


In other words, improperly used cascading is bad? (didn't downvote you FWIW)


Yes and (moslty) no. Cascading that reaches “outside” of its component to affect other things is bad. So it is all about your approach to the cascade. Most people who have been working on the front end still struggle to grasp the concept of encapsulation & isolation when it comes to their CSS.

In my experience working on a web app that sees +80k DAU, the most difficult updates to our UI are ALWAYS in the cases where somebody wasnt cogniscent of the cascade. Or was, and used it when they shouldn’t have.

IMO, theres a lot of pushback to this technique and not a lot of questions into its benefits, but plenty of questions as to why its “just like this” so “why should I use it.”

I encourage you to consider the benefits of an isolated approach to UI, or perhaps try building something with it and see how the method compares to your current approach.

Or, we can all go on assuming that Airbnb, Facebook, IG, et al, have all opted into this approach for no reason


100% agree with you. I stopped reading after this statement:

>when you get into a situation where one of the buttons needs to have slightly more margin-top than the others, then it's easy to fix.

It's easy to fix in "regular" css too: just add style="margin-top: 10px;" to the button.

If this is really a one-off situation, then that is totally fine. Functional CSS feels like over-engineering an already-solved problem.


I really hate the phrase "over-engineering". My oppinion is that at this point, its is nothing more than a fancy way to say - "I think this is bad" (or sometimes worse: "I don't understand this, and since I don't understand it, it must be bad").

And this is a great example of that theory. If one had to apply the terms "over" or "under" to describe the engineering of the practice the article describes, it seems like "under engineered" would be the more apt description. This is pure brute force programming and design.


You totally ignore design systems here. Similar to color palettes you want named styles for consistency and to show purpose (e.g. margin-small, margin-large, etc). Hardcoding margin:10px throws all that away.


The point of this, imo, though, is instead of having a designer design a bunch of components, you have a designer design a bunch of functional styles that can compose components and still be on-brand. So say you have a component, and you want to add an on-brand/in-style shadow to it, you just add the small-shadow class, instead of digging through the css of other components and copy-pasting their lengthy shadow css. I would use this mainly for shadows, fonts, and margins.


> Because then every time you want to tweak all buttons on the site, you tweak it in one place.

What do you do, when the button markup changes? Let's say you need to make all links open in a new window? Then you still need to change 100 buttons. It's even more common for bigger components, like the ProfileCard example. What if the markup of your ProfileCard changes?

Instead of using CSS to define your components, I suggest using some real reusable components, either using templates or JS frameworks (depending on your use case).


> What do you do, when the button markup changes?

hopefully you'd have a Button component in your preferred UI framework, and you'd change it once there.


Exactly. The same applies to CSS when using the functional CSS approach. It's basically: if anything changes, I need to update my Button component.


Right. With the surge in popularity of components architectures, the maintainability concerns of inline styling methods are much less applicable. Perhaps there are other legitimate problems, but this one should be put to bed.


Open up Vim, and do a global find and replace with a simple regex. That's 100 or even 10,000 button changes in a minute.

That's not really related to "functional CSS" though.


Your simple regex will take you 1-2 additional minutes to deal with prettified code like this:

  <button
    href=".."
    class="...."
  >Button</button>
And when you start fixing more complex components and HTML edge cases, you will have a lot of fun [0]. This is fine for legacy code. But I don't want to deal with this in modern projects, if I can just change a single file and be sure all components are updated. As you said, this is not related to functional CSS, but it solves many disvantages of it.

[0] https://stackoverflow.com/questions/1732348/regex-match-open...


You _can_ have the best of both worlds though. For example, styletron[1] lets you write a "button" via something like

    const Button = styled('button', {/* styles here*/});
...and you get deduped atomic classes (plus proper source maps, so the debugging experience is actually pretty similar to vanilla CSS)

There are also more transparent ways to leverage existing functional css frameworks. For example, Mithril.js[2] lets you use CSS selectors in templates, so you can do things like:

    const Button = 'button.some.atomic.classes';
    m(Button) // equivalent to <Button /> in JSX
The problem with `class="button button-with-quirks"` has to do with specificity. Yes, you can edit the base class... but then you also need to go hunting for visual regressions anywhere you have a compound class because who knows what might be overwriting your edit and how. Also, your team needs to be extremely disciplined when dealing with 7 slightly different variations of left margin on a button (and usually they are not).

The two most important benefits of functional css that the post doesn't go into that are kinda important to the discussion are these:

- atomic styles can be deduped, making for smaller bundle sizes

- they make it nearly impossible to accrue specificity-related technical debt

Many of the downsides alluded in the article are solved by libraries like styletron.

[1] https://github.com/styletron/styletron/

[2] https://mithril.js.org


Personally, I like a compositional approach, but the "text-color-white" business is just cringeworthy. There's nothing about compositional/functional approach that requires someone to use silly just-above-an-inline-style classes.

    <div class="card notice alert-colors">
        Warning: frobnitz is dangling.  Please address.
    </div>
I gather it's because ridiculously literal styles are the only thing you can offer in an "un-opinionated" functional framework, because you'd otherwise have to engage in some styling.

ETA: And even "alert-colors" could probably be "alert" or the like, if I saw the consistent need to bold the text or whatever in alerts.


Seriously. This is just inline style with extra steps.


It really isn't. I'd say in some cases it's the opposite.

At my job, we have a mid-size React app where more or less every element has one CSS class with all the styling in it. There used to be more of a framework of reusable styles, but it doesn't get used much any more because it's out of date with what our designers want now. We should fix it, but there's no time because we have to pile on more features to fix later. You know the drill, I'm sure.

But basically, for more or less every HTML tag, there's a custom blob of CSS that's only applied once. This is inline styles, we've just moved them to a different set of files.


I mean in the real world I think the solution is somewhere in between. I use a combination of broad and specific classes so that mass-updates are still easy, but I'm not - as you say - writing a class for every element.


> How is this any different from saying "don't write functions, just repeat the same 10 lines the function would have in each place you'd use the function"?

I think it is more comparable to using function composition, hence the whole "Functional CSS" moniker. The idea is using multiple atomic "functions" (in this case, in the form of classes) to transform an element by composing.

Think like the pipe operator in Elixir:

other_function() |> new_function() |> baz() |> bar() |> foo()


It's actually nothing to do with the pipe operator in Elixir.

In any programming language, the order in which you compose functions is important.

In CSS — and in keeping with your analogy — the order in which "functions" are defined is important.


This is a really interesting discussion because it makes me wonder what CSS could have been like if it had cascaded per-element according to the order of classes.


I never said it has anything to do with the pipe operator, and I did not mean to imply that it is a direct equivalent to the pipe operator. But just as the pipe operator allows you to compose multiple pure functions, the idea with atomic CSS classes is that you are able to compose "pure" classes. The quotes are important here.

Obviously, they are not 100% comparable. CSS is not a programming language.


It's a weak analogy.

In programming, `f . g . h` is not the same as `h . f . g`.

In CSS, `<i class="a b c"></i>` is the same as `<i class="b c a"></i>`.

In programming, the order in which you define functions is not important — it's the order in which you use them which is important.

In CSS, it is the exact opposite.

To further drive the point home: assuming the names of these classes aren't lying, what colour is the text of this element?

<div class="text-red text-blue">foo</div>

It depends on the order in which the classes were defined. This also demonstrates why "pure" is a poor choice of word when describing anything to do with CSS. Nothing here is "pure".


I understood what you meant. Whether or not I'm supportive of the terminology used for "Functional CSS" is a different story.


It seems like at least his favorite css framework (tailwind) wants you to use @apply instead? https://tailwindcss.com/docs/functions-and-directives#apply


I think this advice is meant for the kind of person that uses CSS frameworks. You seem to be describing problems that don't come up if you're using, say, bootstrap.


Functions have rich abstraction capability e.g. they compose and such. CSS has primitive abstraction capabilities (That said, i'm unconvinced, but i'm listening)


> The author suggests creating button HTML templates instead... but why? That's what CSS already does

I think this is really the core of it, because CSS is kind of bad at it, and just about every project ships with more powerful HTML templating anyway.


Yikes.

I agree that this might help you move quickly when starting a project and might be a fine approach for a small prototype or personal site (or, more unkindly, in a consulting project). But you pay a huge cost: maintainability. There is no encapsulation at all, not to mention the pain of having all these generic classes floating around, colliding with anything that might accidentally match. I’ve worked on projects like this where huge HAML views chain many of these functional CSS classes. It makes it very difficult to accommodate new external components or design updates which I would say are pretty much inevitable in any product company. Even if you don’t add anything new, good luck updating the entire system to adjust the padding on all buttons unless you were disciplined enough to truly create encapsulating classes (which is really the opposite approach of functional CSS anyway).

I really think CSS modules got it right (or similar approaches where you have a unique class name per component). Our team approaches component styles like a UIView in iOS—it should render acceptably with reasonable constraints. This means any parent component / view can render this and set display: block, flex, etc and the contents should largely adapt. These days this is pretty easy with flexbox and grid. Even better—you can ensure that the markup classes stay private to you and only allow modifications through JS (or mark some classes as :global). Even better than that—your components can adopt delegation or renderProps to allow parent views to replace / modify with their own markup so everything in the component can truly be encapsulated.


> Yikes.

Agreed. Wholeheartedly.

> I agree that this might help you move quickly when starting a project

I don't even see this... at least I can't imagine a case where I'd want to replace "background: #333;" with "bg-gray-darker". The CSS has at least been well established for years/decades, and it'll be much easier to find documentation/support/etc.

> But you pay a huge cost: maintainability. There is no encapsulation at all,

He's advocating that the encapsulation happen at the level of templated markup (or JSX, whatever), rather than at the level of CSS classes.


The big difference between this and "background: #333" is that in the later case it could also be "background: #334" or "background: #435". The functional framework approach forces a minimal amount of consistency.


One thing I think CSS frameworks got wrong is mixing layout with style. At the time, maybe it was justified due to lack of layout options. But today, especially with grid, but even flexbox, layout can entirely be done by the framework's consumer, and should probably not be done by the framework itself, which should focus probably mostly on style. Unless of course it's a layout framework, but grid is so flexible and easy to work with that you probably don't need a layout framework. I'll just leave this here https://learncssgrid.com/


> One thing I think CSS frameworks got wrong is mixing layout with style.

I think some of this is due to the fact it was originally more about document layout than screen layout. At least the cases where I find CSS (horribly) awkward are cases where I'm trying to do something that falls more into the category of UI layout. For document formatting, it feels like a much better fit.


That said, there is nothing saying you can't combine this with some higher level classes when you need to DRY things up.


Author here. In retrospect a couple months after writing this post, I don't love it. I still am in love with Tailwind and Functional CSS, but I did a poor job defending it.

I'd suggest that everyone read this post [1] by Adam Wathan, the creator of Tailwind CSS. It does a much better job explaining and defending than I did.

[1] https://adamwathan.me/css-utility-classes-and-separation-of-...


Great article. The author mentions all the pain points I went through designing a mid-sized sass base... there's just too many ways to do things and it gets messy fast. It's hard to be both semantic and DRY at the same time.

Might as well just treat everything the same across the board, e.g. tailwinds and reduce the overall complexity of naming

I read many functional CSS articles but this one has convinced me to try it out


To be clear, you don't love the post, or you've changed your mind on functional CSS?


Ah sorry, I just meant I don't love the post (and I just updated my comment to make that more clear). If anything I am even more a fan of functional CSS now than I was when I wrote this.

But my post is just a bad defense of it. The section about the separation of concerns is especially unconvincing, and I spent almost no time talking about the benefits of it. I'd like to rewrite it at some point.


Well, hey, I dig the honesty.


This is a great article, it helped clarify my understanding of functional CSS and made some really good points.

However, I still don't think it is the complete answer. Mostly, if I'm wearing my developer hat (rather than designer hat), functional CSS would drive me batty. If you are working in a larger team, where some of the team write the HTML and some write the CSS styling, this really disadvantages the people who work with the HTML. As a developer, I need to write HTML where I am semantically describing what the component is doing as I have no idea about the details of the design.

What might work is a hybrid approach? That is, designers work with functional CSS and then at the end, map the compositions back to the semantic class styling? I.e you would do mostly the same thing, but would move the functional CSS styling into the CSS and have a mappings at the end. Would this give the best of both worlds - keeping the HTML semantic, but still allowing designers to mostly work with functional CSS?


Thanks for posting this! This article was a really good read that I think communicated the intent behind your original article much better.


Functional CSS is a terrific approach. Tailwind in particular is exemplary.

Absent this approach, in web projects of nearly any size, the CSS inevitably grows and becomes increasingly difficult to maintain. It takes very very few cases of "I'll just write a bit more CSS" as the default solution to bug fixes or changing requirements, before the best-intentioned design system becomes a brittle nightmare. Whereas functional CSS supports composition, and makes refactoring a reasonable proposition.

As a 20-year veteran of web UI development, I encourage skeptics to read Tailwind's docs, which make a better case than the OP or I are doing here.


so i'm on board with your central concern here. my issue with functional css is that your markup has no semantics. you can't just look at it and know what things are by their names. ie,

    <div class="m-5 p-5 text-gray-light bg-gray-darker border border-gray-light">
what the hell is that thing described by all those styles?

versus:

    <div class="profile-card">
and i know immediately what it is, and can instantly map the markup to what i see on the page.

you just lose too much by not having that imo.

i really like composing styles out of small little semantic utility classes as in the first example above, but you can do that and still have semantically named classes easily enough with a preprocessor.

i'd be curious to hear your thoughts on that. when i've discussed this concern with functional CSS purists they usually just shrug and say something like "you get used to it" or "you just don't need those semantic class names" but i find that response unsatisfactory.

clean, readable markup is so much more pleasant to work with.


From the other perspective, I know what "m-5 p-5 text-gray-light bg-gray-darker border border-gray-light" will look like and I can immediately change it. I have no idea what "profile-card" does, and if it's ultimately something I don't like I have to go through the whole asset pipeline to change it.

I'm not saying you're wrong, I think I'm more or less against functional CSS, but just saying there's at least one more way to look at it.


Yes, this is valid to point out as a tradeoff.

I weight clean markup and "knowing immediately where i am by looking at the code" more heavily in this particular balance scale, though -- it's a higher-level concern in some sense.

Practically speaking, I'd typically have the markup open side by side with the SASS (or other source CSS) file where "profile-card" was defined in vim, so the lookup process is just moving my eyes across the page.


One possible solution is in the article - nothing prevents you from using:

  <div class="profile-card m-5 p-5 text-gray-light bg-gray-darker border border-gray-light">
with "profile-card" being use just for identifying the component.

Other than that, I rarely go through HTML without Dev Tools, which shows me exactly what a certain div is for.


yeah that's better than nothing, but your markup is still super noisy and hard to scan.

> Other than that, I rarely go through HTML without Dev Tools, which shows me exactly what a certain div is for.

I do all the time. I'd much prefer to work in my text editor, without being obliged to use chrome tools to extract semantic meaning from my code.


var profileCard = "m-5 p-5 text-gray-light bg-gray-darker border border-gray-light"


"... your markup has no semantics. you can't just look at it and know what things are, by their names."

Huh? I think you've got it exactly backwards. My React components all have semantic names. In contrast, you're apparently using raw HTML "div" elements and relying solely on your style classes' names for semantics. You can certainly do that (with or without functional css) but it's orthogonal to the things that make Tailwind and functional css great, and your complaint makes me wonder about your setup; it's almost as if you're hand-writing and maintaining static HTML identical to what you see with "view source". Are we both talking about styling web applications?


> but it's orthogonal to the things that make Tailwind and functional css great

exactly. that's what i've been saying, and why i don't understand why "inline css" and "functional css" have been conflated.

i'm not sure why you're bringing up react -- i'm talking about the general case of writing markup. obviously you sometimes might write it directly by hand, and sometimes it might be generated for you by react components or server-side components or whatever.


There's another active post right now [1] where Tailwind's creator has been addressing these understandable initial reactions.

TLDR: Tailwind is utility-FIRST not utility-ONLY, and its `@apply` directive and approach to composition means you can exercise a lot of control without every element requiring so much "noise".

Don't get me wrong, I'm not saying there's only one good way to do things and this is obviously it; rather, it's worth overcoming one's initial revulsion to look at what's possible, bc it is in fact quite elegant.

[1] https://news.ycombinator.com/item?id=18084013


I'm sold on building up your UI through the composition of utility classes.

I just don't want them in my html. It's really not resistance that's at work here. I just think you should name your abstractions. Note this does not imply coupling. If you're so worried about that give every element a different name for all I care, put a number at the end of the names, but at least make them meaningful. I still want to be able to read my markup.

It's odd to me that functional-css seems to have gotten bound up with "inline everything." The two concepts are orthogonal. And it seems that the big benefit of having everything in line is... you only have to have one file open?

I mean, I guess that's simpler than two files side by side, but it's such a tiny benefit compared with readable markup imo.


classes like m-5 or p-2 can be semantic enough.

But using classes named with colors is silly.

It's as silly as naming a function based on the content of a string it's manipulating.

const str = "cat";

function reverseCat(str){

    return str.split("").reverse().join("");

}


> Absent this approach, in web projects of nearly any size, the CSS inevitably grows and becomes increasingly difficult to maintain.

In web apps (as opposed to web pages), this problem is better solved by breaking up and grouping CSS with its associated components. Re-use the components, not the CSS classes.

Regarding how to keep CSS modular, just give each component a unique name and apply styles to child elements using nested selectors:

    .exampleComponent .exampleItem {
      border: 1px solid #aaa;

      /* etc */
    }

This becomes even easier in SASS:

    .exampleComponent {
      /* put all the component's styles in here */

      .exampleItem {
        border: 1px solid #aaa;
      }
    }


But wait, what exactly is so hard about doing something like

    // _profile.scss
    .profile-card {
      @extend .m-5;
      // several more lines of extending
      @extend border-gray-light; 
    }
and just get the best of both worlds? That variant also has the advantage of letting us JS folk use element classes for useful stuff, and makes changing all instances of "profile-card" simultaneously a lot simpler.


I was wondering that as well. By that point, though, I've never found a point in using utility classes when I can just go to the file for my current component and edit it directly. Just writing specific CSS for my components and page-layouts while using shared variables has saved me way more time than any CSS library I've used. 99% of CSS libraries are full of problems


I think for css classes like ".profile-card" this approach makes a lot of sense. Tailwind has @apply, which is a great way to turn these utility classes into named css classes.

However, after a while your app will end up with classes like .profile-card--inner, .profile-card__wrapper, and .profile-card__inner__wrapper--horizontal. When that happens it's usually easier to use those utility classes directly in the HTML template. You'll end up with something like:

    <div class="flex items-center mb-4">
    </div>
It's quick to write and requires no context switching!


I don't get it as well, I just looked at Tailwind which is mentioned and it just seem to be a collection of css soup which don't mean anything, I think I would be lost quickly in a codebase with only this css soup.


Most of the people commenting are missing one of the major point in "functional CSS": Keep specifity low = lower code size, less side-effects, higher maintainability.

Yes, you add bits of complexity in the HTML, but you also gain almost no specifity on the CSS side.


Could you elaborate on this more? All three of these points seem counterintuitive to me.

1. "profile-card" takes fewer bytes than "m-5 p-5 text-gray-light bg-gray-darker border border-gray-light", so the space-savings of not defining profile-card within the CSS seems to be lost the more you reuse semantic styles within your HTML.

2. "m-5 p-5 text-gray-light bg-gray-darker border border-gray-light" and "profile-card" should amount to the same CSS styling applied at the same level of specificity in an apples-to-apples comparison, so I'm unsure about side effects. Are you saying that using exclusively functional styling you can count on naming conventions to know if two styles would conflict?

3. "m-5 p-5 text-gray-light bg-gray-darker border border-gray-light" looks a heck of a lot harder to maintain than "profile-card" once I have 50 profile cards in my application styling, spread out across multiple app development teams (and even development languages).

Are you saying it provides other maintainability benefits which are cross-cutting improvements that outlay the ability to think of your HTML as being made up of semantic components? Or are you saying that you are relying on component frameworks which make component definition in CSS a duplication?


1. Think about this: You have to write or customize .profile-card for every project, with "m-5 p-5 text-gray-light bg-gray-darker border border-gray-light" you're writing 0 lines of CSS. Zero. All your CSS will be your utility framework (sizes around 5~15kb) and it will never increase in size. Now, tell me you never seen a two year project where CSS alone reached 2+Mb because at every edit someone added another class to the list...

Also: When you gzip your HTML those repeated classes will compress pretty well.

2. Yes, you're right! Same specifity for the example in question. My point was more in general. Think @extend[0], nested selectors in SCSS. They look less scarier than "m-5 p-5 text-gray-light bg-gray-darker border border-gray-light" but they do not always do good.

And I can tell you'll have no side effects: If you look at the HTML only, what ".profile-card" does? Does it add padding, typography, borders, transitions? How do you extend it? I can't tell. But I know for sure that "m-5" will add margin and margin only. "bg-gray-darker" will add background-color and background-color only. And so on. Every class does only one thing. They don't overlap. Once you memorize the simple naming convention you can't go wrong.

3. Why it looks harder to maintain? Do you all really get scared by a few, readable, classes? Also, classes are no meant to be semantic or content-dependent[1].

At the end, I don't want to defend to death this practice. Maybe it's a concept that is hard to explain (and the OP tried a bit lightly) but I assure you, there are concrete benefits in using this approach. Many may not like it, and it's completely fine, but it's not the hell most of you are shouting here.

Peace! :)

[0]: https://webinista.com/updates/dont-use-extend-sass/ [1]: http://nicolasgallagher.com/about-html-semantics-front-end-a...


> At the end, I don't want to defend to death this practice.

I tried to phrase things such that I didn't seem to come across as aggressive. We all have such limited views of the world, and opinions are an expression of those views. I found attempting to understand other opinions can widen your own viewpoint, sometimes in surprising ways :-)

My expectation of what people would give as their three benefits are as follows:

1) abstraction of CSS - CSS is not especially crafted to be readable, and you typically need to code workarounds for older browsers using legacy/vendor styles and progressive enhancement. Merely using a functional CSS framework can make the CSS much more readable than manually specifying style information.

2) DRY/directness in component frameworks - if I'm abstracting a profile card into a component, there is little value to stylize based on a profile-card class, especially if that means my style is now separate from the rest of the component definition.

However, if you are not using a component framework but instead using something like templated HTML pages, you really do worry about whether people will identify a particular piece of markup as a profile card or the like, or that profile cards on one page will start to deviate from the rest of the app.

3) (Harder for me to explain) one of the maintenance issues with CSS comes from (logical) components, selectors, and styles all having M:N relationships with each other. So I might define my profile-card styling entirely within a single selector. But I might also elsewhere say something like:

``` a, .nav .selected, .profile-card .info { color: #ed0a1f; } ```

This is slightly different from the concept of side effects, but IMHO this is what makes CSS so difficult to reason about and maintain.

Use of functional CSS (and encouragement to embed styles within the HTML directly, rather than composing new classes via something like @apply in a stylesheet) means that you have created a pretty clear/classical relationship of styles to presentation.

So you might make an argument that classes should be leveraged more for semantic information, the actual styling becomes much simpler.

That sort of argument would make me wonder if there is a potential tool for those who are using templating rather than component frameworks for their buildout - a CSS lint tool that encourages you to use semantic classes, but that those classes must be composed entirely from an extensible set of functional components, rather than raw CSS.


I'm sorry, didn't want to appear aggressive either. Maybe when I wrote my comment I was influenced by the great number of negative comments here, but obviously, nothing personal!

Maybe there is a lot of confusion also because the naming of this methodology. The whole "functional" thing. It's funny that the very same practice has also been called "Atomic CSS" and "Object-Oriented CSS (OOCSS)"(!).

I would name it "Non-Cascading Style Sheets" because the whole point is actually giving away most of the "C" in "CSS".

I was also thinking that another point of such negativity may be that to use it you have to somehow master all the CSS rules, where not-so-experienced developers may rely on some "trial and error" or some bad pratice (eg. adding many nested selectors) to achive the same result. I might be wrong.

I remember that there are tools that throw a warning when a class is mutated (ie. overwritten by another rule) because you don't really want to - let's say - add a border when using something like "bg-gray-darker".

Yes, this practice can be a great choice for component frameworks. But it's also great for rapid prototyping and designing UI components or whole web pages directly in the browser.

And for templated HTML pages you can be more expressive using something like

    "profile-card: m-5 p-5 text-gray-light bg-gray-darker border border-gray-light" 
Where the "profile-card:" bit has no effect on the presentation but gives the code reader an insight of the markup.

I actually used to do something like this at first during prototyping/designing, but then I stopped. Maybe just because at some point I became so accustomed that I was able to catch every part of the page at first sight.


You're changing the source order doing this which can get messy plus generating a lot of long selectors. Example:

  .m4, .profile-card, .other-card,
  .header, .foo, blah {
    margin: 4em;
  }


I just posted the same thing before getting to your comment.

Additional benefit: you can nest stuff. So you card will include a nice dropshadow/border mix with you also can use on it's own somewhere else.


This is an underrated comment, and if you're planning to maintain a large web site this is the way to go, in my mind.


Awful idea. Just awful. The reason for splitting content (+hooks in form of CSS classes) and presentation is to make problem space smaller. If you say that HTML is now concerned with presentation too, you are basically going back to inline styles. And yes, I would prefer style "font-size: 10px" to class "fs10" anytime. At least I don't need to learn new classes with every single codebase I come across. There is a reason developers get emotional when someone tries to defend ideas like this - it's not because we don't understand, it's because we do, and we've been there. The location of the CSS is a solved problem, just let it be.


This is really bad advice.

You reduce errors by reducing code by wrapping your code in functions, thats functional and its how classes work. This article suggests the opposite just write everything from scratch perfectly, not going to happen.

> there's nothing stopping you from continuing to add those semantic classes, even if they're irrelevant for styling If they are irrelevant to style then it could be applied to anything, it has no meaning and is not semantic.

They don't know what separation of concerns is, or why its a good thing.

>when you get into a situation where one of the buttons needs to have slightly more margin-top than the others

Yea just break your designs consistency im sure your users will love that.


I tried this at one company. I have never gone back. It's terrible advice? You can only reconcile this as a matter of experience.


> You can only reconcile this as a matter of experience.

I was able to give three common and specific reasons why its bad advice, none of them where to just trust me, or my experience.

If the only reason you like something is because you like it, fair enough, good for you, you like a thing. Its ok to like things, but that doesn't mean there is any solid logic backing the things you like.


This seems to misunderstand the basics of why we have CSS in the first place, to separate "how something appears" from "what something is", and suggests to mix the two.

The obvious result is that you would end up with similar objects with different styles. A button with "main" role should have a consistent style across instances, not be green in one place and grey in another because you forgot to add the "green" class. Also changing the color of "main" buttons from green to blue should not entail changing each usage of the "green" class to a usage of a "blue" class.


I often wonder how useful this septation actually is. Most of the apps I have worked on seem to be horribly coupled despite separate css.


You can introduce implicit coupling in any app (i.e. in a non-CSS programming language). It's bad practice in both cases.

This kind of separation doesn't magically make your frontend code good, it just gives you the freedom to architect it well. Whether you do is up to you.

Admittedly it is very difficult to find an example where this has been done well, but this is I guess why we have abominations like AMP.


Sure it is bad design, I won't argue with you on that.

But the other thing is that we rarely upgrade just CSS, usually we get a whole new front end, or even more likely a whole new app.


This. In addition, it means you have to edit multiple things to change how something looks.

If .login-box is now going to be larger but green, you'd normally just edit the CSS to change that.

With visual classes, you might have to modify the HTML to add/remove/change classes, then also edit the CSS. Or maybe only the HTML. Or maybe only the CSS. It's hard to know.


> If .login-box is now going to be larger but green, you'd normally just edit the CSS to change that.

No you don't, you can edit the one LESS/SASS/whatever file, and rebuild to reflect the change in your custom class that mixes in the desired properties, done. Or you do the same in your HTML templating language. All of the code reuse patterns you're used to from regular programming are applicable here, and that's why it's better.

Also, if you're in a larger team with separation of responsibilities, then the UI-focused person can make the change without you without having to understand CSS. Functional CSS is considerably more flexible.


I think you misread my comment. By 'normally' I mean using regular 'CSS controls how something looks' HTML, and not using visual class names (that this author calls 'functional CSS').


I quoted the wrong sentence, I meant to reply to the "you'd have to edit the HTML" aspect. Functional CSS lets you wrap up composite styles in various ways, similar to abstracting a function in normal programming, so you don't necessarily have to do this. You can though, and it's often simpler to do so.


In my experience, more often than not, the opposite is happening. The designer wants the same widget to have a slightly different style in different places. Then you either give it some additional class for context or use helper classes. Benefits of either approach seem to be moot. Reusability suffers in any case.


I've found this is (usually) solved with soft skills. I just talk to the designer and explain we have all these very similar components already and it will help with the visual consistency if we follow an existing convention OR update the existing convention to use the new style (giving them the option to choose let's them stay in control of the design). They are usually very understanding as they don't always consider these things.


It's also rarely a surprise that if you ask "why did you special case this particular [button/widget]?" to some designers the answer turns out to be "I didn't have a good template and just redrew it" or "I don't know, I was just freehanding that because I was in the flow".


This stuff never scales. No one can remember the class names, no one want's to search through the examples and style guides for a project, no one want's to standardise naming of their own hacks etc and so you start of with good intentions and end up with a lot of duplication and a whole lot of shit.

CSS is an expressive markup. You shouldn't try to turn it into programming.


> This stuff never scales. No one can remember class names

Are you saying that with a CSS file with one-class-per-component it's easier to remember the hundreds if not thousands of class names, compared to a functional library, where you only have to remember a handful of them?

You might not like it, but the very reason of existence of functional CSS libraries is to limit the number of classes and improve reusability and composition.


Have you written a line of CSS, ever?!

Why would anyone restrict themselves to one class per component? Do you know that classes can be combined? Do you know how specificity works?

CSS fundamentally lends itself to being compositional. Suggesting that this isn't the case without added libraries is either ignorance or madness.


No, I'm saying anyone that tries to standardise CSS with a universal theory is wasting theirs and their companies time and resources.

This approach sucks and you end up with "gutter-left-10 skin-primary-blue gutter-bottom-20 row-single col-3 designer-lastminute-overridehack" which is just proxying CSS into class names and does not scale or transfer to anyone you bring onto a project.

BEM is equally awful because you're encoding structural data into the class name which again is just proxying CSS.


CSS never scales.

The point of turning it into programming is to make it scale. But all those frameworks are completely missing the point (what's the problem of web technologies? They seem to always miss the point, prioritize the non-solution, and complain loudly of anybody that complains about the actual problem). A framework can not solve the scaling problem because it's a language problem, and the preprocessors focus only on expanding things, when the specificity is a larger problem than DRY.


As a frontend developer of 15-20 years now I've been pretty dumbfounded and unconvinced by any arguments for this style of css, I think it's especially hard for frontend developers of such duration because this is effectively the first ever style of css you write, and then you were force fed xhtml, semantic web and then later responsive became the "Told you so!" of the methodology.

Despite my scepticism of extremes of semantic web, I realise now when I read articles talking about switching to this style of css, their problems are entirely unrelatable to me because I implicitly see the conceptual structure of a design vs its visual specifics.

This just feels like a new age of developers don't see the need for the abstraction and so it's a constant mental burden for them without any benefit.. I think what has propped this up is that some of the problems that semantic css has historically only ever been able to solve (such as responsive) are now being solved differently, either through more powerful css layouts that implicitly layout better responsively, or that they rely instead on javascript to switch classes/html/components out with media query listeners.

Ultimately I think whatever you decide should be based on what your team aligns to best, don't feel guilty about 'not getting' this pattern, but I think it's important you pick one way, as mixing these worlds just doesn't work (at a project level), but certainly you should always try new things for new projects or experiments.


I'm a frontend developer of about 15 years as well and I think functional css makes a lot of sense. My biggest argument for it is not having to name every thing. You know how many times I've had to think of a name for a random container that exists simply to align some crap? Then if you need another wrapper or something for that for some reason? It eliminates the name game (whenever you want it to).


> My biggest argument for it is not having to name every thing.

This x 100. As a guy who is the only American on a team with a bunch of non-native speakers, taking away naming responsibility is a big win.


this sounds like me. I spend more time looking at a thesaurus than I do CSS articles


Wow, this gets some real hate on HN. I highly recommend reading [0] instead (which is by the way linked in the main article).

If you're writing HTML by hand, then yes, it will be a PITA changing all those "bg-blue" Profile Cards using functional CSS (while it's just a single change when using .profile-card instead). In reality, it's not the functional CSS being the issue, but the markup duplication. If I extract a real reusable ProfileCard component, I can apply functional CSS to it exactly once. If the color changes, it's just a single place I need to look into.

There is no silver bullet. If you design web sites, try some templating language to extract your components. If you develop web apps, take any modern framework like React, which enforces using reusable components. If you still prefer writing HTML by hand, then yes, functional CSS is not for you.

[0] https://adamwathan.me/css-utility-classes-and-separation-of-...


It's a much better article, but really jumps the shark by the end, and the reasoning to convince become very unsound, like suggesting you'd only end up with ridiculous classes like 'image-card-with-a-full-width-section-and-a-split-section' .. but no I wouldn't.. I wouldn't ever put layout in a class name (full width), I'd call it the hero, priority or whatever it was semantically, which is a discussion with the ui/ux members of the team.

Composing utility classes via css (ala, what many have done for years since sass/less) is one thing, but then collapsing the component class all the way back to the html I really can only describe as jumping the shark, it's gone beyond logic.


> If I extract a real reusable ProfileCard component, I can apply functional CSS to it exactly once. If the color changes, it's just a single place I need to look into.

Then you're basically moving re-use from CSS to HTML templates. And if both exist only once, it shouldn't matter where you have to adjust that one line.


You're right. My main point was to separate your code by purpose instead of technology. That's where component-based development is heading to. If you're using components, then you're still free to choose one or another CSS aproach, but most functional CSS downsides don't apply anymore.

My team in fact combines both approaches. I don't need to define a CSS component just to add some margin, but I am also free not to use 15 functional classes to clutter the HTML.


I don't understand why I'd use functional CSS over inline styles. With inline styles I have editor auto-complete, no confusion as to whether it "pt-10" or "pt-15" even exists.

I make pretty heavy use of cascades and don't put classes on every single HTML tag and try and keep my HTML as semantic as possible even though I actually do have components for every button. I will put an inline style of something if that is the most logical approach but proper semantic classes allow me to work at a higher level than individual styles.


For me, it's about atomic design. I want to use predefined, reusable values only. So I'm only able to use "pt-10" for 10px and "pt-20" for 20px (as an example). With inline styles, nothing prevents me from using "padding-bottom: 11px" (which may not be defined in the style guide).

Also, from the article:

- Inline styles don't respect media queries, which basically rules out responsive design

- Inline styles aren't limited to pre-defined options, meaning you can still end up with 90 different shades of blue)

- Inline styles cause specificity issues, since they trump separate stylesheets.

- Inline styles don't support print-specific styles.

- Inline styles can't address pseudo-elements (such as ::before and ::after)

- Inline styles can't apply to multiple elements. Utility classes can define .bg-blue once and have it apply to many things, which leads to shorter markup and quicker rendering speed.

- Inline styles are a pain to type. Compare class="f-sm bg-blue" to style="font-size: 10px; background-color: #0000ff;".


> For me, it's about atomic design. I want to use predefined, reusable values only. So I'm only able to use "pt-10" for 10px and "pt-20" for 20px (as an example).

I would call these "padding-small" or "padding-big" in that case. Of course, a better way would probably be to abstract that even further in actual purpose rather than style.

> Inline styles don't respect media queries, which basically rules out responsive design

I question how you could have style-like-classes like pt-10 and be responsive at the same time. So this style is padding-top: 10px as it's name suggests except on mobile. That makes no sense.

> Inline styles aren't limited to pre-defined options, meaning you can still end up with 90 different shades of blue)

That's fine. Although why limit yourself to calling the class "blue" when you could call it "brand-color" and actually be able to change it something other than blue in the future.

> Inline styles cause specificity issues, since they trump separate stylesheets.

I don't think you want your "pt-10" style to be "trumped" by another style otherwise that would be confusing. So again this is not an advantage to this style.

> Inline styles don't support print-specific styles.

Again, it would be confusing if "pt-10" suddenly didn't apply when printed.

> Inline styles can't apply to multiple elements. Utility classes can define .bg-blue once and have it apply to many things, which leads to shorter markup and quicker rendering speed.

So the advantage is you get to type 5-10 fewer characters per element you apply it to?

> Inline styles are a pain to type. Compare class="f-sm bg-blue" to style="font-size: 10px; background-color: #0000ff;".

Only if you know all the classes that actually exist for the particular project you are working on. Does f-md exist? Is really "fd-small" in this project? My editor will autocomplete inline styles so they might actually be easier to type.


>> For me, it's about atomic design. I want to use predefined, reusable values only. So I'm only able to use "pt-10" for 10px and "pt-20" for 20px (as an example).

>I would call these "padding-small" or "padding-big" in that case. Of course, a better way would probably be to abstract that even further in actual purpose rather than style.

This is perfectly fine. Functional CSS does not enforce any naming. In Bootstrap it's just "p-1" through "p-5". But I would rather go with more semantic names, too.

>> Inline styles don't respect media queries, which basically rules out responsive design

>I question how you could have style-like-classes like pt-10 and be responsive at the same time. So this style is padding-top: 10px as it's name suggests except on mobile. That makes no sense.

Following your example, you can have "padding-small" with different paddings on Desktop and Mobile. Which is not possible using inline styles. For Bootstrap you get media query suffixes for many classes. One common usage is "d-flex flex-column flex-md-row", which makes an element "flex", with column direction on mobile and row direction on desktop. Handy for simple use cases like that.

>> Inline styles aren't limited to pre-defined options, meaning you can still end up with 90 different shades of blue)

>That's fine. Although why limit yourself to calling the class "blue" when you could call it "brand-color" and actually be able to change it something other than blue in the future.

Again, I think you're mistaking a single Functional CSS implementation (like the one used by the author) with the concept itself. You are not forced to use color names and numbers in your functional CSS class names. And I fully agree that semantic naming is way better.

>> Inline styles cause specificity issues, since they trump separate stylesheets.

>I don't think you want your "pt-10" style to be "trumped" by another style otherwise that would be confusing. So again this is not an advantage to this style.

What the author means: using only functional classes, you know exactly that your "pt-10" padding is not overwritten (unless you use another "pt" class by mistake). With "traditional" classes, you can't be sure of that. And more often than not you will get problems with the cascade, especially in bigger projects with many developers. That's where all the "!important" hacks are coming from.

>> Inline styles don't support print-specific styles.

>Again, it would be confusing if "pt-10" suddenly didn't apply when printed.

You can do much more with CSS than adding padding ;) Hiding elements for print is the main use case here. You can't achieve this with inline styles only. A "print-hidden" utility class can do that.

>> Inline styles can't apply to multiple elements. Utility classes can define .bg-blue once and have it apply to many things, which leads to shorter markup and quicker rendering speed.

>So the advantage is you get to type 5-10 fewer characters per element you apply it to?

No, the advantage is that you can use only pre-defined, reusable, atomic definitions. If the style guide says there are only 2 types of padding ("padding-small" and "padding-big"), you won't be able to set another padding using functional CSS only. With inline styles, you can do whatever you want. This also applies to raw CSS stylesheets. That's why pre-processors are so valuable - you can define your SASS/LESS/whatever variables and achieve the same effect. And before you ask: "then why do I need functional CSS in the first place?" - it's because of the other advantages, like not having to use a pre-processor or defining/importing a stylesheet in the first place.

>> Inline styles are a pain to type. Compare class="f-sm bg-blue" to style="font-size: 10px; background-color: #0000ff;".

> Only if you know all the classes that actually exist for the particular project you are working on. Does f-md exist? Is really "fd-small" in this project? My editor will autocomplete inline styles so they might actually be easier to type.

If you don't know all the classes, then you need to know all the style guide values. Otherwise, how do you implement a consistent-looking design? Take our "only 2 padding values defined" example. You will have to look stuff up, be it functional class names, traditional class names, SASS variables or simply the values to be used. Also, my editor will autocomplete functional CSS classes, too.


> I think you're mistaking a single Functional CSS implementation (like the one used by the author) with the concept itself.

Honestly at some point what you describe I would just describe as normal CSS.

Functional CSS is classes based on their visual function rather than an abstract concept. This the definition. But the more semantic your names are the less they related to an actual visual function.

If on mobile you don't apply any padding then your padding CSS class is a lie. And if you don't call it "padding" in some way then it's not Functional CSS. I also think conceptually having a few utility classes like "print-visible" or "print-invisible" is not really applying Functional CSS as an overall concept.


What about theming/branding so that you can make your enterprise web-app fit in with each of your clients other web-apps?

If your class names are semantic like profile-card it's easy to have a branding css file for each client.

If your class names are functional like m-5 p-5 text-gray-light bg-gray-darker border border-gray-light you're going to... what? make code changes for each client?

Obviously if the website is only going to have one branding, this isn't an issue, but advice like "use semantic css" or "use functional css" needs to be put in context. What you do in an agency context for content sites would be different from an in-house web-app context, or a web-app for SAAS context.


Even if you only have one client - do you really want to manually hunt down all profile-card instances and update the styling anytime you need to change the styling?

And if you had a bug related to profile-card styling, are you going to find all cards to update the styling? Are you sure you didn't forget some?

This approach seems to be based on the idea that design is completely immutable after the initial conception. This is... not how design usually works :)


It's unclear to me the problem you are addressing. Searching for places to make amendments is an important consideration when naming something. I would have thought that class names like "profile-card" would be easier to search for than "m-5 p-5 text-gray-light bg-gray-darker border border-gray-light". Especially if you have some page elements which may look the same now but are functionally different and could look different in the future. How would you find one and not the other?

Is that the problem you were addressing or did you have something different in mind?


I was commenting on the original proposal, even in the single-client context. So, we're talking about the same problem - I just obviously wasn't very clear about it :)

So, yes, semantic names matter, and functional names are a bad idea in the long run, because they shatter maintainability.


It's all about tradeoffs, there are no silver bullets. If your class name is like profile-card then it could be simpler... until it's not. Because it turns out that one of your client profile-card needs to behave slightly differently on hover or whatever. In theory, profile-card is a great idea, in practice it can be a headache


What I'm saying is you have files client-alice.css and client-bob.css, and you define different profile-card:hover rules in each. But with functional css you have nothing to hang your rules on.


It's never not simpler.


You can use `text-primary` or `text-secondary`. Sure it's less obvious looking at the markup what something looks like but it allows for theming.


I usually don't want people to be able to create infinite variations of things because of a lack of consistency.

I like defining a few concrete component styles BEM style and having it easy to re-use them and other people not abuse them too much. After the initial components are defined I don't want to think about what border or colours are involved I just want to drop profile-cards in various places. It feels like this "functional" approach doesn't solve enough real-world use cases (that I have experienced at least) to justify using it.


> It feels like this "functional" approach doesn't solve enough real-world use cases (that I have experienced at least) to justify using it.

I suggest reading:

https://hackernoon.com/full-re-write-with-tachyons-and-funct...


We did this at my last job, but inevitably ended up with a mix of half functional CSS and half component CSS.

If you have lots of repeated components on a page (comments, thumbnails, tags) then it's difficult to defend repeating, potentially dozens, of the same declarations. You're better off with the component defined in a stylesheet.

I think the real use for functional CSS is for one-off adjustments on those components:

  <div class="comment">..</div>
  <div class="comment">..</div>
  <div class="comment disabled">..</div>
It's also a pain to edit all of the instances of an object when you want to update styles consistently. One upside, though, is that you have to consider the impact of the change in each spot.


> If you have lots of repeated components on a page (comments, thumbnails, tags) then it's difficult to defend repeating, potentially dozens, of the same declarations.

That's where you have two choices:

1. Use your HTML templating language to define a dynamic variable representing the set of classes and use that.

2. Like the article says, make use of the functional CSS's tools to create a new class that includes the styles you use. Same idea to #1, just at a different stage.


Both "solutions" don't address the problem of repeated class names, they just help repeating them in a correct but not less obscene way. Bloated markup cannot be defended.


Yes they do, at least in a way that's no worse than every other CSS toolkit in widespread use.

And there's nothing "correct" or "incorrect" about it. I suggest reading [1] if you want some real data on the usefulness of functional CSS.

[1] https://hackernoon.com/full-re-write-with-tachyons-and-funct...


I mean "correct" in the formal sense that every element gets the intended style, which is possible even with bad design and bad technology.


I've used BEM, atomic design and functional CSS. I actually like some kind of combination of all three. This is my 2c:

The pros of functional CSS as a replacement for CSS/SASS variables:

- You define your 'palette' up front: which margins, font sizes, colors are acceptable, etc. You could do something similar with CSS/SASS variables, but you'd give up the capability to rapidly prototype on any machine with any browser and you'd need HMR set up everywhere. Also since it's a class you can (de)compose it with other classes and build up 'abstractions'. So I'm really using functional CSS as a better replacement for SASS variables.

- It's easiest to start hacking away at designing widgets without worrying about things looking inconsistent eventually, because you're working with a limited palette

And then what I take out of atomic CSS is splitting up the code into different levels. Instead of atoms, molecules, organisms, I have: palette, abstractions, components. Abstractions are composed of other abstractions and/or things from the palette. Ie: an abstracted class might be like: .center-vertical, .center-horizontal, and then composing those would give the .center class. Components are concrete widgets like buttons, popovers, modals, tables, lists, etc.

And I use the submodule idea from BEM. So if I need to create custom themes, it would be the like .button .button-(theme name) and writing the theme works just like inheritance would here but I'd be using composition instead


Why does it seem like no one knows anything about CSS? BEM, "Functional" CSS, all this nonsense simply because nobody know about the child selector as opposed to the "any descendant" selector. (Maybe because it wasn't supported in IE6 and we're still reeling from that to this day...)

Take ten minutes and learn. Here's some tips:

Attribute selector:

  button[disabled]
    background-color: gray
Modifiers are just classes, never have disconnected .some-classes floating around. Keep them scoped to their element :

  button.large, a.button.large
    font-size: 2rem
Child selector:

  profile-card > h2
    font-size: 1rem
    margin: 0
Everyone forgets to put in the alligator and then complains that their ridiculously nested markup gets out of control. This way a card can contain _anything_ and not have to worry about stomping its styles.

Semantic elements:

  profile-card
    display: block

  profile-card.active
    background-color: green
You don't need to be limited by span/div-itis. It's 2018 go wild.

Pro-tip:tm: try learning CSS before creating or adopting a CSS "framework" to solve problems that CSS already solves.

Hope this brief rant saves a life or two. Hang in there people.


Applying CSS using utility classes it just a different way to abuse HTML for the purpose of inline styling.

- How do you set a class for states like hover, focus, active, hidden, checked, etc

- How to you use/create/style pseudo-elements?

- How do you add responsive control (like CSS media queries)?

'Functional CSS' is like sitting down at a full piano keyboard and trying to bang out a tune by only hitting one key - there's a LOT more range possible in CSS, and it's only difficult mostly because we MAKE it difficult by ignoring this.

The only/best 'functional' CSS tooling I would even look at these days is http://css-blocks.com from the people who made Sass, it's a much more modern approach and you end up with highly optimized code, HOWEVER you write human-readable CSS stylesheets and you let the CSS-Blocks compiler and Opticss optimizer output the 'functional css' you need.

Let humans do what humans are best at (writing nice stylesheets) and computers do what computers are best at (compiling things). It will outperform and human pretending to be a compiler, and with better accuracy.


This is how you can do all of that:

  class="hover:red" -> .hover\:red:hover { color: red }

  class="before:red" -> .before\:red::before { color: red }

  class="medium:red" -> @media (min-width: 500px) { .medium\:red { color: red }
The important thing though is it doesn't need to be used for everything. I think it makes a lot of sense for structural stuff. When you dig into like, children of a hovered element I can see it getting a little messy.


How come people who do this only ever use class names? Why not invent your own data attribute like data-hover="red" where you create new namespaces for things like hover, or pseudo classes, why it it always only ever class names?


Totally talking without thinking about it too much here:

The classList API makes modifications to the class property very easily.

You'd be essentially limited to one identifier in attribute selectors. You can't really select from multiple identifiers with a data attribute without doing like:

  [data-hover*="foo"]
which would search for "foo" anywhere in the attribute, which could mean incorrect substring matches.

Chaining attribute selectors would be rough too:

  [data-hover*="foo"][data-hover*="bar"] {}
vs

  .foo.bar {}


> The classList API makes modifications to the class property very easily.

So does the dataset interface for custom data attributes: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement...

> You'd be essentially limited to one identifier in attribute selectors. You can't really select from multiple identifiers with a data attribute…

That's just not true, there's an attribute selector that targets strings in a whitespace separated list: [attr~=value], so you could think of .demo as being a shorthand for [class~="demo"], or #demo as a shorthand for [id="demo"].

  [data-hover~=foo][data-hover~=bar] {}
would target a tag like this:

    <div data-hover="foo bar"></div>
But not a tag like this:

    <div data-hover="foobar"></div>
More info about attribute selectors: https://drafts.csswg.org/selectors-4/#attribute-representati...


I wasn’t aware of the tilde attribute selector. Still a lot more characters, though.

The classList api is still a lot more suited for this than dataset. None of the modifications done through the dataset api would reflect in the DOM and be readable by CSS unless you were to convert the list to a space separated string and explicitly set the attribute. classList handles all of this for you.


> None of the modifications done through the dataset api would reflect in the DOM and be readable by CSS unless you were to convert the list to a space separated string and explicitly set the attribute.

I'm really not sure what you mean by this. If you set the data attribute any of these ways, it can be targeted in CSS with [data-demo="example"]:

    el.dataset.demo = 'example'
    el.dataset['demo'] = 'example'
    el.setAttribute('demo', 'example')
CSS doesn't require a space separated anything. When you use an attribute selector in CSS it treats the entire value as a string, spaces included. But it's not classes versus attribute selectors, as class is an attribute, and therefore also something you can select with attribute selectors.

Also, think about the asymmetry between CSS and HTML when considering saving characters, one CSS selector targets ∞ tags, so I'd rather write slightly longer selector one time, than need to use a much longer 'namespaced' value on each element where I want the style to apply. That's leveraging what CSS does best!


I'm just saying if you want to target something on an element it needs to be set in an attribute and classList takes care of this.

I use classes strictly for styling. I change these styles by adding and removing class names and classList handles it very well without me needing to read the data attribute, make it an array, manipulate it, join it and update the attribute.


I feel like you're still thinking small in terms of attributes, and big in terms of values. Many many values all crammed into one attribute (class), but the reality is you can invent infinite (∞) data attributes. There's literally no need for you to format the values as a list of space-separated values…unless you want to. But if you don't want to, there's no need. Consider this, instead of targeting something with classes like this .active.demo, and setting it like this

    el.classList.add('active')
    el.classList.add('demo')
You would NOT need to do something like this to use data attributes, [data-example~=active][data-example~=demo] and to set it like this:

    if (!el.dataset.example.split(' ').includes('demo')) {
      el.dataset.example += ' demo'
    }
You could instead easily set two attributes and test for their presence, even if they don't have values (or you're not using them)

    el.dataset.active = el.dataset.demo = true
And then you can target that in CSS with [data-active][data-demo]. To remove them later is just as simple:

    el.dataset.active = false
And it's gone! Try to think BIG in terms of attributes, and small in terms of values. It's a lot nicer than trying to cram all of your values into just one attribute when you literally have infinite attributes available to work with!

Not only do you have infinite attributes to work with, but you can

Using classes as your only way to target styles, and ignoring the other aspects of how CSS selectors can target elements is like picking up a guitar and trying to play a song, but only plucking one string. You might be making it harder on yourself to get the job done, and the result isn't any better for the effort.

EDIT: Just for kicks, have you ever considered the flexibility of what data types you can set as an attribute value other than a space separated list of strings? Try this:

    // set JSON to attribute value
    document.documentElement.dataset.example = JSON.stringify({one: 1, two: 2})

    // get JSON from attribute value
    JSON.parse(document.documentElement.dataset.example)
You can even stick a bit of JSON there as the attribute value, which can be parse/stringified by JS, is _easy_ to add or remove properties from and work with on the JS side (not requiring helper methods like classList), and is _still_ targetable by CSS once set on an element :D The possibilities are endless, the apparent limitations a lot of people butt up against are self-imposed.


I'm sorry I'm just not seeing the value in it. I'm just seeing more complexity JS and CSS wise without solving any problems.


I'd call this style "compositional" rather than "functional". You're composing an element's style from smaller chunks.

My main problem with this is that some people like working that way and some people don't. This leads to a mish-mash where you have two completely different places to look for where your styling might be. Since you can't specify all of your styles in this fashion, then in order for there to be one spot where the styles live, putting them in CSS files with semantic classes is the sensible default.

My other problem with it is that it encourages many DOM elements with one style each as opposed to fewer elements with more style rules. I feel like I'm swimming whenever I'm looking through the markup with an inspector.

More ideally what I'd like to see is styled-components, so the entirety of a component lives all in one code file. I don't particularly care for the use of javascript to specify literally everything on the page, from the markup to behavior to styling, but the siren song of having everything there in one place makes up for it. If you want terseness in style definition, which is the main problem this "functional" approach solves, then you can simply invoke short javascript functions.

My ideal approach though actually would lean on a text editor / IDE to keep a list of components, and opening up the markup, styling, and scripting of a component all at the same time, and just using HTML templates, SCSS, and vanilla Javascript, keeping each file unsullied by the syntax and semantics of the other languages.

I'm unconvinced that everything really needs to be Javascript, but I don't mind wandering down that rabbit hole with everybody else until the React fascination passes. It's not the worst way in the world to specify UI.


As usual maybe it is wiser to take the good parts from different approaches, rather than going "all in" with one ideology / methodology.

For my sites I find it useful to have a small collection of very generic classes. One common case that was annoying is how the spacing keeps changing as you move text and components around a page, and you end up fiddling with the rules all the time to adjust for how the top/bottom margins merge. No matter how "logical" it is, from a graphic design pt of view, the spacing is right when it looks right.

So I have a few very generic classes like this:

    .mb-0   { margin-bottom:0; }
    .mb-1   { margin-bottom:1em; }
    .mb-2   { margin-bottom:2em; }

     /* text */
    .txt-lg { font-size:1.4em; }
    .ta-r   { text-align:right; }
    .ws-nw  { white-space:nowrap; }
These are useful for making small adjutments to the layout. That said, going all in with atomic css doesn't make sense to me.


I do the same. I have a scss file with a few margin and padding mixins that I can throw into the dom when I need to. Otherwise, I'll stick with updating all my buttons at once in my css `button` class.


This ridic argument boils down to code reuse and components.

The whole reason for css is to facilitate style reuse when writing markup. In normal html pages you write a bunch of markup, chunks of that markup might represent the same "component" and so css is a great way to style those similarly using semantic class names.

If you use small components that exist in some type of template (react, vue, etc...) you can take advantage of that to facilitate your code reuse instead of a "semantic-component" css class. I think that is where utilities become valid because you still only change a components styles in one place.


Why is this named "functional" CSS?

Something like "const FIVE = 5" doesn't seem to capture the essence of functional programming either?


Maybe it's not a reference to functional programming but to that other definition of "function", you know, the one used by everybody except programmers.


I actually initially thought it was a reference to http://functionalcss.com/ where you use CSS in place of JavaScript.


function - purpose, task, use, role, ...


Have you ever really looked at a thing with class="profile-card" and said "oh this is a profile card", when it wouldn't have been just as easy to tell that based on the context or what it contains?

Wait, what? Who hasn't done this?


Oh God. Please don't let this be a thing. I hate to be negative but this is a bad direction for a set of technologies (HTML/CSS/JS) that have already veered heavily down a miserable path.


This thread is why I love HackerNews. I'm in the middle of considering something like this w/ Tailwinds and share some of the concerns expressed in some comments here, but I'm still keeping an open mind.

Is there anyone who's tried it for a project and still hated it? Seems like a lot of the detractors haven't actually used it yet.


I used this technique in my previous startup. I even had shell scripts that generated my LESS files.

One of the driving philosophies was that when one saw a CSS class, they should easily be able to find it's definition in the source. Another driving philosophy was that one should easily be able to determine what the class is doing.

This lead to classes like `u-centered`. The `u` tells me it's in the utils.less file. Classes starting with `l-` were layout classes, `t-` text classes, etc..

I had classes like this:

u-{max,min}-width-{xxs,xs,s,m,l,xl,xxl}

t-white

u-bg-red (red background)

t-h3

l-container-{xxs,xs,s,m,l,xl,xxl}

You get the picture.

(The nice thing about xl and xs is that you can keep adding x's as you need.)

I found it to be very effective. I understand the arguments that it kind of defeats the purpose of CSS, but I think CSS is pretty easy to mess up, and this give you a solid, consistent structure to work with.

Of course, I didn't follow this style 100%. There were some cases where it just made sense to use a more semantic style, but I found those case to be few and far between.


Seems like a waste of time when you can just do style="background: red;". You're not adding anything to CSS you're just renaming and enumerating all the style attributes and values.

I think it makes sense in small doses but I think once you're using shell scripts to generate all these combinations you've lost the plot.


There's a big difference between class="u-bg-red" and style="background: red;". The big difference being that the class make it so that it is first-class application idea.

And I think that may be one of the larger points here. CSS can be simple, and using techniques like this forces it to stay that way. You have to take a step back and understand what we're trying to do as engineers. I would argue that being able to quickly understand code (e.g. the context to understand a line of code is small) should be a top priority of most software project.


"u-bg-red" vs. "backround:red" is just the same thing aliased. If you were to introduce an actual concept like "warning" or "error" that was red that would be different.


You are correct from one point of view. But, the point I was making was that the class definitions for bg color can be contained within a single file in your application. Using `style` is completely different in that anything is possible. This is a big deal, as cutting down on possibilities/simplifying is a very important process in software engineering.


> But, the point I was making was that the class definitions for bg color can be contained within a single file in your application.

But that doesn't matter because it's not an abstraction. If you have 10 HTML files and 1 CSS file, you can make a class called "warning" and have it be a background color red you've simplified those HTML files because you have less style information in the HTML.

But if you are using classes like "bg-red" or "pt-10" then you're not actually reducing the style content of your 10 HTML files. You've just renamed a style to a class. Sure you've reduced some possibilities but you've actually made the situation worse because now you have 11 files with style information. You've added new names for basic styles which adds even more complexity.

If you take that idea of reducing style possibilities to the logic extreme then you wouldn't be using classes like "bg-red" and "pt-10" anyway. You'd just do what everyone already does with CSS and abstract your styles appropriately.


My experience with functional CSS was skepticism followed by delight. Reading BEM style actually makes me more skeptical now. A class of "Button Button__Primary" tells me much less about the styles of that button than a string of functional CSS classes would.


Which is why you have a styleguide. Open your browser, open your well crafted styleguide. Here is what our "Button" looks like, here is it again when its got "Button_Primary" on it. Do you need a new type of Button? Author it in the styleguide... now go use it everywhere and be happy. I might be wrong, but in my experience a separation of concerns is the only way a large project stays healthy.


When the customer asks me to change the background of primary buttons from green to yellow and the background of nonprimary buttons to red, while changing other green backgrounds to a green-brown gradient, classes like "Button Button__Primary" tell me much more than classes like "bg-green".


Your customers speak a different language than most of mine. The requests are more like "I need the green buttons to be yellow now!" It's easy to find bg-green on buttons and just find/replace with bg-yellow.

Also, using Tailwind/functional CSS for items that are repeated over and over on your site like buttons, you can easily extract them to a component. Switching from bg-green to bg-yellow would be as simple as opening your SASS/LESS file for components or button components and replacing it in that one spot.


> It's easy to find bg-green on buttons and just find/replace with bg-yellow.

Oh, that's because running sed over all your project files, all in a set of weak typed languages is easier than changing a definition in a single place. I totally get it.


Sure it does. It tells you that it looks like a Button, with some primary variation styles.


Which is useful, but that's the extent of the depth of information I'm getting. I like that functional CSS lets me see "how something is" over "what something is."


Isn't this the same as regular programming? When you have a function called updateUser(), that doesn't tell you every single thing about its implementation, nor do we expect it to.


It's not supposed to tell you what it looks like. Why is it a goal to be able to tell exactly what something looks like from reading the markup?


You shouldn't need to know what the exact visual style of the button is. That's not important. You have a button, it's the primary button. What else do you need to know when coding your HTML?


Everything old is new again (sort of). There was a similar paradigm being promoted several years back that was dubbed "Object-Oriented CSS (OOCSS)": https://www.smashingmagazine.com/2011/12/an-introduction-to-...

It's a little unfortunate that the use of the terms "functional" and "object-oriented" were chosen in these cases as they can easily be confused with functional vs. OO programming, when in reality CSS or any paradigm of writing CSS has nothing to do with this distinction.


This was my first thought too.

There's nothing novel here. There's just a misunderstanding of how CSS works, an over-engineered solution to a non-existent problem, and then a misused name added for a veneer of sophistication.


Neat.

Now add a way to hierarchically roll-up these micro-classes into semantic classes behind the scenes (Perhaps in webkit?). Compile things so you only carry-around the css micro-classes you've used, and make a flag to either deploy using the semantic or micro class method.

Best of both worlds. There are also some other mix-and-match ways of doing this. Where the real value is separating the tiny CSS adjustments you make from the business-class stuff, creating a middle tier (which this guy deploys directly)

It might make things easier. Or it could be yet another dumpster fire. I think it depends on how it's used.


You could do this with SASS or LESS.

Make all the "functional" classes as abstract mixins or placeholder selectors (in SASS parlance), and then use them to define your concrete semantic classes.


variables and mixins, clean css, readable templates instead of some overloaded hodgepodge of classes.


Yeah. I was reading this thinking "If only we had some way of abstractly creating CSS!"

Which of course we already do. Maybe there's a case that the toolchain or conventions need tweaking. So it's worth the discussion in my mind. Most times you really don't realize what you need from a tool/framework until you've reinvented it, so we need folks like this doing sanity checks on where the rest of the industry is going.


Functional CSS changes a mistaken way of thinking about CSS classes: as a unit of visual abstraction.

When you have a "ProfileCard" class, you expect it to encapsulate the profile card without leaks, and with perfection. But that is never the case - there are so many variations of profile cards that almost everyone who uses "semantic" CSS (BEM, SMACSS etc.) end up with hundreds of tiny variation of this class, each one of them scoped to their particular container or page. Not to mention the proliferation of different shades of the same color, inconsistent typography, and ad-hoc spacings.

The right level of abstraction for user interface is the DOM+CSS; neither of them stand alone. This idea "separation of concern" has taught us to think of them in separation, and feel guilty everytime we have messy CSS that breaks that idea. But it is the idea that is wrong.

The right level of abstraction is the "component". eg: in a React component library you might have multiple Buttons, each of which is a highly reusable non-leaky abstraction. Here Functional CSS abstracts a lower granularity: design tokens/scales. It will give you consistent spacings, colors, and typography. These two in tandem is a fantastic way to look at building UIs that are consistent, reusable, and extremely easy to write and maintain.


I really hate this style.

I think the solution is using elements/components as the means of sharing styles. If you need a slightly different style you extend and modify an existing component. This can be achieved using libraries like `styled-jsx`, `styled-components`. Or hopefully as the shadow-dom spec progresses this will take care of this issue. I also think doing a way with the `scoped` attribute on the style tag was a dumb idea. As it made compartmentalization way easier.


First of all I love reading arguments about CSS architecture like this, since even for me doing CSS 19 years now I still haven’t found a „goldstandard“ - and I think he makes good points.

However, I would be more inclined to use his utility classes as one layer in an ITCSS architecture and then have component styles that inherit from them, keeping them away from the markup as much as possible, while allowing to use those utility classes in the markup for quick prototyping.


> Also, if you find yourself in a situation where you're using the exact same classes in a bunch of different places, that's probably a DRY problem with repeated markup, and you should likely consider abstracting that into a reusable fragment or template so that you can define it in one place and just include it wherever you need it.

This pretty much resolved my objections towards this approach. I think it makes a lot of sense with react.


Another interesting CSS framework taking this approach: UniversalCSS: https://github.com/marmelab/universal.css

A few advantages: self-documented classnames, zero dependencies, classnames are reusable across projects, removes the need for a CSS preprocessor or bundler, no need to switch between HTML and CSS file while developing, etc...


This is all really terrible advice and my only conclusion is that you have never actually had to maintain websites that use this approach toward CSS as they grow past being a little one off blog into a large, customer facing, PWA.

With this method of CSS it will take years to consolidate, update and redesign your application. Ask me how I know. :-)


In the old days, I was doing CSS by hand for every site I made. It kind of sucked.

Then Bootstrap came out, and the idea of CSS frameworks was a thing. I loved Bootstrap, but so did a lot of other people, and as a result you started seeing Bootstrap everywhere...like when you buy a car and you start seeing everyone else driving one where ever you go.

So I started trying to customize Bootstrap to make it look less like other bootstrap sites by adding custom CSS, which basically brought me back to where I started.

In practice it has been much, MUCH easier to work with CSS frameworks that use utility classes, because it makes customization easier. I do think there needs to be an intermediate layer where it's easy to define semantic classes as composites of utility classes. I would think this should be possible in the days of Less, Sass, and precompiled web sites.


I tried using Tachyons for a project and it really broke down when I needed to make really custom components.

For instance, one component was a cropping viewport that had to be a set height and width. There really isn't any solution for that other than adding a very specific utility class, or creating a semantic class.


I think the point is that Tachyons should be good for 90/95% of the styling you want to apply to the site. I think the creator would be the first to say that if you need something specific which Tachyons can't do you should do that but it doesn't make Tachyons redundant.

Personally, Tachyons still provides me tremendous value even though I sometimes have to write custom classes. I'm also often surprised to find that something that I thought would need a custom class, could be done with Tachyons when I dug a bit deeper.


We did this for a project a few years ago and it was alright. In the end we decided against doing it again purely because the DOM became so extreme with one-rule classes that it became a nightmare to read the templates. So much noise.

For building things out and prototyping it was amazing though.

On the plus side our css file was so tiny.


Most of the "a lot to love" points are also hit by BEM/SMACSS. In regard to this point:

>You never have to deal with one instance of a thing needing a slightly different style than the other instances, which screws up your reusable classes.

...what I found was that just as often, I'd need a new Atomic class different in a subtle way from existing ones, and this was annoying to implement because

a) it expands the kludge-dictionary of short class names you have to memorize, but often in a way that's too situational for anyone to actually memorize it, meaning the next time someone runs into the same problem they will re-invent the same solution rather than reread the entire list of Atomic classes to see if one exists, and

b) the whole point of Atomic is that I shouldn't have to be writing CSS, and I was, all the time.


Tailwind takes care of this. You just need to define your spacings, colors, typography, and a few other details like borders and shadows, and all the classes you'll need are all there. You can use PurgeCSS to trim down the final CSS size to just the classes you use.


I agree somewhat for web pages, but this looks like a maintenance disaster for a web app of any significant size. I will probably turn down any offer to work on a team with a large project that uses this approach, unless fixing it would be part of my job.

For web apps, I contend that modularity ought to be the goal for HTML, JS, and CSS. In the project I'm working on now, each widget/component has its HTML, JS, and CSS together in a single folder. When a widget/component is first loaded, its CSS is added to the DOM. Each component has a unique parent class name, and all its markup and styles are nested under it.

Having cross-cutting styles that are re-used throughout the app sounds decidedly un-modular. Why not re-use components/widgets instead?


More fundamentally speaking, I'm wondering what the intrinsic value of CSS is when you compare the work involved in building a UI in web-land and native-land.

I remember once looking up on the proposed alternatives to CSS. One was basically a lisp, or at least the syntax, as far as I recall it. Think of what you could do with that!

However the problem now is that the problem CSS intended to solve can only be considered in terms of CSS itself. I'm curious what other approaches could be taken if we worked entirely from a clean slate. Would it involve changing the DOM? Would it require a separate language? Who knows...

CSS works great for websites but not so much for full-blown apps, where you're programming with a totally different mindset than what the web originally anticipated.


Problem is, defining quantity in the class name doesn’t work.

.m10 may be fine for desktop but not for mobile.

Then you’ll have media queries which define .m10 as margin: 5px or something, which is nuts.

You could go for unspecified .mSmall etc, but in real life, things tend to be more specific and messier, in my experience.


In bootstrap 4 you get responsive variants like .m-sm-1 and .m-lg-1. Then you can have class="m-3 m-sm-1" to have different margins for mobile and desktop.


> I think that separation of concerns (i.e., the whole idea that the markup should be completely independent from the styling) is something that has been burned into our brains because of the history of CSS (trying to get people away from using tables, sites like CSS Zen Garden, etc.)

CSS has come a long way since CSS Zen Garden.

With CSS grid and flex, you can create components with less markup and small amounts of CSS.

The example on the tailwind site https://tailwindcss.com/docs/what-is-tailwind/ just looks like a steep learning curve to me. I could write that same component with much less HTML and just a few lines of responsive css.


I believe this type of CSS works well in projects with no real concept or design - I call it wild-west front-end where you design as you go ending up with no patterns and real identity.

If it's popeprly designed functional CSS would be exaclty what it actually looks like - garbage.


Can't you do the same with SCSS and at least keep the DOM clean and have it nest more naturally?

Like include "materialShadow(3)" for a hovering button, but when you want to build a special card thingy you include "card", which than includes the shadow already.


Using sketch / photoshop these days gives you "Copy CSS Attributes" functionality for most of the elements, which is basically 50% of your CSS, the rest is layouts ( super easy these days with flex box / grid ), media queries and probably some more.

I agree that Cascading part of the CSS is very troubling, but I don't think functional CSS solves it in an elegant way. Actually I think it's hardly readable and confusing :(

As of the argument that you don't need to write CSS properties anymore, I would suggest using a plugin like Emmet [1].

(1): https://docs.emmet.io/css-abbreviations/


I don’t get why people are still defending this method of CSS. When - or, perhaps I should say 'if' - your webapp has to scale you will realize the enormous amount of problems you’ve created for yourself using this method of CSS.


I'm not particularly good at identifying satire, but this is a joke, right?

I mean, the ONE BEST THING about CSS is its ability to promote consistent styling across a site by creating REUSABLE, NAMED styles that are SEMANTIC and applying them consistently.

Let us run through the author's claimed list of advantages:

> You don't have to write any CSS of your own (which, to me, is fantastic)

This one is an obvious troll.

> You can likely build things faster (obviously non-scientific, but anecdotally I've seen many people confirm this)

The combination of "likely" and "obviously non-scientific" undermines this claim (and rightly so) in the middle of making it.

> You don't ever have to think about naming things

Again, I presume this is a troll. Naming things is hard if you care about having meaningful names. If you don't care, then naming is trivial. This approach eliminates meaningful names so it is hardly a benefit.

> You can tell what something looks like by just reading the markup for it

That one is an actual advantage, and makes me wonder slightly what's going on.

> You don't ever have to worry that changing the styles for one thing will break something else (which may make visual regression testing irrelevant)

Another obvious troll. If you never reuse anything, you'll never have to worry about a change breaking anything else. Also true if you never change anything. Also completely meaningless.

> You never have to deal with one instance of a thing needing a slightly different style than the other instances, which screws up your reusable classes.

True enough... if you never reuse anything, then you never need to worry about the impacts of reuse.

> Your CSS always stays the same size rather than expanding over time

Well, sure! If you move all of the intent out of the CSS file and into longer and more complex style attributes, then the CSS file itself will get shorter (while the length of the CSS file PLUS the style attributes will get longer).

> It's easy to un-apply a style by just removing the class (as opposed to the traditional cascade where you typically have to override, adding even more CSS)

This isn't even well-considered. Using a fixed set of single-visual-effect-not-semantic-intent styles will have no effect on the complexity of cascading. Choosing to apply styles only to individual elements and eschew the use of cascading WILL avoid all the complexity of cascading, but the choice to do that is independent.

> Rendering speed performance is supposedly improved (though I have seen no proof of this)

There is no reason this would be true, and the author isn't even claiming it.

After reading it through, I am beginning to seriously doubt that this was intended as satire. In which case the author is very, VERY wrong. I continue to hope that I am simply missing the joke.


Same thoughts as you, and it looks like we both went through the benefits line-by-line with a comment in this thread!

It sounds like the author wants Functional CSS to be the Ultimate CSS Solution™, when in most cases, you can write better CSS and/or stick to a design system and/or plan out and manage your components better.


I think, in the end, I'd much rather use JavaScript + React + react-jss for this kind of work. It's actually really nice with material-ui and re-using most options from the theme and/or existing components. yeah, 2/3 of my app come from react-dom and material-ui, but at the same time it's very consistent, easy to inherit from and easier to comprehend.

Web-Components may help someday, but so long as component properties are effectively strings, and hard to pass in from the outside, same for events, it makes it harder to manage discreetly.


This "functional CSS" approach is obviously wrong.

It causes repetition that would be avoided by defining a single CSS class (this can and probably should be done inside in the file defining the component), and also prevents making appearance changes outside of the component (e.g. in non-component JavaScript or with a CSS-changing browser extension).

If you want to obfuscate the semantics, then "minimized" class names are a better solution.

If you don't care about repetition, then inline styles are just as good, and actually better since you can for instance use any of the 2^24 sRGB colors.

None of the "downsides" listed in the document are reasonable arguments:

> Inline styles don't respect media queries, which basically rules out responsive design

"Utility classes" also don't, unless you define one for each possible media query and style (that's > 2^16 possible widths, > 2^16 possible heights, > 2^8 attributes...).

> Inline styles aren't limited to pre-defined options, meaning you can still end up with 90 different shades of blue

That's a downside, and also CSS has built-in color names.

> Inline styles cause specificity issues, since they trump separate stylesheets.

Use !important.

> Inline styles don't support print-specific styles.

True I suppose, but nobody cares about printing webpages nowadays, and those who are meticulous enough to care probably aren't choosing between inline styles and utility classes since they are both bad approaches.

> Inline styles can't address pseudo-elements (such as ::before and ::after)

You can just put the content in the HTML itself if you are explicitly specifying the appearance.

> Inline styles can't apply to multiple elements. Utility classes can define .bg-blue once and have it apply to many things, which leads to shorter markup and quicker rendering speed.

class="bg-blue" has to be repeated just as much as the equivalent background style...

> Inline styles are a pain to type. Compare class="f-sm bg-blue" to style="font-size: 10px; background-color: #0000ff;".

You should use IDEs with autocomplete, and then they are going to be easier to type, and most importantly developers already know them and can thus easily read and write them without consulting any documentation or CSS file.


> CSS has built-in color names.

You can't be serious can you? Css has what around 150 color names? That is jut not good enough for any serious work.

> Use !important.

Please don't use !important, avoid it as much as possible. It just compounds the issue.

> class="bg-blue" has to be repeated just as much as the equivalent background style

But the definition of what shade of blue we're using is in only one place. Forget bg-blue and think of theme-blue, theme-blue-highlight, theme-blue-mid and so on. A professional design needs vocabulary.

> You should use IDEs with autocomplete

Do these IDEs help with reading and interpretation?


The way people using CSS ties to the way they write markup. I like to think like thinking about Big O; read, insert, delete, update. Database design involves this kind of thinking too. What operation you do most on your data structure (html in this case)

Atomic CSS

What's time complexity for each operation(by human)?

Read: O(sigh)

Insert: O(1)

Delete: O(n)

Update: O(n)

Pre-BEM era CSS

What's time complexity for each operation(by human)?

Read: kinda O(1)

Insert: O(1)

Delete: O(1) without garbage collect (unused css)

Update: kinda O(n^n)

That's a quick thought, maybe your operations are more arbitrary.

Probably when someone introduces new css framework/technique, showing some kind of complexity measurement (if possible) would be good idea?


I've been a semantic CSS proponent for years, but I'm intrigued. CSS puts everything in a global namespace, which is an anti-pattern everywhere else. Most modern approaches have been moving towards limiting the scope of Cascading (CSS Module, Styled Components).

The semantic approach forces you to generalize your HTML up front and leads to over-engineering styles. Plus JS component libraries make refactoring across a project a lot simpler.


The everydollar web app used to have a lot of utility classes and it was a nightmare to work on. We've spent a lot of engineering hours cleaning that up. I suppose if you were completely strict about only using utility classes you might get a little farther, but I still wouldn't recommend utility classes. The best idea I've seen is utility SCSS mixins applied behind the scenes to BEM classes or locally scoped css.


I moved away from “utility-first” CSS in favor of heavy usage of SASS mixins. If you can modularize your CSS to the degree shown in Tailwind, then you can get the best of both worlds by keeping your class names in BEM while the underlying SASS is primarily composed mixins.

Referencing the OP’s example in short:

  #m-5 {
    margin: 20px;
  }
  .card {
    @extend #m-5;
    /* custom styles */
  }
Edit: formatting


Has anyone ever maintained an SCSS codebase like this, with all kinds of logic, mixins, deep nesting, and variables? It's a nightmare.

Keep your CSS as absolutely shallow, declarative, and "noun-based" as possible. Stay away from utility classes and "adjective-based" classes. Preferably everything should be within it's own component (React/Vue/Web component/etc.).


I'm still a little confused. The wording in the example makes it difficult to figure out which example is really "functional css"


Like most things, the best approach lies somewhere in the middle. I’ve had a lot of success with using component driven CSS (BEM, SMACSS, etc style) in combination with utility classes. The components keep everything consistent and make building pages much faster. The utility classes let you do the inevitable little tweaks without a bunch of one off, weird component modifier classes.


After using bootstrap4 i have come to use this approach more often. Its just easy to use d-flex, justify-content-, p-, m-* classes to construct a component.

After reading https://adamwathan.me/css-utility-classes-and-separation-of-... i might use it even more!


That seems much more procedural than functional. There's nothing functional about "set this element a 5px margin and a light gray text and a darker background and a light gray border" which is quite literally the statement of the first snippet's @class.

Composing .profile-card out of these could be a functional approach, but you're just writing @style via @class.


I think producing atomic css classes falls should be done by a computer. [Styletron](https://github.com/styletron/styletron) and [CSS Blocks](https://css-blocks.com/) comes to mind.


If using React and looking for a similar approach -- check out Rebass and styled-system (https://github.com/jxnblk/styled-system). Their APIs are a pleasure to work with


I’m about to start writing a very simple html page ( think search panel + result table underneath) after having stayed out of html for a few years. What are the current best practices regarding css tools and framework that could make my life easier ?


HTML + CSS, pure and simple. Don't overthink. Frameworks like bootstrap were useful back when they started: column layout (and other popular patterns) were hard to achieve, and each browser (and version) had their own quirks to work around.

Today, CSS Grid and Flexbox are easier and more powerful than any framework, and aside from bleeding-edge features the major browsers have converged.


thanks, indeed last time i checked (a few years ago), flexbox weren't really widespread. I think i'll stick to that.


Honestly, try tachyons for styling. I rarely have to write any CSS now, which saves considerable time.


I use Webflow so I don't have to deal with these types of decisions.


The benefits?

> You don't have to write any CSS of your own (which, to me, is fantastic)

This applies to any CSS or UI framework.

> You can likely build things faster (obviously non-scientific, but anecdotally I've seen many people confirm this)

Yes, this is anecdotal and debatable. At the end of the day, you still have to read the documentation of this specific CSS framework.

> You don't ever have to think about naming things

I don't think developers that are creating anything don't ever have to think about naming things. If you're creating something, you have to name it. But yes, you don't have to add that name to your CSS class.

> You can tell what something looks like by just reading the markup for it

You could also tell what something looks like by just reading the CSS for it.

> You don't ever have to worry that changing the styles for one thing will break something else (which may make visual regression testing irrelevant)

There's a couple other approaches to this like style localization/isolation that the author called "ton of crazy randomly-generated class names". As opposed to the ton of single-purpose utility class names, which is more sane? You could also write stricter CSS selectors (like BEM or your own).

> You never have to deal with one instance of a thing needing a slightly different style than the other instances, which screws up your reusable classes.

Sure, as long as if you stick to a framework. If you're building a one-off with no collaboration with other people, then this is easier to pull off with an off-the-shelf CSS/UI framework.

> Your CSS always stays the same size rather than expanding over time

Okay!

> It's easy to un-apply a style by just removing the class (as opposed to the traditional cascade where you typically have to override, adding even more CSS)

You could isolate styles that are prone to removal into a single class with regular CSS too. Hate to be the nerd to say this, but the "Cascade" in CSS is what makes it such a versatile interface styling engine.

> Rendering speed performance is supposedly improved (though I have seen no proof of this)

Once again, anecdotal.

————

Sounds like the author is allergic to reading/writing CSS and wants the markup to be heavily coupled with styling. Also sounds like having a strict framework makes their developer experience happy, which is applicable to any well-designed design system.

There's nothing wrong with any specific CSS methodology or framework, and there's a time and place for every single one of them.

I think I would prefer vanilla CSS with strict rules for one-offs before using something like this, though.


I like using functional CSS for utility classes

e.g.

> .mb-1 {margin-bottom: 1rem}

> .text-center {text-align: center;}

> .flex {display:flex;}

But why would you give up the templating win of CSS?

Make a standard button class.

When you want it to have a different (standard) margin, use a utility class on it.


>When you want it to have a different (standard) margin, use a utility class on it.

Then when the next PM wants this button to be blue, you make another utility class and end up editing HTML. It's better to just think entirely in terms of components that are independent of any external framework or guideline, which are only responsible for themselves. Everything on your page is a concrete implementation of an abstract component, and in that implementation you can customize all you want. Otherwise you end up with a massive dependency graph between components of various "utility classes" rather than a completely flat hierarchy of components which handle their own dependencies.


> Then when the next PM wants this button to be blue, you make another utility class and end up editing HTML.

So you're suggestion that when the PM wants this button to be blue, you make another component for that button? You haven't changed the problem, or the amount of work, you are just using a different layer to implement it.


> You haven't changed the problem, or the amount of work, you are just using a different layer to implement it.

Changing the layer you're implementing on is the whole point. It's about maintainability and keeping things encapsulated.

Now when someone comes back to look at this button a year later, they're not left wondering why this usage of "Button" is colored blue, and tracking down the utility class. They will know that it's an instance of "BlueButton" and can just edit the component directly.


How is a component called BlueButton more informative than <button class="blue">? The information content is exactly the same.

Now, more than likely the component isn't called BlueButton and the CSS class isn't called "blue" but rather both would have a name more semantically appropriate.


Found myself in agreement up until the concept of "semantic CSS class names". If you want semantic markup, then CSS is absolutely not the place to implement it IMHO.


It doesn't seem to me that the author defends semantic class names


I see functional css classes as a better primitive than raw css. Using tacyon's + less, all my classes can be composed from functional classes. Best of both worlds.


Today is the day I deleted last atomic class in my project. It was a long journey but it was worth it!


Functional CSS reminds me of React and JSX - there are plenty of people who will argue at length what a bad idea it is, having not tried it.


i don't see a big difference here to plain inline styles. seems to be very inconvenient


Font + colour scheme made this article unreadable.


I found the background colour a bit easier on the eyes personally. The font is a bit ugly though.


As a native-focused engineer I find it fascinating how web developers always find new ways to make their platform even worse than it already is...


[deleted]


The second paragraph "Isn't that basically the same thing as inline styles?" discusses exactly that.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: