Page MenuHomePhabricator

Set up and configure Less & PostCSS for Codex
Closed, ResolvedPublic

Description

The WMF/WMDE task force decided to move forward with PostCSS as our primary styling tool for "Code", our new component library. Now that we have decided on tooling, work can proceed to set up and configure styles in the new library.

Update 2021-11-01
Due to findings since our decision about shortcomings of PostCSS plugin system in connection with the future CSS spec changes (exemplified on [[ https://www.xanthir.com/b4o00 | removal of @apply for native CSS mixins ]]), we've decided to moving forward with a Less & PostCSS combination, trying to be as close as it reasonably makes sense to future standards CSS. So limiting using Less to the absolutely needed functionality.


Acceptance criteria

  • Syntax should align with the future CSS spec as much as possible (we will consider using postcss-plugin-env for this purpose)
  • Final output should strip out things like root declarations and custom properties; var() references should be replaced with actual values; redundant/non-usable code should not be shipped
  • CSS should support certain legacy browsers (so that fallback / server-rendered elements display correctly even without JS) -see T293290

Below is the original set of pros/cons for the different tools that were considered (for historical reference)


At the Vue.js developer summit, we discussed this topic and did not reach a conclusion (see T286951). We need to revisit the pros and cons and decide on a path forward.

OptionProsConsNotes
LessUsed in MediaWiki core, widely used at WMF. Would offer consistency with core and many extensions/skins.Much less widely than Sass used outside of MediaWiki/WMFLess was historically chosen by WMF because of its superior PHP implementation. Similar syntax and features as Sass.
SassMuch more widely used globally than Less (meaning easier onboarding for new designers/devs), used in WMDE projects, useful features like @extend and logical programming support (see Santhosh's comment)Would require core developers/WMF to use two slightly different pre-processors (potential for errors/higher cognitive overhead)Similar syntax and features as Less
Native CSS (with PostCSS)Close to future CSS standards. Removes the need for a pre-processor (which may be more future-proof), PostCSS is extremely customizable and much faster than Sass and Less. AutoPrefixer supportParadigm shift for developers who are used to pre-processors, lots of PostCSS configuration and plugins needed, plugins needed for functionality that doesn't exist in native CSS yetPostCSS will likely be used with any of these options for things like autoprefixing, but that it would be an absolute requirement with native CSS to transform new CSS features for browsers that don't yet support them

Event Timeline

Comments are welcome here, and please feel free to correct me or suggest additions to the pro/con table. I've never written modern, native CSS with PostCSS processing, so my thoughts there are just based on some research and not experience.

I'm pretty okay with any of these options. I think using Sass would be a little annoying for MediaWiki core/WMF developers since we'd have to keep two sets of very similar syntax straight, but I'm willing to deal with that if others feel strongly about using Sass due to its significantly higher popularity.

I also worry that native CSS isn't quite there yet due to lack of equivalent features and instability of new specs, but the most critical features (variables, nesting, and slightly sub-par mixins) are available.

AnneT updated the task description. (Show Details)

Comments are welcome here, and please feel free to correct me or suggest additions to the pro/con table. I've never written modern, native CSS with PostCSS processing, so my thoughts there are just based on some research and not experience.

I'm pretty okay with any of these options. I think using Sass would be a little annoying for MediaWiki core/WMF developers since we'd have to keep two sets of very similar syntax straight, but I'm willing to deal with that if others feel strongly about using Sass due to its significantly higher popularity.

(I have absolutely no experience with Sass) I know that WVUI currently uses some variables from WikimediaUI-Base which has css and less variables, would this mean we also have to add sass variables?

Personally I would prefer to use less because its used elsewhere in MediaWiki and means developers don't have to learn yet another syntax, plus it would make it easier to test shared components in extensions (patches like https://gerrit.wikimedia.org/r/c/mediawiki/extensions/GlobalWatchlist/+/713509 where I copied the then-unmerged ProgressBar from my WVUI patch to GlobalWatchlist to see a demo of it on patchdemo) without needing to switch between Sass and LESS, though I'll admit that's a fairly minor benefit.

PostCSS will likely be used with any of these options for things like autoprefixing, but that it would be an absolute requirement with native CSS to transform new CSS features for browsers that don't yet support them

If we're going to need PostCSS anyway, should we just try to rely on that for all of our needs without introducing a hard dependency on another specific preprocessor? I think both LESS and SASS are starting to become legacy technologies the same way that Coffeescript did; if we rely on PostCSS plugins and limit ourselves to features that are part of the spec we may be able to gradually remove plugins over time. We could rely on the preset-env plugin to do this.

Another advantage of PostCSS is that we could export things like custom properties (variables) to JS or JSON files for use in platform-agnostic design tokens.

Also, I think that PostCSS is the "happy path" for css pre-processing in Vite: https://vitejs.dev/guide/features.html#css-pre-processors

From the Vite docs:

Because Vite targets modern browsers only, it is recommended to use native CSS variables with PostCSS plugins that implement CSSWG drafts (e.g. postcss-nesting) and author plain, future-standards-compliant CSS.
That said, Vite does provide built-in support for .scss, .sass, .less, .styl and .stylus files. There is no need to install Vite-specific plugins for them, but the corresponding pre-processor itself must be installed:

Final thought – WVUI did rely on WikimediaUI-base (which is in LESS), but if those styles were themselves defined using PostCSS, we could have a library of universal design tokens that could be used across various platforms (web, Android, iOS, etc).

I think the shared library could provide us with a place to experiment with some of this new technology outside of MediaWiki, but over time we may want to introduce some of this into other parts of our ecosystem.

I also think postcss is the futureproof option here.

@AnneT In the compatison table, about SASS,one powerful and unique feature of SASS is, it has functions, loops and such logical programming support. One use of that is to to write functions to generate grids, or spacing permutations based on lgical properties(LTR, RTL support), CSS utitliy function generation, viewport unit based spacing classes etc. In Section translation we have used this features(Examples: 1, 2, 3 ). But there are alternate ways to achieve the same using postcss and plugins.

Thanks, @santhosh, I've updated the table to reflect that

I spent some time last week working on a demo tabbed UI component. I wanted to get a feel for how Vue 3, the composition API, Vite, and new tools like PostCSS could work in the context of the new component library we're getting ready to build.

It was pretty easy to achieve a basic PostCSS setup that provides support for autoprefixing, custom properties (aka CSS variables) and SASS-style nesting. I've also configured the project to strip out all variables after converting them into static values and to remove all :root instances from the output.

Configuration looks like this:

postcss.config.js
const customProperties = require( 'postcss-custom-properties' );
module.exports = {
	plugins: [
		require( 'autoprefixer' ),
		// there is also another plugin, postcss-nesting, that implements the CSS Nesting spec exactly
		require( 'postcss-nested' ),
		customProperties( { preserve: false } ),
		require( 'postcss-remove-root' )
	]
};

Vite picks up this configuration automatically (postcss must still be added as a dev dependency in addition to the plugins above).

With this configuration, you can write styles inside of your vue components like this (VSCode highlights all syntax correctly with lang=postcss, although phabricator does not):

<style lang="postcss">
/* Import the CSS variables from Wikimedia UI Base */
@import 'wikimedia-ui-base/wikimedia-ui-base.css';

.my-component {
	&__header {
		align-items: flex-end;
		box-shadow: inset 0 -1px 0 0 var(--border-color-base);
		display: flex;
		justify-content: space-between;
	}
	&__body {
		padding: var(--padding-base);
	}
}
</style>

Vite can compile all styles from all components into a single stylesheet for the project. Final output of the above rules looks like this:

output.css
.my-component__header {
	align-items: flex-end;
	box-shadow: inset 0 -1px 0 0 #a2a9b1;
	display: flex;
	justify-content: space-between;
}

.my-component__body {
	padding: 5px 12px;
}

No additional unused rules or variables from the imported stylesheet make their way into the output.

Obviously this is a very simple configuration, but I think we could easily add more features if we needed them. I was pleasantly surprised how much things "just worked" using Vite here.

TLDR; I think PostCSS can do everything we need. LESS is not as widely-used these days, and node-sass is deprecated; PostCSS seems to be rapidly becoming the standard here.

The task description already mentions it, but PostCSS also comes with AutoPrefixer support, a functionality that is simplifying our mixins needs to only functional and not browser support mixins anymore. A big advantage.

WVUI is already using Autoprefixer with Less.

Wikit is already using Autoprefixer with PostCSS and Sass.
Additionally it uses

egardner renamed this task from Choose a CSS pre- or post-processor for the library to Set up and configure PostCSS for Codex.Oct 12 2021, 6:27 PM
egardner claimed this task.
egardner added a project: Codex.

Change 730354 had a related patch set uploaded (by Eric Gardner; author: Eric Gardner):

[design/codex@main] [WIP] Set up and configure PostCSS

https://gerrit.wikimedia.org/r/730354

Change 730358 had a related patch set uploaded (by Eric Gardner; author: Eric Gardner):

[design/codex@main] Configure postcss-preset-env

https://gerrit.wikimedia.org/r/730358

Change 730354 merged by jenkins-bot:

[design/codex@main] Add wikimedia-ui-base vars and Button styles

https://gerrit.wikimedia.org/r/730354

Change 730358 merged by jenkins-bot:

[design/codex@main] build: Configure 'postcss-preset-env'

https://gerrit.wikimedia.org/r/730358

egardner updated the task description. (Show Details)

Update on this:

Per some of the discussion on this patch, we're re-evaluating whether we are better off just sticking with LESS here. Now that we have tried to use PostCSS for a while, there are a couple issues:

  1. We had hoped to rely on the future CSS spec for some of the advanced features we need. But the spec has been somewhat disappointing here. The CSS nesting spec won't support selector expansion (&__header, etc); @apply (the answer to LESS/SASS mixins) has been abandoned, etc.
  2. There are alternate PostCSS plugins which do implement the behavior we want (postcss-nested for example), but now we are writing CSS that will never be 100% native; instead we are relying on our own custom setup which any contributors will need to familiarize themselves with, etc.
  3. In some cases we may need to rely on non-official PostCSS plugins (maintained by an individual developer, etc) for needed functionality, which is not ideal.

Do these drawbacks justify returning to LESS? The advantages: a single set of rules to learn (rather than our own custom setup), active developer community, compatible with the rest of MediaWiki.

Due to the issues listed by Eric above, and the fact that Less will make it easier to theme server-rendered components in the future, we have a proposed patch for reverting back to Less. Feedback is welcome!

Change 734404 had a related patch set uploaded (by Anne Tomasevich; author: Anne Tomasevich):

[design/codex@main] Write styles in Less instead of PostCSS

https://gerrit.wikimedia.org/r/734404

Not using postCSS has an impact on script bidirectionality support. PostCSS has better implementation of upcoming logical properties in CSS. If we are not using that we will need our own ways to implement bidirectionality. See my comment above.

From my perspective, it's important to state that we've got a reliable path forward, that might prevent us from facing burdensome and time-consuming unchartered territory. Using Less and for certain parts PostCSS, where future CSS syntax is technically well supported or functionality for better developer experience is gained. WiKit does already do the same with Sass & PostCSS (for Autoprefixer).

Would recommend to move gradually to PostCSS over time, instead of our original take of using it exclusively now. As we've already stated in the developer summit and the task force, the syntax differences between Less and Sass are neglible.

Change 734404 merged by jenkins-bot:

[design/codex@main] Write styles in Less instead of PostCSS

https://gerrit.wikimedia.org/r/734404

Volker_E renamed this task from Set up and configure PostCSS for Codex to Set up and configure Less & PostCSS for Codex.Nov 4 2021, 7:27 PM
Volker_E updated the task description. (Show Details)

Closing this since Less has been implemented.

@santhosh thanks for your comments on handling bidirectionality: I'm going to open some tasks soon to cover supporting RTL/bidirectionality in the library and will tag you there.