theCrag / website

theCrag.com: Add your voice and help guide the development of the world's largest collaborative rock climbing & bouldering platform
https://www.thecrag.com/
110 stars 8 forks source link

CSS cleanup and re-organise strategy #1587

Closed brendanheywood closed 6 years ago

brendanheywood commented 10 years ago

This will be a medium term ~6-18 months ongoing task, so partially a checklist of things to do, and also a checklist of things to keep doing. Much of this is distilled wisdom from multiple css frameworks.

The motivation is simultaneously keeping the css payload tight, and maintaining it. Rather than periodical audit and cleanup, and then slowly letting it bloat out again.

I want to break apart portal.css into a whole bunch of little .less files to make the authoring simpler and clearer. They will still get served as a single file. As part of this process of breaking apart each component out into it's own file it will highlight what actually is used, and where and how. When a whole component gets removed, it's simple to not @ include a whole component css file and we're done. Much easier to prune dead code.

So we should end up with a 1-1 mapping between less files and mason templates. Eventually I'd like to get to a point where the only classes that a mason template is allowed to use are the ones in it's corresponding less file, and vice versa. Eventually going one step further each component should declare a base class on it's top level element, and ideally all styles hang of it. Not every template will need it's own styles. Going one step further I'd like to phase in a set of simple css guidelines which makes inheritance much easier to deal with.

Example (not done yet): Mason template: /minor/cardClimber Top level element <div class="card-climber"> ... </div> Less file: .../less/cardClimber.less

CSS Guidelines:

It will be easy to knock up some static analysis tools to detect and fix dependencies not being declared right in less based on template use. For instance it would be very easy to say only the styles used by the list view, profile page go into portal.css. Other pages could pull in a secondary style sheet, depends on how small we can get portal.css down to.

scd commented 10 years ago

Awesome, this will sort out so many issues - 18months+ I recon. We should really take our time and do this properly.

Just to make sure, we should also publish the css components so we/others can build badges on external sites.

I will also work on the process.css code.

You alluded to optimisation policy issues with what goes into portal.css. So I agree that we should have a generic portal.css and a specific one for styling which is unique to that page(s).

Example use cases should be documented within the component file.

More thinking out aloud...

What about the components that may have javascript associated with them as well. We should wrap these up in this framework.

We talked about automatic generation of javascript code so that we can generate the equivalent template output on the javascript side of things as well. Are we committed to always doing this via html snippets, or will we want to still do it with javascript occasionally. I think there are advantages of having javascript capability as well, especially for remote sites.

brendanheywood commented 10 years ago

You alluded to optimisation policy issues with what goes into portal.css. So I agree that we should have a generic portal.css and a specific one for styling which is unique to that page(s).

If the numbers say so.

One thing I was thinking about but didn't mention is having a 'critical.css' which imports the components for say the header and primary nav, and that this css is conditionally inlined into the page head rather than referenced. This might sound counter intuitive but getting this into the first 14kb which fits in the first tcp packet means time to first render is really fast. On future page loads it doesn't need to be rendered inline as it is in the cache already. This could be a little tricky so want to tackle it last but could be a big win on mobile.

See: https://developers.google.com/speed/pagespeed/service/PrioritizeCriticalCss

On the topic of splitting off page specific styles, it all comes down to the numbers. There are pros and cons, which depend on the size of the css, the number of selectors, and how often we release. We are still well under the selector limit bug in IE which requires splitting into separate files. We don't release super fast so the caching works quite well. Our css paint performance is ok, it's only the actual download itself which is slow. Turning it from 1 file into 2 would make it worse on some pages. One type of optimisation if we do split is loading the core on synchronously and the second one asynchronously so we get faster above the fold rendering similar to above. But still my gut feeling is that once we rationalise all the components and css we probably don't have a massive imperative to split them apart any more. l'll test this after we've cut it up, but the important thing is that once it is cut up doing stuff like this will be way easier. We could also use static analysis to determine which css components a certain page uses, and which aren't already in the portal.css file and build it accordingly. We could use GA stats and say the top 90% of pages by type should use only one core css file, which might end up being list view, profile, home page, and dashboard, and then all other pages get a secondary css file(s).

The other thing to keep in mind is that while the css is getting bigger and bloated, it isn't the critical bottle neck with page load, this is actually all the JS files and by a very large margin. I want to formulate a similar strategy for how we load and manage JS as well. Eg in list view, which should in theory be our most targeted page, we load 11 of our own scripts, and 22 in total. A lot of the these should be merged into one file, or at least fewer files, or removed completely, or loaded async on demand (like google maps). Some of this is tangled with requireJS + jquery work I've already started but which stalled because of legacy dependency clashes with certain js libs we are using. This needs most thought and prototyping in another issue.

Example use cases should be documented within the component file. Yes it would be really awesome to get an automated element library / style guide happening. Could be easy to knock up some simple comment system in the file for mock data to help build the style guide. It would also show dependencies between components and also show what isn't being referenced.

What about the components that may have javascript associated with them as well. We should wrap these up in this framework. We talked about automatic generation of javascript code so that we can generate the equivalent template output on the javascript side of things as well. Are we committed to always doing this via html snippets, or will we want to still do it with javascript occasionally. I think there are advantages of having javascript capability as well, especially for remote sites.

I think we play this by ear. All of this is guidelines and could be broken for good reasons. There is a growing consensus in the community that any css classes used for styling should not be leveraged for js at all. Part of this is about storing component state or metadata using data-attr, part of it is about being free to change classes and restyle things without potentially breaking js behaviour. This sounds good but happy to make judgements case by case.

On the templating side, I think we err on the side of server side templates, but again use judgement. One technique that is probably really applicable here is using the server side template to renders into a comment, or fake script tag, which is then used by the JS library. This has a lot of advantages like not requiring a JS side compile step, and always being kept in sync. There are a couple ways of doing this right now with deep support, and this is also getting more standardised too, see these for some history / inspiration (skim read in this order): http://ejohn.org/blog/javascript-micro-templating/ https://github.com/BorisMoore/jquery-tmpl http://www.jsviews.com/ http://www.html5rocks.com/en/tutorials/webcomponents/template/

The only time this lets us down is if we have only loaded a js file, for instance on a 3rd party site. But there are plenty of other solutions in this space, like getting that JS to load a page which just returns templates, or by post processing the result of a mason template and compiling that down into the original JS (quite different and much simpler than cross compiling perl into JS)

brendanheywood commented 10 years ago

Another rule, more for myself:

brendanheywood commented 6 years ago

I'm closing this, all the new csss is bem following this scheme so now it's just a gradual migration as we touch things