As someone with an embedded C and C++ background, I have to admit, the world of web programming seems bewildering and alien with all its frameworks and workflow engines and module bundlers and virtualization and containers. Does anyone even write code anymore, or has web programming simply become a systems integration problem?
It's a testament to how awesome and diverse this field is that you can take two people, both think of themselves as professional programmers, and chances are each will be mystified by what the other person does day to day.
I almost think the author's intent was to show all the different things he knows about.
There isn't too much difference in the tools in this list than what you use everyday. The problem is they aren't bundled together and the flexibility adds to confusion.
I liked the article, but there's something I need to point out regarding CSS preprocessors. It's way more important than making CSS "a bit better".
Preprocessors allow you to achieve modularity and DRYness. They allow you to move the object-composition duty from the browser to the build process - hence avoiding overloading the browser with composition (i.e. composing a class with SASS mixins or extends, instead of plugging many classes in a single HTML element). They allow you to easily express relationship through class names instead of relying on DOM hierarchy (separation of concerns). And, obviously, they allow variables! Common and centralized palettes, sizing definitions, typography definitions; also, "computable" definitions (e.g. deriving a shades/tints palettes via the built-in color management functions, or computing a typography scale from a base size).
If you have the time to learn CSS and a preprocessor adequately (and think about how to tackle common architectural issues having these characteristics in mind, isntead of borrowing solutions from e.g. OOP), then you might have clean, elegant and maintainable CSS (instead of a hairy jungle of rules that nobody in your team would want to mess with).
I can tell we're aligned regarding CSS architecture - and also regarding Angular. :)
The style guide you linked is very clear and concise in explaining why BEM is great without being a panacea - it's ugly, but it's simple, predictable and solves many of the issues which arise with CSS nature (e.g. everything in CSS is global). I also liked the emphasis on having BEM as a naming convention, no more.
Regarding how you introduce BEM, I would only:
* Reinforce the idea that a BEM compliant worflow would typically allow developers to change mark-up without having to look up stylesheets and vice-versa;
* Reinforce how much it would typically reduce side-effects!
I'd also give a few words on the topic of using the preprocessor (mixins, extends and, obviously, variables) to achieve DRYness.
* My argument to my team was to have readable semantic and obvious classnames (without style references in the name, e.g. no .blue-widget) which are "composed" via SASS (and SASS constructs might have style references in the name e.g. my-button @extends %blue-button);
* The other argument, and the one I actually believe `philosophically is that this allows you transfer the object-composition duty from the browser to the build process. It just makes sense to me: why have thousands of clients composing styles (e.g. button class="btn btn-lg btn-primary") when this is predictable ahead-of-time (button class="my-btn", where .my-btn = @make-btn(lg, primary)). This gives you performance and, as I said above, the possibility to have readable class names - I don't exactly know what "btn btn-lg btn-primary" might be, but "btn-login" is quite obvious.
In your contributing guidelines I noticed you have @extends with classes (e.g. @extend .mint-list). I use placeholders instead of classes to avoid side effects which are difficult to predict (even more so when you have a team with different levels of expertise). Here's why: http://csswizardry.com/2014/01/extending-silent-classes-in-s....
I'd also reinforce the notion - as less experienced developers do this quite often - of the different concerns of HTML (structure) and CSS (style). Newcomers to HTML seem to believe that HTML is a GUI mark-up language and, ergo, it shouldn't be problematic to use it as a presentational layer. As a practical example, "newcomers" usually have HTML elements only for presentational purposes, such as <div class="shadow"> or a list item used as a divider between other list items. I usually spend a few minutes of my time explaining how to avoid this using e.g. :before and/or :after.
I hear what you are saying about clean and elegant css being possible with preprocessors that add abstraction capabilities. I have never ever seen it in practice, at least nothing on par with the abstraction abilities of code. Can you post a medium scale example of clean & maintainable css that we might study?
I'm not really aware of that, as it's hard to infer CSS architecture when the final "build" is minified and built from a preprocessor. We would need something public. Maybe https://github.com/google/material-design-lite/ ? I'm obvious "partial" to BEM.
P.S. I don't think you'll have the abstraction abilities of code.
Bootstrap is quite the opposite of what I'd consider good CSS architecture (although it's obviously a great project). Way too much reliance on DOM structure.
On a larger scale (overall layout of a page) CSS reliance on DOM structure is a bad thing. But on a small scale (layout of a component) the cleanest markup is usually going to require coordination between the CSS and the DOM structure (and JS if the component has custom behaviors.)
This is true for basic html too. You could create a bullet list by adding a div with a class for the container and arbitrarily located divs with classes indicating that they're list items related to the container, and then use complicated CSS to pull it all together into a visual representation of a bullet list. Or, you could use a ul element for the container with direct child li elements for the items. Your visual style relies on the DOM structure, but overall it's a cleaner solution.
Why would you create a list with <div> elements? I understand your point; DOM structure has styling defaults and you have to play with it - 100% decoupling it's not possible. Still, trying to achieve decoupling between structure and styles doesn't mean that you should create bad mark-up.
In your scenario, I'd use a list element (<ul> or <ol>, according to the nature of the data) with a class (e.g. .my-list) and list item elements also with a class if needed (<li> with e.g. .my-list__item). No complications here. If somewhere along the way someone wanted to to a navigation area with exactly the same styles but with a different mark-up (anchors inside a <nav>), you could reuse or extend those classes to a <nav> element for the container and <a> elements for items. That's another "level" of DOM independence.
That's exactly how Bootstrap's classes for lists work. And they are tied to the DOM structure, though not necessarily to particular elements: .my-list has to go on a container element, and .my-list__item has to go onto children of that element.
The point I was trying to make was that at a component level, your CSS classes are usually going to depend on a particular hierarchy in the DOM elements that the classes are applied to, or they won't work correctly. How much of a dependency you have is a tradeoff; you can design your framework to minimize the dependency, but you're likely to create a more complicated framework in exchange.
> That's exactly how Bootstrap's classes for lists work. And they are tied to the DOM structure, though not necessarily to particular elements: .my-list has to go on a container element, and .my-list__item has to go onto children of that element.
Not quite exactly. My solution doesn't require list items to be child elements of the list. Bootstrap's "list item" needs (by definition/rule) to be a "direct" descendant - a child element of a given type (a selector with "> li") of the list. They have classes for lists, and then style the list items via element and "descendancy" (i.e. .my-list > li).
If somewhere along the way you decide/are asked to change the mark-up in order to have an element for grouping list items (so, you'd have elements between the list and list items ), Bootstrap's way of creating rules wouldn't work anymore - list items wouldn't be child elements of the list, despite you wanting to keep the styling in them. Independently of how you solved this in the mark-up, if your rule was like Bootstrap's .my-list > li, then it wouldn't work anymore because list-items wouldn't be "direct" descendants of .my-list.
This might seem minor or unusual, but I assure it's not - this is the kind of changes in structure that happen very frequently and make DOM-tied CSS fail. And bear in mind the Tetris effect on this: your less-than-experienced team member might solve this with yet another rule, but a even more specific one (.my-list > .group > li) which will yield harder to maintain CSS (this rule is very specific; it would need even more specific rules to be overridden when necessary). If your development rule was "no DOM tying; just use classes), the problem of escalating specificity would've also been avoided.
> The point I was trying to make was that at a component level, your CSS classes are usually going to depend on a particular hierarchy in the DOM elements that the classes are applied to, or they won't work correctly. How much of a dependency you have is a tradeoff; you can design your framework to minimize the dependency, but you're likely to create a more complicated framework in exchange.
I understand your point, but I don't agree with the notion that "but you're likely to create a more complicated framework in exchange" by minimizing the dependency on the DOM. You're likely, definitely, to create a more verbose CSS framework, with a way bigger amount of classes. But I don't think this is the same as complicated; it's more verbose, it may require you to write more code[1], but I think it's very predictable and easier to follow by team members with different expertise levels.
P.S. Also, bear in mind that BEM-like solutions also have hierarchy. Elements which belong to blocks. They just don't depend on a specific hierarchy on the DOM; DOM hierarchy is independent of styling hierarchy.
[1] I'd argue it will make you write more code in the beginning. Traditional DOM-tied styling will eventually catch-up and the code you have to write to overwrite "over-specific" selectors and similar issues will grow bigger.
I don't know if reading the source code is enough, but if you try incorporating it in projects, it's easier to see how well SCSS works in practice. I really enjoy how Bootstrap sets up conventions for typography and other variables:
There's global variables for serif, sans-serif, and mono...When prototyping a site, I sometimes change my mind over whether or not to use serif or sans-serif...with SCSS, it's a matter of just switching $font-family-base to either $font-family-serif or $font-family-sans-serif:
I usually set a $font-family-headings variable if I decide to use a third font for headings. All font-family names are set in this file and I never have to refer to them explicitly in any of my other CSS.
The elegance of setting a base font size and then having h1-h6 be multiples of that number is also a delightful convenience. And this is just the bare minimum of ways that SCSS can aid in composability...though to be honest...besides variables and the ability to nest definitions within each other...I don't habitually use all of the other really nice features, yet.
Not exactly, it's something I've been noticing from my experience with CSS and many teams with many members which were experienced programmers but without any CSS experience.
P.S. A good heuristic I'd like to point out (and hard-code in any CSS newbie's brain) is that if you're relying on DOM structure (e.g. styling X if he is a descendant or sibling of Y), then you're doing it wrong. Very, very few exceptions to this. Structure (HTML) is a different concern than styling (CSS) and it might change frequently; it should have minimal impact on styling.
P.P.S. Another good notion is that CSS is truly like Tetris. Errors do pile up. If you are over-specific when defining a selector, soon you'll have to do a even-more-specific one to override it. If you are too confident and define a leaky rule (e.g. all `<p>` elements inside a given widget), soon you'll have to create code to override it.
is that if you're relying on DOM structure (e.g. styling X if he is a descendant or sibling of Y), then you're doing it wrong.
Actually this is the way to do it without going overboard with it. Even UI frameworks like Boostrap or Foundation rely on this convention to style elements on the page.
Littering the HTML markup with classes all over the place for the illusion of "loose coupling" between the CSS and HTML is an anti-pattern and counter-productive.
You just need to use classes when appropriate and necessary and then rely on the inherent and predictable relations between HTML elements to supply styling information and close the deal.
I'd rather litter the markup with classes and then be able to change their order and location in the DOM without affecting styles than having to do changes both in HTML in CSS files - bear in mind that, with DOM dependency, most style changes would imply you to change or at least check the HTML file. It will also make you end up "plugging" exceptions on top of exceptions - element X looks like A when he's a child of Y, but then it will have to look like B when he's a descendant of Z (something common with a page-level class, for instance). This is way safer and maintainable with BEM-like modifiers.
I'd say that waiting for "inherent and predictable relations between DOM elements" is a disaster waiting to happen. Of course, there are exceptions (the table mark-up and table styles might be coupled, I guess), but you should try to avoid it.
If you're looking to improve the CSS you end up writing - I highly suggest considering BEM [0]. It stands for block, element, modifier and defines a fairly rigid structure to build components with.
tl;dr: It promotes extremely simple, component based/modular css that is _trivial_ to refactor with confidence unexpected regressions won't pop up.
I'm primarily a backend engineer, but I do full-stack work, especially in my free time, and after seeing it used by our front-end devs at work I decided to try it on my own project - and for the first time ever, I felt like the CSS I was writing actually made logical sense in the same way any program I'd write makes logical sense. Adding constraints is majorly helpful when your language has hundreds of virtually equivalent ways (or at least seemingly equivalent) of doing the same thing - it's just setting yourself up for confusion later.
With or without any sort of preprocessor, BEM is still crazy beneficial if you have a codebase with many people touching the styles, it -
a.) promotes good css practices by limiting the usage of entirely un-necessary slow css selectors because they'd require convention to be broken (and then caught easily in a code review)
b.) promotes extremely DRY components
c.) defines a very simple yet specific way of handling style variations that make DRY component variants (eg a button component could have a red, green or blue modifier) obvious to everyone on the team in a way almost analogous to a primitive in a programming language -- most codebases don't otherwise have a defined pattern for this leading a lot of wheel reinvention and extra complexity which in turns breeds more complexity, leading to truly disgusting css.
Of course there are downsides, by putting limits on a language some things will necessarily become more difficult/complex to accomplish, but I personally find the benefits far outweigh this.
Additionally, I'm not sure how it works trying to integrate it into a mature codebase - I could see that being a challenge for some projects/CSS code styles, but I've not done that so can't speak from more than speculation.
No matter how good you are now, your code when you've spent a year with a framework will be better. Consequently you should pick a framework (or language, or tool) and stick with it until you actually have a good reason to move on to something else. The benefits of jumping to whatever someone else recommends because they claim their choice is better for X, Y and Z reasons are likely less than the benefit of your own experience with a framework you've learned and understand.
90% of the speed of your code in terms of both writing and execution are a function of how well you write it, not the libraries you're using. Writing better code comes from practising (and thinking).
To be honest, I think the person who has spent a year with a framework and who is ok to use it on a day-to-day basis won't simply trust a random guide in a random blog.
I'm unique in that I've never done any web development whatsoever (all my work is in finance and HPC), so I know zero Javascript, no CSS, and only the most rudimentary HTML. This article reminds me why I stay away from the web dev space.
I love it. It wasn't even that long ago that I used to spend countless hours building everything with the sliding doors method and doing weird hacks to make things work in IE6 or (gasp) IE5. There was a lot less to know, and things were certainly simpler back then, but it was also extremely tedious.
Nowadays I can focus my effort on problems that are actually interesting. There's been an explosion, and with the variety, things have gotten complexed. I understand that it can be cumbersome to those entering the field, and a lot of the time it's total overkill for the problem. But... once you get over the hump, there's now a lot of really cool shit you can do on the web that was completely unrealistic or unimaginable just a few years ago.
Do you not find that you spend far more time now wrangling with new implementations of new frameworks for new concepts, only to discover later that you should've researched more, because you have a problem which an even newer implementation of a newer concept has solved and blah blah blah. The amount of time I've wasted in my life learning things to keep up with Web dev trends...
Frameworks are great, but you have to spend a lot of time wading through the documentation and architecture. Why this is different than that framework and why this does something different than that framework, and why this framework solves something this other framework fucks up.
For a time I just started putting together my own stuff and then realized it was so custom, it was totally useless outside of a particular project. I've come around a little bit, but its frustrating when the whole industry jumps on a bandwagon, promotes the shit out of it and then some time later, they're onto something else and the cycle repeats itself.
The best example for this is Backbone.
It was one of the first JS frameworks I started fooling around with, along with Node and Express. Everybody thought this was the greatest thing ever. Now, less than a year or so after I first started dabbling with it, you can't find anybody still talking about it (even though its still a rock solid framework). Everything is now Angular, React and various other shiny toys. I would say the same thing about Knockout. People thought this was the next big thing, and now I can't find anybody promoting it anymore.
Yes, but none of this is really specific to web development. It's just the nature of being a technologist.
It's really a balancing act of picking the latest and greatest vs. picking the tried and tested. No one wants to learn something that'll be useless in a year. Alternatively if you forego learning anything new then you'll miss out on technologies that can actually help you.
For me, I don't really view learning things as wasted time. Even if I don't use some technology I learned a year or two ago, there's plenty of valuable lessons that can be learned from why things didn't work out.
It would get frustrating if I were learning all the wrong things all the time. So, I focus on the things that genuinely get me excited followed shortly by new technology that isn't completely fresh.
Because sometimes these developments are sensible and change industry "best practice". I cringe terribly thinking back on some of the code I've written using methods which were acceptable at the time, and if I didn't keep up with trends to some extent, I'd still be writing code like that.
I pretty much wanted to write this post, and I'm a primarily frontend developer - the tooling required just increases in insanity.
I yearn for the day a lot of this machinery can be tossed out & we can focus more on code/architecture. I've yet to meet a frontend developer who liked working with build tooling.
This is something I've struggled with... most of the stuff I do is in JavaScript and I think the web is cool, but I hate most modern bloated websites and prefer simple text-based ones (like HN!).
It's good for the profession and practitioners over the long run as it raises the barrier to entry for the field rendering it more difficult for non-skilled persons to fake proficiency and thus casting a shadow over others who strive for excellence and quality in their work.
It's in our best answer for front-end web development to be viewed as a field that attracts highly-skilled professionals and not a past-time for hacks or amateurs.
I'm surprised that the "nothing complex / hack up a quick prototype" recommendation is Angular. I get that it's powerful, but there's so much deep magic inside angular [1] that I find even simple stuff takes significant forethought and wrangling.
As a substitute, why not Ractive.js? It's simple and does what you'd expect. You put
In my experience, those people who have tried it as a framework for "some web-related stuff we need urgently" find Angular really attractive.
When they need to dive deep in the magic they just hire a consultant...
I can confirm that the explosion of package managers (npm/bower), task runners (gulp/grunt), UI frameworks (foundation/bootstrap/skeleton), pre-processors (sass/less), JS frameworks (...), etc., that you can waste entirely too much time deciding between them.
As an aside, I've been working on a project that uses Angular 1.3, and I'm not entirely sold yet. I do like that modules are usually contained, but the dependencies are hard to reason about (plus there's all the black magic I'm convinced they had to use to get this to work). Everything about the application feels sluggish, because there's a ton of other JS frameworks being pulled in. So whatever you do, don't mix and match 10 of them. It's painful as a user
After reading the article I think what the author meant is: How to get even more confused with the insane plethora of Front End stuff out there and give up life.
But I can't blame him. I've also tried to create lists, to reason it all. Several times, and to no avail. One thing he got right, an image at the very beginning with the word chaos in the middle.
Cringing was my main reaction too, but it was more about the use of the "all the things" meme and the "kitchen sink" advice.
Clearly the author is a very smart guy, but he seems to be in early-career discovery mode. What I want my early-career developers to learn is to be great at one or two core things, not to throw a dozen hot new tools at every problem.
Yeah. It kind of reminds me of photography: when people just get into it, they tend to be obsessed with all the different gear, until 20 years later they are content with a simple manual view-finder camera.
Rather than evaluate every framework under the sun to try and find the one that's perfect for your specific situation and needs, I would probably focus on finding something that's widespread, well-documented, has a lot of momentum behind it, and an active community. Right now that would probably be React or Meteor.
Seems odd to include Meteor, which is pretty controversial and might never take off, but not Angular, which has much, much higher usage than both of those two combined.
> Language Checklist
>
> When you have answered those high-level questions, it's a good time to talk to your teammates and pick up a language!
No, No and No.
Please, just use something that's as close to plain javascript as possible. Your client will thank you because you don't have to reinvent wheels for the sake of programmer porn...
The way I chose in the past. Use a jobsite (in my case www.cwjobs.co.uk). Type in framework. Count number of jobs. If one is significantly bigger in the job market, this gives me more flexibility and job security going forward.
This has resulted in me going with AngularJS as there are 7-10 times the number of jobs advertised vs other frameworks.
My current role also uses typescript and was using it before the Ang 2 announcement. I do watch where the various technologies are going within the whole stack.
I recently tried to explain my setup to a friend and realized this is getting out of hand. I like the do one thing/pluggable UNIX philosophy as much as anyone, but saying "Typescript,tslint,gulp,jspm,Karma,mocha,chai,sinon,nightwatch,stylus,stylint,istanbul,react,skeleton,jsx,editorConfig,babel,Cordova" makes your head spin. Also getting them all to work together and play nice with sourcemaps and gulp tasks is a pain. Just setting up the tooling for the project BECAME the project. Sure it's IDE independent, pluggable and makes for clean development, but next week another thing will be shiny and I'll be doing more boilerplate. sigh
Yes, it can take a while to get things set up. But you really only need it once. I've used the same core gulpfile for at least a year across multiple projects. And when new things pop up that are useful to your workflow you can integrate them pretty easily. To me the benefits far outweigh the cost of learning or at least integrating most build tools and concepts.
React is a library, not a framework. What's your router? What's your model? What's your buildchain, how do you deploy, how do you do ajax requests, etc etc etc?
Facetious comments like this help nobody. There's not a site in the world "just" using react + webpack. And I say this as someone who works with a react and webpack site.. oh and backbone, and gulp, and rsvp, and requirejs, and another 70 lines in package.json.
I find it odd that he didn't include Jade in this long list of tools and technologies of modern web development as it's IMO the best tool hands down out there when it comes to HTML modularization/componentization and I can't imagine now developing websites or even web apps without it in my workflow.
I feel like memes should be left out of serious write ups because if you do it wrong, or if you have an audience who doesn't normally consume memes, you will end up with what happened to me, which is my attention being focused on the wrong place.
Why would you want to include grunt or gulp? Shell scripts do the job just as well and can be run from npm. Bash is streaming, parallel etc etc. You can do everything you want with &, &&, |, and >
My shell scripting skills aren't really that good. I feel that this might be true for most front-end developers. A JS based task runner is nice for me, as a I can harness the language I use on a daily basis (as well as the community with jobs similar to mine). Maybe if I used more bash than JS I would have a different opinion.
Language preferences/fluency aside, I feel that there's much to gain from the JS "hash-based" way of expressing objects which are used as configuration objects (which can be dynamic) in task runners. I'm not aware of an easy alternative to this in shell scripting, but this is probably due to my ignorance on the subject).
Up until recently I would not have agreed with you. However, recently I've skipped on Gulp and Grunt and it has helped me with various things:
* Saves me time so I don't need to figure out why a Gulp/Grunt script is behaving erratically, such as a watch that crashes even though exceptions are being caught for it
* Reduces my development depenencies, which helps with the following two things:
* There's less of a chance that there will be a package that needs to be built that will crash and burn on Windows
* I don't need to download a shit ton of stuff from NPM every time I clone from Git
* Helps me think about my architecture critically as I don't want to do anything too complicated outside of Gulp/Grunt
* I don't need to wait for someone to make a plugin for a test runner
Do I want to deal with writing the code / instructions to:
* Explain how to setup/install the build tools.
* Account for differences in shell env.
* Explain to windows users to get cygwin/whatever, or make a separate set of scripts for them.
No.
Grunt/Gulp have the benefit of having a consistent cross OS package manager (npm), in a language that the coder is likely to be familiar with should they need to tweak it.
It's a testament to how awesome and diverse this field is that you can take two people, both think of themselves as professional programmers, and chances are each will be mystified by what the other person does day to day.