The CSS for dev.to is fairly wild-west right now. It's mostly scaled by way of isolating parts, meaning more copying and pasting and relying on SCSS nesting, less re-usability and few true rules.
I'm wondering if there are any CSS methodologies or strict rule sets you've used that you like. I'm familiar with BEM and would lean towards that from what I know, but I'm looking for some input to bring to the team.
Top comments (38)
Scoped CSS is all the rage right now, and I personally am a big fan. (CSS Modules is a good implementation: github.com/css-modules/css-modules)
Here's why: when you're building an app, you spend a few minutes styling the app itself and many hours styling (or wanting to style) individual components. But CSS by default doesn't support that. Every style affects the whole app. There's no modularization, which leads to frequent surprises (a la "dang it, I guess that class name is already in use" or "why did my style change over here mess up my component on a totally different route?").
BEM is really good, but it's a workaround. Scoped CSS is a solution. And it's a first-class citizen of Angular and Vue, if you happen to use one of those.
Cool, these are concepts I've seen flash my way but I never really caught the wave. Thanks. Still would love some other input on any of this.
I've really begun to dig the scoped CSS while working in Vue. It's made creating modular components that can be shared across the org a repeatable process that doesn't end in firefights on who's styling wins.
But, I don't have enough experience with large scale projects and long term projects, so I'm really enjoying reading this post :)
If you follow a CSS methodology, your code is going to be modular and you won't have any problem with scope. Try ITCSS, for example.
Most of the time you're right, a CSS methodology works great and avoids scoping issues. But regular CSS is non-scoped and non-modular by definition, so there's always the possibility that in a larger app, a developer will unknowingly use a component or utility name that is already in use elsewhere, thus destroying the semantic barriers between components and causing style conflicts. I've seen this happen a few times (with BEM) and it can be very difficult to figure out why things are broken.
That said, I'm not opposed to CSS methodologies at all, but if scoped CSS is an option I will always choose that because it's far less likely to fail due to human error.
In my company, we separate each CSS component in different files (button.scss, tabs.scss, etc). This way, there'no way to get conflicts.
If you think, css classes create scopes the same way js functions does.
CSS is not the problem. Developers are.
That's not the way I see it. If I have two separate JavaScript functions and each declares a variable named "foo", they will always refer to different memory locations. There is no way to get "foo" in one function to refer to "foo" in the other function. In CSS, if I declare two classes named "foo", both of them globally refer to everything with the class "foo."
Separating CSS components into different files doesn't create new CSS scopes. If you happen to use the same selector in both, then you'll end up with two different sets of styles for a single element. This isn't a rarity in large apps; it happens often. If one developer wants to create a tab that acts like a button (
.button-tab
) and another developer wants to create a button that looks like a tab (.button-tab
) they'll end up with an overlapping selector. Some developers will dig through the codebase to figure out where the conflict is and rename the class to fix things; many will not, and instead choose to bump up the specificity in order to make their styles work, which over time reduces maintainability.CSS was created for developers. If developers consistently have trouble with certain aspects of it, then blaming the developers isn't a productive approach. Scoped CSS is inherently predictable and debuggable in ways that global CSS is not.
If you create 2 foo functions globally, they will conflict. Of course you won't do it.
In CSS you can also prevent that. For example you can use BEM - or even nested selectors to help.
That's what I was trying to explain.
About separated CSS files, I forgot to say that every class inside each file must start with its name. For example, in the file button.scss you would put
.button
,.button--big
,.button__icon
, etc.Developers - specially with less experience - have problems with every language. That doesn't mean the languages are bad or wrong. It means we must create patterns and best practices for them.
"A CSS methodolody"... is a thing?! Oh you mean a way of structuring and naming selectors...?
Yes. Such as BEM, ITCSS, OOCSS, Atomic, etc.
you find out just how bad it is when you load a vue single file component and it mysteriously break another one because the CSS wasn't loaded yet
This has never happened to me. I wonder if that's been fixed in the latest version.
@ben
Don't go for hype-driven development!
Use stable architecture! Stay clear of frameworks, preprocessors and build steps. CSS is all you need! Base it for example on Herry's BEMIT and ITCSS. In addition, use very small and simple rules, meaning mainly one class you select (without nesting).
BEMIT is a naming convention, which makes sure that you can get a lot of info from the class name alone: How many elements are affected? Which role does it play? Where on the site can I find it? For example
c-menu__logo--small@mq-mobile
is a class name, which affects one element, located in the menu, which is a logo and makes the standard representation smaller in size. Additionally, it will only affect the mobile media-query.ITCSS is basically establishing layers of specificity (ranging from generic to specific), which makes sure you override rules in a sane manner. Harry uses the layers Settings, Tools, Generic, Elements, Objects, Components, Utilities in that order, but you can of course define your own!
On top of that, factor-in theming from the start. I already wrote an explanation, so I'll just copy that here:
t--light
t-
(theme) CSS class. For examplet-menu__item--active
>>> Full Example
Using the above techniques allows you to very easily
Hehe, you don't have to tell me about avoiding the hype. We probably have the least hypey approach I can think of. 😄
Thanks a lot for the tips. Will definitely take into consideration.
Yeah, I like this approach as well. I use a modified/simpler system of BEM/ITCSS, namely:
Structured like so:
Couldn't agree more! I think my favourite ways to write css are based on BEM(IT) and SMACSS. Thanks for t he great comment.
Personal opinion - it's easy to go crazy overarchitecting CSS. If it's under a couple thousand lines, just basic SCSS with nested selectors broken down by module, I think is more than enough.
Over 5k–10k lines is where I start to see the ROI of adopting a more formal CSS methodology (or refactor and embrace meta tools like variables and vendor prefix polyfill generators more). In my opinion too many sites out there today are the FizzBuzzEnterpriseEdition of CSS from going overkill with patterns premature to their scale. You know what they say about premature optimization…
As someone who started in CSS 10–12 years ago before tools like it existed, at first I was really turned off by React's approach to "inline styles". I think they're labeling them something different now to avoid conflation with inline CSS and its various pros and cons. Even the React approach has grown on me more over time though. You get pretty nice isolation which is really the most important part of scaling CSS anyway. In this sense, React components basically became what everyone wanted web components to be. And with components, we can solve a much smaller problem in CSS architecture.
Yes, this was the general reason for not going nuts with CSS rules early on, but I feel like it's worth creating some rules or exploring options.
Can you define more specifically what you mean by "nested selectors broken down by module"?
Is something like Elm to do the HTML and the JavaScript and the CSS too crazy?
It's not too crazy for someone else's type of app. We optimize for render performance and want to be a bit closer to the metal so we don't have to ship massive JS builds.
I'm a huge fan of SCSS + BEM, with the component-driven architecture of BEM complementing the component-driven architecture of React. I usually give each component its own small stylesheet and
@include
it in a main stylesheet. I have found that this gives me the most flexibility, readability, and re-usability of anything I've seen.I've had great results with a similar setup, (also a React app), although with two differences:
@include
in a core stylesheet, I tend toimport
the stylesheet directly in the component's JS source, using webpack loaders to handle this. This allows for slightly better build performance when developing, especially when using Storybook or similar, as well as not having a huge list of stylesheet imports in one place.One great thing baked into Angular: CSS scopes! I am a fan of Atomic Design :)
When full stack developers, a.k.a. Devs who doesn’t care much about style but need to keep the site in a decent shape, where in charge we followed the Trello guide gist.github.com/bobbygrace/9e961e8...
Now we have front end devs using Atomic design, but we keep the
js-
rule to id classes that are not use for styling but for JavaScript.I really like cssguidelin.es/ and the 7-1 file structure from sass-guidelin.es/ or some variation of it like smaccs. CSS guidelines is a pretty robust read but I love that it also drops tidbits of things I didn’t know just by explaining why some ‘rules’ exist at all. Both of these are from people I’ve followed and trusted for ages now so I may have a bit of selection bias haha
I love Tachyons (CSS library). It basically means that you almost never have to write custom CSS. Once you've started to get used to it it's so much faster. Not only that but it solves the CSS scoping issue in plain CSS which means it doesn't matter which framework you use. It's based on a design system so I makes it easy to make everything feel very cohesive. It's also trivial to make responsive websites with it. I've used it for many if my personal and work projects and have nothing but good things to say about it.
Sorry, just a bit of a fan.
I've been doing a lot of React Native recently and the way you write the stylesheets for React Native recently and the "inline styles" approach has been really pleasing to write.
I'm not an expert in CSS by any measure but from the experience I have, BEM (with SCSS or stylus) and React inline styling are my preferred approaches. If you want something a little more structure than inlining styles you could have a look at styled components: styled-components.com/.
I think that between styled components and BEM it would depend on how much you'd like to change your current build system by. BEM is totally compatible with SCSS and all the goodness that comes with it. React inline styling and styled components would require you to rewrite a lot of your existing SCSS into something that is closer to JS (and update tooling accordingly) so it may be too much overhead for not enough gain.
I've been learning styled-components after listening Wes Bos' Syntax podcast on the topic and a friend suggesting a look-see at them. So far, I'm really liking it. But I'm very much one for "keep everything together and easy to find", which is a selling point: the styles for the component are right there if you need to refactor/remove something.
Or, go the other route and try vanilla-css.com