Principles we use to write CSS for modern browsers(gist.github.com) |
Principles we use to write CSS for modern browsers(gist.github.com) |
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.
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.
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.
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...
- 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.
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"
WET: Write Everything Twice
Credit: https://roots.io/sage/docs/theme-wrapper/#fn2
:)
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. ;)
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?
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).
CSS tooling is quite rudimentary, too, which doesn't help.
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.
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.
I've experimented with it on a green field project and got promising results. Found I could refactor my CSS with confidence.
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.
For a context, I somehow can't wrap my head around writing something like:
<div class="nav nav-inverse nav-hide-xs">
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...
Also, I see "fixed" bug reports in both Chrome and Firefox when using flex with fieldset. To be fair, recent fixes.
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 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.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.
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.
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
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.
EDIT: why the downvotes?
With a naming convention, if you want to use work from two different packages and they happen to use the same names, you need to edit one of them. People come up with conventions to try to avoid this, like prefixing everything with the package name, but that doesn't fundamentally fix the problem. If two packages have the same name, they clash again. You have a fundamental tradeoff between short prefixes which are easy to work with, and long ones which are less likely to clash.
In other systems, when you use a package, you choose the prefix. If two packages use the same names, you just give them different prefixes. Short prefixes are fine, because they don't need to be globally unique.
It looks like CSS Modules works the second way, and that's an improvement over just being a naming convention.
Perhaps I wasn't clear - of course you should be careful about naming things well (one of the hardest problems in CS, right? :P), but using consistent terms, case and the like is one thing.
A large part of CSS naming conventions is doing more convoluted stuff such as business-page__contact-form__submit--disabled, just because there are other submit buttons on your website and you don't want some styles to clash. This is the part that is abstracted away by automatic solutions.
If your favorite programming language scoped all variables globally, no matter where you defined them, sure you could prefix them with the name of the current function to solve your problem, but it'd be painful and error prone.
Yes, that's true, but your use of the word "just" implies that auto-generation is a detail. It's not. It's the the big win. At root, everything is machine code, which also has a flat namespace. Having that flat-namespace code auto-generated is a huge lever.
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.
However, my context was mainly around architecting your own CSS, not as it relates to using someone else's.
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.
The real strength is how little of it you have to write. The most complex layouts I have only take a few lines of flex and they're way more responsive than their non-flex counterparts.
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.
Moreover, the barrier to entry to learning SCSS/LESS is really low if you know CSS.
[0] https://github.com/sass/sass/tree/4acf5158734013f08fca4be6e2...
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.
Check this out for an alternative to flexbox if you can't ignore that last n% of your users: https://kyusuf.com/post/almost-complete-guide-to-flexbox-wit...
That means even windows installations that haven't been updated since 2012 will support flexbox.
Luckily (for my sanity) we have a "new age" product that we can use responsive layouts for.
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.
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.
Sometimes though I will use the fallback because it actually does it better than flexbox.
Nevertheless I use flexbox almost everywhere. It's a great system to arrange anything from general layout to smaller components. There's absolutely no way that I'll deal with any kind of hacks to get basic things like vertical centering right.
https://github.com/philipwalton/flexbugs
I haven't come across anything in IE 10 or 11 that I haven't been able to work around pretty easily.
As a practicality, I prefer the naming conventions to the CSS processing pipeline, because it gives me a much better ability to debug and iterate.
But with a dev/prod environment, you can have your cake and eat it too (for the most part). In dev we have our classnames be in the format of `[classname]---[file-path]---[filename]---[partial-hash]` So one of my classnames from a current project is `.container` in the file, but shows up as `.container---src-components-scanner----styles---1446d`. And in production shows up as `._1533JgnvGu096C2bCAkrxT`.
Also, from the issues v2.X that polyfill appears be broken in IE9 atm, which is the last one with zero flex going on. (Fun fact, our metrics have ie9 and 10 with comparable userbases - fairly standard large public facing site. 9 is fully unsupported and IE10 is no longer an active target for our QA team beyond basic layout and functionality)
I do generally use a less mixin to shim all the tweener syntax tho.
https://www.chromium.org/developers/how-tos/chrome-frame-get...
Discontinued though.
I do occasionally get strange looks from my colleagues.
I don't particularly like the Javascriptification of every technology but these webdev graduates have the right idea.
We use SHA1 hashes of the CSS classes' contents as it's name when using CSS modules. This has the cool side effect of making any 2 classes that do the same thing to have the same name, and get de-duped in the final output, regardless of where they originated in the application.
When I saw it happen the first time, it really kind of cemented in the idea that this combined with a way to "punch through" the modularity to combine and extend "base" classes and include global colors (for us it's SASS imports) has pretty much "solved" CSS for me.
During development we have it set to `[local]---[path]---[name]---[hash:base64:5]` which gives massive verbose class names but lets me pinpoint exactly where they came from.
There's also one step that I left out that helps, which is to have something like csscomb[0] to order the properties of each class into a set order. It really lets this optimization shine by ensuring that different property-order won't cause different hashes.
Virii, Trojans and Hacks, oh my!
https://www.microsoft.com/en-us/WindowsForBusiness/End-of-IE...
Now you have to go through this endless dance of Enable/Disable compatibility mode depending on what site you are trying to visit. We have a lot of non technical users so as soon as you ask them to delve into menu options to use some added functionality on a site you lose them.
Even technical users hate this so most people sideload chrome. However a large number of workstation are locked down and those people have no option but to continue with IE.
I don't even want to admit how many managers come back to them with "we mitigate that risk with user education, we have too many legacy (blah blah blah)." There's always some excuse, isn't there? Usually within departments, but once executive-level hears this sort of thing, they tend to at least investigate what the real risks are. So I'm adding on to your advice to other readers to suggest they "go higher" with their security warning.
Man, I wish we lived in a world where management understood that people are shockingly good at finding ways of not doing what they're told!
(AKA sit down and shut up with your bullshit "sit down and shut up"s)
It's a breath of fresh air when an enterprise student has a modern environment. But it's enough of an outlier (in my experience teaching all these different places) to still surprise me to hear when it's true.
We started out in late spring / early summer back in 2015 saying we needed to support IE9, but that has since changed to 11. The notice from MS that nothing before 11 would be supported after January of this year (2016) forced the issue, I think.
Back when I worked at a financial company two years ago we sure had mandatory crusty old versions of IE, though. Except for the groups that got special permission to use a browser that actually worked for things they had to have.
Give it a year. Without MS support, they will be forced to give up these older versions. Of course by then, IE 11 will seem quite "vintage", but that's life.
IT can be brow beat just as hard as developers. They will change whatever domain policies you make them change. Quit being a pushover.