A bit meta, but I need this off my chest: I love how this document starts off saying "this is for react apps". IMO every discussion about CSS coding standards needs to start with context.
A lot of old CSS lore came from people who build websites. I mean those fairly uninteractive things, focus on content. Blogs, restaurants, newspapers.
Building an application that happens to use the DOM as their UI toolkit is totally different. The whole "reuse the same classes but with different content" thing that CSS classes were designed for becomes less important, and "reuse pieces of behavior" makes a lot more sense.
There's probably more domains or subdomains that warrant their own CSS best practices. But I'm totally tired of a blog designer and a react app coder fighting on HN about how the other one is doing it wrong, when really they're just solving different problems.
I build large static websites, and sometimes apps, and can confirm that the CSS techniques listed in the article work very well for both use cases.
UI components don't need to map to richly interactive parts of an app, they can just as appropriately map to repeated design elements in a well planned static site.
Well said. This goes (probably double) for the similar conversations about javascript, where lots of people question whether it should be used at all, which is a reasonable question for sites but not for applications.
"reuse the same classes but with different content"
What difference does the content make if the styling is meant to be the same?
"reuse pieces of behavior"
Now, that made me curious. Can you expand on that because I'm not sure I quite understand what you mean.
edit: I've read through the naming convention they describe and I don't see much anything that different than how I would create CSS for a website. It's just a clean naming convention that would work for a website as well as an application.
IMHO, naming conventions such as SUIT, BEM, OOCSS and the like are NOT a good practice, but merely a workaround for dealing with the limitations of a global namespace.
My preferred solution are CSS Modules[1], Vue's scoped styling[2] or something similar.
What amazes me is how violently the run-of-the-mill programmer hates namespaces. Despite the fact that managing namespace collision is important for composability (either deliberate or accidental) and code generation.
This problem has, for instance, dogged RDF. All the time I hear about programmers who "don't want to learn SPARQL" and I think the heavy use of namespaces is one of the impediments. For most other programming languages it seems the opposite:
(i) half of the software managers in the world are driven nuts because their team is screwing around with Vagrant instead of working
(ii) it seems no programming task is too boring if you do it in rust or go.
CSS Modules is still a "naming convention," just one that is auto-generated for you. Naming conventions in CSS are as much of a good practice as naming/linting conventions in JS.
- Good CSS design needs zero !important statements. Fix your specificity or your component architecture if you have a need to use !important.
- DRY is a good thing, not a bad thing. Maybe straight CSS isn't quite there yet but...
- Why not use the tools at your disposal to aid in development (and DRY) such as SASS/LESS?
- Flexbox will be great once IE dies the well-earned death it deserves.
I'm very happy the author had great success with their setup. What works, works. But I hesitate to assume that just because it works without using DRY principles or other tooling, it means you shouldn't.
Avoiding !important is generally very good advice, although the ZOMG NEVAH! approach is a bit overzealous IMHO.
One good example would be overriding random external styling (e.g. an included CSS file some plugin you use). If their stylesheet has very long and specific selectors, you can either repeat them entirely (#plugin .container .subcontainer .input-wrapper.input-wrapper-blue input[type=text]:first-child) or stay within your general selector-writing practices and use !important instead. I'd argue the latter is a better practice.
Secretly, I'm not that happy with flexbox. I think it's more intuitive in some cases, but I don't think it's more intuitive than floats and the like.
For example, I always feel like I want a `justify-self` property like `align-self`, but instead I must use `margin: auto` on the opposite side—in a flex row of elements, if I want the last one to be right aligned while the rest are hanging out in the center, I have to tell that last element to be `margin-left: auto`.
I think it's just an issue that it has taken so long to be useable (IEs :( ), there has been a lot of hype, and it's not quite the panacea I imagined it would be.
> - Why not use the tools at your disposal to aid in development (and DRY) such as SASS/LESS?
Because there is so much tooling churn + barrier to entry.
The point is that sometimes it's better to repeat yourself than to use the tool of the month.
I love React, and even there, I only style components in the way they need to be styled, and not with any other brand-specific styles. Those go in the good ol' fashioned CSS with "gently nested" CSS selectors. The enterprise world is considerably more nuanced than many SPA devs understand.
A class of folks from US Gov, manufacturing, pharmaceutical and finance industries (to roll them into general groups) and every one of them answers "IE9" when asked what browser they have to support, and every one of them is at home with "the old ways" of writing CSS, by embracing the cascade.
It's not that they're wrong. They're pragmatic.
And, In some cases a little bitter, I'll grant you. ;)
A random brain dump prompted by this statement: "No DRY. It does not scale with CSS, just focus on better components"
All programming involves resolving a conflict between two different principles and a lot of the fiercest disagreements are between people that weight the importance of these two things differently:
1. Reducing repetition
2. Reducing dependencies and side effects
The language and it's tooling/ecosystem can affect the importance of these.
The project's complexity, rate of change and lifespan is also a factor that might push you one way or the other.
But anything that helps one of these harms the other.
I wouldn't say that they are always mutually exclusive. I think there is a variable ratio between advantages gained by 1. and disadvantages caused by 2.
In other words, at first, reducing repetition will net nearly no negative results - you just recognise different areas that do very similar things and write a common functionality. The most basic example would be programming languages providing standard libraries, even though everything could be done with regular operations. At this point, abstractions are even simpler to use than implementing things yourself.
Problems start to arise once you hit a certain point beyond which your abstractions become harder to use and maintain than simply writing things multiple times. This is where you should stop abstracting/modularising things away (assuming that the reason is purely overengineering, not bad engineering).
That's consistent with my experience with a very DRY Sass library. If the consumer needs flexibility, such as different themes or new context for components it quickly becomes impossible to manage dependencies and abstraction begin to leak.
CSS tooling is quite rudimentary, too, which doesn't help.
You are essentially right. But I would say anything that helps one of these harms the other.
Part of the art of good language/library/thingy design is to understand, and then defy those trade-offs. Try and have you cake and eat it too. It's not always possible, but sometimes it is.
Why not both? Global flexbox support is >96% and in the US it's >97%.
Unless you're aiming for a 1:1 pixel-perfect experience in crappy old versions of IE, it's negligibly simple to detect IE (or lack of flexbox support), and just use something else. You can usually get pretty close to a lot of flexbox layouts with display: table and related properties, and also falling back to floats for others.
In a worst case scenario, you can provide old IE with a more mobile-like experience and just let things stack up.
Flexbox is supported in all versions of IE that Microsoft themselves still support (IE 11 and up). You can still support it in IE10 too, albeit with a different syntax.
That means even windows installations that haven't been updated since 2012 will support flexbox.
Last week I was in an interview with Amazon for a position in their web development team. One of the questions was related to this, they asked me to describe how to create the layout for a web page with two columns, I immediately thought about Flexbox but decided to describe the code using "float: (left|right)" and box-sizing, I felt that the two interviewers didn't like my answer because it is outdated.
This largely depends on your target audience. Flexbox is only problematic for IE <= 9, which, according to caniuse.com accounts for less than 1% of all browsers.
But this should always be checked against more relevant stats (your country, old website you're redesigning, etc.), so yeah, if you know you have a lot of people on IE9 and lower, flexbox is out of the question.
I agree with the Flexbox and DRY principles, but it's weird to still rely on arbitrary naming conventions like SUIT when CSS modules have been around for a while now.
Naming things has always been difficult, especially in CSS where it can lead to merging/overriding/precedence issues. Not having to think about what CSS class names are either available or possibly conflicting is a benefit from CSS modules that increases productivity by an order of magnitude I've rarely seen in CSS, especially in large codebases.
You've got a button and want to call it "button" and style it using ".button"? Go ahead. It will only inherit styles if you explicitly say so. The global namespace remains healthy for each component you write.
These days using "nav" instead of <div class="nav"> is the preferred method by default. The other two classes are just modifiers that may or may not be required. There's nothing wrong with them.
Also, I see "fixed" bug reports in both Chrome and Firefox when using flex with fieldset. To be fair, recent fixes.
FWIW, I'm using Angular (1.x) on a project at work, rather than React. One of the things I did recently was take the CSS file used in the project ("Few Pages App", rather than SPA, which had a common .css file), and turn it into an Angular (javascript) "directive".
I wish I had done this earlier. I have no "compile" step, it's just straight js plus the framework. However, I now have a mechanism to use variables for any (new) stuff with repeated settings, inserted into the rest of the text in the "<style> ... </style>" template.
I've developed my last 5 projects (corporate websites with many different layouts) with SASS + Foundation 6 an no naming convention. Instead I relied on nesting selectors.
I can behave and usually not go deeper than 4-5 levels. It's a really neat way unambiguously tell a CSS rule where it should belong to. For example I can create a
section.hero-block{ /* things inside are scoped */ }
CSS selectors who live outside are pretty basic, utility style ones, they exists on one level, so they can be easily overwritten by the scoped ones if needed.
This is how I've developed projects for the past two years. Every module is scoped. If it needs variations but contains the same HTML structure - it gets a modifying class (.full, .half, .side, .footer, whatever)
If it has a different HTML structure - it is a different module entirely: `.module.v1` VS `.module.v2`
Doesn't matter if 85% of the CSS is shared between v1 and v2. If the HTML structure is different, it is a different version of that module. If you can run a diff checker and return 100% the same HTML structure but you need a different coat of paint, you add a variation class. All modules begin as a "v1". This prevents it from needing to be added to the scope selector if a "v2" is ever added. I've yet to work at such a scale where the loss in CSS performance was a problem.
Utility and State classes live in global space. Global being defined as anything unscoped, not "everything in CSS is global space". Since everything is scoped - I can safely reduce selectors. Very rarely does it go more than 3 levels.
I use some level of OOCSS but don't use it for things like `.floatLeft`. If it is a style I will want to remove later, typically for responsiveness, then I don't want a class `.floatLeft` that is really `.floatNone` at a certain size. I would rather take `.item` and change `float: left` to `float: none` with a media query.
So, I don't do any front end work in my day-to-day, so this may be a stupid question. This article starts out with how CSS gets a lot of negativity. What alternatives are there? Do browsers understand anything but CSS for styling?
I think an important thing to note here is that this individual's team is very small. If you have a small team that closely collaborates then scaling things which take discipline (like CSS) becomes vastly simpler.
CSS is difficult because it takes so much effort to do things the "right" way. It requires a good set of linting and testing tools or constant vigilance to maintain a correct, robust system.
As the codebase or team grows the difficulty of that task increases. That, to me, is why CSS often viewed in a negative light.
Funny how all the original markup and languages are becoming the machine code of the web. No one writes js anymore, just compiles into js. No one writes css anymore, just SASS -> css. Html? Nope, directives or shadow dom.
[+] [-] skrebbel|9 years ago|reply
A lot of old CSS lore came from people who build websites. I mean those fairly uninteractive things, focus on content. Blogs, restaurants, newspapers.
Building an application that happens to use the DOM as their UI toolkit is totally different. The whole "reuse the same classes but with different content" thing that CSS classes were designed for becomes less important, and "reuse pieces of behavior" makes a lot more sense.
There's probably more domains or subdomains that warrant their own CSS best practices. But I'm totally tired of a blog designer and a react app coder fighting on HN about how the other one is doing it wrong, when really they're just solving different problems.
[+] [-] Wintamute|9 years ago|reply
UI components don't need to map to richly interactive parts of an app, they can just as appropriately map to repeated design elements in a well planned static site.
To me its the same problem.
[+] [-] sanderjd|9 years ago|reply
[+] [-] talmand|9 years ago|reply
What difference does the content make if the styling is meant to be the same?
"reuse pieces of behavior"
Now, that made me curious. Can you expand on that because I'm not sure I quite understand what you mean.
edit: I've read through the naming convention they describe and I don't see much anything that different than how I would create CSS for a website. It's just a clean naming convention that would work for a website as well as an application.
[+] [-] ooqr|9 years ago|reply
[+] [-] MatekCopatek|9 years ago|reply
My preferred solution are CSS Modules[1], Vue's scoped styling[2] or something similar.
[1] https://github.com/css-modules/css-modules
[2] https://github.com/vuejs/vue-loader/blob/master/docs/en/feat...
[+] [-] PaulHoule|9 years ago|reply
This problem has, for instance, dogged RDF. All the time I hear about programmers who "don't want to learn SPARQL" and I think the heavy use of namespaces is one of the impediments. For most other programming languages it seems the opposite:
(i) half of the software managers in the world are driven nuts because their team is screwing around with Vagrant instead of working (ii) it seems no programming task is too boring if you do it in rust or go.
[+] [-] davidkpiano|9 years ago|reply
[+] [-] cel1ne|9 years ago|reply
[+] [-] ulkesh|9 years ago|reply
- Good CSS design needs zero !important statements. Fix your specificity or your component architecture if you have a need to use !important.
- DRY is a good thing, not a bad thing. Maybe straight CSS isn't quite there yet but...
- Why not use the tools at your disposal to aid in development (and DRY) such as SASS/LESS?
- Flexbox will be great once IE dies the well-earned death it deserves.
I'm very happy the author had great success with their setup. What works, works. But I hesitate to assume that just because it works without using DRY principles or other tooling, it means you shouldn't.
[+] [-] MatekCopatek|9 years ago|reply
One good example would be overriding random external styling (e.g. an included CSS file some plugin you use). If their stylesheet has very long and specific selectors, you can either repeat them entirely (#plugin .container .subcontainer .input-wrapper.input-wrapper-blue input[type=text]:first-child) or stay within your general selector-writing practices and use !important instead. I'd argue the latter is a better practice.
[+] [-] adregan|9 years ago|reply
For example, I always feel like I want a `justify-self` property like `align-self`, but instead I must use `margin: auto` on the opposite side—in a flex row of elements, if I want the last one to be right aligned while the rest are hanging out in the center, I have to tell that last element to be `margin-left: auto`.
I think it's just an issue that it has taken so long to be useable (IEs :( ), there has been a lot of hype, and it's not quite the panacea I imagined it would be.
[+] [-] dclowd9901|9 years ago|reply
[+] [-] gbog|9 years ago|reply
[+] [-] caub|9 years ago|reply
[+] [-] daurnimator|9 years ago|reply
Because there is so much tooling churn + barrier to entry. The point is that sometimes it's better to repeat yourself than to use the tool of the month.
[+] [-] al2o3cr|9 years ago|reply
Remember kids, the cascade is TEH B4DZORS - so always include everything you would have gotten from it in every class name. headdesk
Solidly delivered on the "no DRY" premise. Maybe they should coin a new acronym like "WET": "Write Everything Thrice"
[+] [-] awesomebob|9 years ago|reply
WET: Write Everything Twice
Credit: https://roots.io/sage/docs/theme-wrapper/#fn2
:)
[+] [-] spdustin|9 years ago|reply
Solid. I'm using that in my class today.
I love React, and even there, I only style components in the way they need to be styled, and not with any other brand-specific styles. Those go in the good ol' fashioned CSS with "gently nested" CSS selectors. The enterprise world is considerably more nuanced than many SPA devs understand.
A class of folks from US Gov, manufacturing, pharmaceutical and finance industries (to roll them into general groups) and every one of them answers "IE9" when asked what browser they have to support, and every one of them is at home with "the old ways" of writing CSS, by embracing the cascade.
It's not that they're wrong. They're pragmatic.
And, In some cases a little bitter, I'll grant you. ;)
[+] [-] vog|9 years ago|reply
[+] [-] Guillaume86|9 years ago|reply
[+] [-] Roboprog|9 years ago|reply
[+] [-] andybak|9 years ago|reply
All programming involves resolving a conflict between two different principles and a lot of the fiercest disagreements are between people that weight the importance of these two things differently:
1. Reducing repetition
2. Reducing dependencies and side effects
The language and it's tooling/ecosystem can affect the importance of these.
The project's complexity, rate of change and lifespan is also a factor that might push you one way or the other.
But anything that helps one of these harms the other.
Thoughts?
[+] [-] MatekCopatek|9 years ago|reply
In other words, at first, reducing repetition will net nearly no negative results - you just recognise different areas that do very similar things and write a common functionality. The most basic example would be programming languages providing standard libraries, even though everything could be done with regular operations. At this point, abstractions are even simpler to use than implementing things yourself.
Problems start to arise once you hit a certain point beyond which your abstractions become harder to use and maintain than simply writing things multiple times. This is where you should stop abstracting/modularising things away (assuming that the reason is purely overengineering, not bad engineering).
[+] [-] brunoc|9 years ago|reply
CSS tooling is quite rudimentary, too, which doesn't help.
[+] [-] adrianratnapala|9 years ago|reply
Part of the art of good language/library/thingy design is to understand, and then defy those trade-offs. Try and have you cake and eat it too. It's not always possible, but sometimes it is.
[+] [-] davedx|9 years ago|reply
Yes, great, if you can ignore all the IE users. Is that what "modern" means?
I'd love to use flexbox where I work, but it's just not feasible to give up all the customers we would lose.
[+] [-] freshyill|9 years ago|reply
Unless you're aiming for a 1:1 pixel-perfect experience in crappy old versions of IE, it's negligibly simple to detect IE (or lack of flexbox support), and just use something else. You can usually get pretty close to a lot of flexbox layouts with display: table and related properties, and also falling back to floats for others.
In a worst case scenario, you can provide old IE with a more mobile-like experience and just let things stack up.
[+] [-] kilian|9 years ago|reply
That means even windows installations that haven't been updated since 2012 will support flexbox.
[+] [-] guessmyname|9 years ago|reply
[+] [-] MatekCopatek|9 years ago|reply
But this should always be checked against more relevant stats (your country, old website you're redesigning, etc.), so yeah, if you know you have a lot of people on IE9 and lower, flexbox is out of the question.
[+] [-] ggurgone|9 years ago|reply
It is not as feature-rich as flexbox is but it works great - I built a similar one when I used to work at Yelp https://www.yelp.com/styleguide#section-arrange and it scales well.
[+] [-] bobbytherobot|9 years ago|reply
Sometimes though I will use the fallback because it actually does it better than flexbox.
[+] [-] unknown|9 years ago|reply
[deleted]
[+] [-] EdSharkey|9 years ago|reply
I've experimented with it on a green field project and got promising results. Found I could refactor my CSS with confidence.
[+] [-] bbx|9 years ago|reply
Naming things has always been difficult, especially in CSS where it can lead to merging/overriding/precedence issues. Not having to think about what CSS class names are either available or possibly conflicting is a benefit from CSS modules that increases productivity by an order of magnitude I've rarely seen in CSS, especially in large codebases.
You've got a button and want to call it "button" and style it using ".button"? Go ahead. It will only inherit styles if you explicitly say so. The global namespace remains healthy for each component you write.
[+] [-] prashnts|9 years ago|reply
For a context, I somehow can't wrap my head around writing something like:
when `<nav>` makes more sense. Sure, if you have a case with alternate "inverse" navbar, go ahead with a class `<nav class="inverse">`.About the flexbox, ah, well, even now they have undefined behaviour on several elements such as a `fieldset` [1].
[1]: http://stackoverflow.com/questions/28078681/why-cant-fieldse...
[+] [-] talmand|9 years ago|reply
Also, I see "fixed" bug reports in both Chrome and Firefox when using flex with fieldset. To be fair, recent fixes.
[+] [-] Roboprog|9 years ago|reply
I wish I had done this earlier. I have no "compile" step, it's just straight js plus the framework. However, I now have a mechanism to use variables for any (new) stuff with repeated settings, inserted into the rest of the text in the "<style> ... </style>" template.
[+] [-] kowdermeister|9 years ago|reply
I can behave and usually not go deeper than 4-5 levels. It's a really neat way unambiguously tell a CSS rule where it should belong to. For example I can create a
CSS selectors who live outside are pretty basic, utility style ones, they exists on one level, so they can be easily overwritten by the scoped ones if needed.[+] [-] Nadya|9 years ago|reply
If it has a different HTML structure - it is a different module entirely: `.module.v1` VS `.module.v2`
Doesn't matter if 85% of the CSS is shared between v1 and v2. If the HTML structure is different, it is a different version of that module. If you can run a diff checker and return 100% the same HTML structure but you need a different coat of paint, you add a variation class. All modules begin as a "v1". This prevents it from needing to be added to the scope selector if a "v2" is ever added. I've yet to work at such a scale where the loss in CSS performance was a problem.
Utility and State classes live in global space. Global being defined as anything unscoped, not "everything in CSS is global space". Since everything is scoped - I can safely reduce selectors. Very rarely does it go more than 3 levels.
I use some level of OOCSS but don't use it for things like `.floatLeft`. If it is a style I will want to remove later, typically for responsiveness, then I don't want a class `.floatLeft` that is really `.floatNone` at a certain size. I would rather take `.item` and change `float: left` to `float: none` with a media query.
[+] [-] seag64|9 years ago|reply
[+] [-] frankwiles|9 years ago|reply
[+] [-] unknown|9 years ago|reply
[deleted]
[+] [-] zephraph|9 years ago|reply
CSS is difficult because it takes so much effort to do things the "right" way. It requires a good set of linting and testing tools or constant vigilance to maintain a correct, robust system.
As the codebase or team grows the difficulty of that task increases. That, to me, is why CSS often viewed in a negative light.
[+] [-] talmand|9 years ago|reply
[+] [-] surganov|9 years ago|reply
https://github.com/chibicode/react-functional-css-protips
[+] [-] pluma|9 years ago|reply
I'm not sure which is worse:
A) having twenty classes on each element, each doing only one or two things
B) having twenty classes overlapping on the same one or two things
[+] [-] jorblumesea|9 years ago|reply