Using multiple tailwind stylesheets - css

I have three tailwind stylesheets that may be included on a single page. Due to the way they're included, it's not possible to set the import order to manage precedence. Is it possible to tell tailwind or postcss to include another stylesheet, from another package, and produce just one "main" stylesheet?
My project is in a monorepo split into three different packages:
my-app
┕ tailwind.css
account-profile
┕ tailwind.css
ui
┕ tailwind.css
The my-app package is the main application, written in Remix, and it imports the others. The account-profile package provides an interface inside the application to handle account management. The ui package is a component library used by both my-app and account-profile. When you navigate to the account profile in the application, it would load all three tailwind.css stylesheets.
Here's a gist to help explain why including multiple tailwind stylesheets causes problems: https://gist.github.com/WriteLock/10d2f632c9fa66e0d9dedfa291ed2f3a
The div with the lg:block class does not appear as it should because of the order that the stylesheets are imported.
The only solutions I've come up with either do not work or are not sustainable:
#fullhuman/postcss-purgecss - Does not work across packages.
Scoped CSS is experimental and tricky to use. Since the UI library will be used in various places, it wouldn't work for that case.
Manually add any necessary tailwind classes to the safelist in the tailwind config in one of the packages, and skip importing the other two.
Add the content paths for account-profile and ui packages to the tailwind config in my-app, i.e.:
content: [
...,
"../account-profile/**/*.{ts,tsx}$",
"../ui/**/*.{ts,tsx}$"
]

Related

Classes brought from Team A and Team B polluting the same global namespace

I am new to Tailwind CSS but there is something that confuses me.
Let's run a scenario:
Team A
builds a UI component library using TailwindCSS (Button, Forms, Dialog, etc)
publish NPM package where exports index.ts and theme/tailwind.css
Team B
npm install Team A library. Imports theme/tailwind.css into their application main.ts (entry point).
At this point, their main.ts should have
import { Button } from '#team-a/ui`
import '#team-a/ui/theme/tailwind.css` // tailwind classes coming from Team A
import `./theme/main.css` // tailwind CSS global file belonging to Team B
At this point in time, in the <style> tags in the head, we will have classes brought from Team A and Team B, polluting the same global namespace.
How do you get around this issue?
There a few ways to avoid this, but if both teams uses tailwind there should not be any issue. unless you have custom CSS that for example overrides custom properties at the :root.
Regardless here a few ways to avoid clashing CSS styles.
use #layers,
Scope the CSS to apply only to a specific tag and below. This is a tricky one, usually frameworks will handle that, react with CSS modules, angular with view encapsulation, but it is possible with postcss or sass.
Prefix the tailwind config with each team unique string, if they build separated tailwind output CSS.

Suitable library/plugin that removes unused CSS in React

I have been doing some research to find the most suitable CSS library for my React app that would remove (the 96% of my bundle.css) unused CSS.
I realized that most libraries need specific paths to the CSS files to be removed and maybe a whitelist of what should be kept. However, it's trickier in a React app, because there is:
an SCSS file for each custom component
a 3rd party CSS library (antd)
CSS that is runtime-generated
Are there any libraries that allow to do this (hopefully without going through a headache to configure them)?
P.S: I use webpack and mini-css-extract-plugin

CSS modules and rollup - generating separate CSS files ("themes") with same hashes

I'm using CSS Modules (Sass) with rollup on a component library project, which is working well. Each component ends up with a dist folder containing a single JS bundle file, and a corresponding CSS file with the scoped CSS classes so consumers of the component don't have to worry about CSS class name conflicts. All they do is include the JS bundle and the CSS file and everything is great. Yay CSS Modules.
The problem I'm now facing is that some components really need separate "themes" - ideally, separate CSS files, one per theme. So consumers can continue as they've been doing: including the JS bundle, but now choosing which CSS file to include to pick a theme.
I'm not sure how to get this going with CSS modules & rollup, and whether this is even the sort of approach others are taking. From what I can see, rollup always handles bundling things together, whereas I want separate CSS files, all of which get their classes renamed identically during the build phase. That way, if within my JS I refer to styles.myclass, if myclass had gotten renamed to scoped-myclass by CSS modules for the original CSS file, for a second CSS file it would also get the same name.
This would keep consumption of the component extremely simple - just a matter of including a different CSS file.
Any suggestions?
Awfully late, but let me answer this 3 years on. So what I ended up doing was totally detaching the CSS generation step from rollup and relying on the Sass CLI to handle that portion of the build process. It felt a bit klutzy, but I remember it wasn't awfully hard to do and solved the problem I outlined above. I don't believe there was a plain rollup solution at the time, nor do I think there's one today.
However... in my case the whole approach was kinda mistaken. This certainly won't be everyone's scenario, but let me spell it all out because hey it may be useful and it definitely wasn't obvious to me at the time.
This was for an in-house shared component library, where each component and its corresponding CSS was a separate npm package stored in our Artifactory. When it grew, plenty of internal references popped up, e.g. multiple components would reference the Button component, and over time they'd reference different versions of the Buttons component - each of which needed its own properly scoped CSS, unique to that package-version.
So what I found was that by doing it this way - having the CSS generated as part of the npm package dist files - I had to write an additional layer for the consumer applications that would parse their node_modules/ folder for our own internal components and combine all the different CSS files, such as the multiple versions of buttons. e.g. the main application would directly import buttons v1.0.0 in its package.json file, but the Dialog component (also included in the package.json) could include buttons 2.0.0 as its own dependency. For every version of the package, there was a uniquely scoped version of the CSS - so the consuming application HAD to include every version otherwise the styling would be borked.
So all in all, it ended up being way more complex that I wanted. I thought I could make it easier & better with the separate generated themed CSS files as part of the package dist, but it didn't end up that way. If I could revisit that project today, I'd re-examine a solution used by Material UI and others which I kinda poo-poo'd at the time: automatic injection of the CSS into the page by the component JS, rather than generating standalone CSS files which required extra work by the consumer applications to gather up and add to the final webpage. Frankly, now I regard it as the "least crap". There are definite downsides to the injection approach (extra work done on every page render for everyone! Yikes!), but there's no doubt in my mind it hugely simplifies the job of the consumer applications. It's a balancing act, but in 20-20 hindsight I'd lean towards the injection approach. With that, scoping & theming is a different and much simpler problem.
If I got you right, consider looking at SCSS plugin: rollup-plugin-scss. It captures all spare .css files imported in the components, and then processes them through underlying node-sass. The catch is, it seems like you can write a custom callback function that'd handle your CSSs differently based on conditions you throw in.
Based on the example from the plugin's page:
import scss from 'rollup-plugin-scss'
...
export default {
input: 'src/index.tsx',
output: [...],
plugins: [
...
output: function (styles, styleNodes) {
// replace this with conditioned outputs as needed:
writeFileSync('bundle1.css', styles)
writeFileSync('bundle2.css', styles)
},
]
}

How to distribute CSS via NPM

I'm trying to break up my monolithic React app into reusable parts that can be shared with other projects.
I want to extract some generic components (e.g. Button, Header, Dropdown, etc.) into my own little UI library. The problem I'm running into is how to manage the CSS. Right now, my app just has a single stylesheet that takes care of everything.
These are the solutions I have seen:
Embed the CSS styles for each component in the JS for the component itself (CSS in JS).
import or require the CSS files in the JS for the component and use webpack to bundle the CSS file for you.
I really don't love either option. I understand the appeal of co-locating the styles with the component, but I feel like: a) it clutters the component definition, and b) it fights with how CSS works (no more taking advantage of cascading styles since everything is so tightly scoped to the individual component).
And, I can't bring myself to import a CSS file. That just feels so wrong. We're not even writing javascript anymore at that point.
I realize that these aren't exactly popular opinions, but is there a 3rd option that I'm missing for getting a good old fashioned CSS file from an NPM module that I can just drop in my HTML and use? Ideally one that doesn't involve copy/pasting it from node_modules. :)
Thanks to the tip from #EmileBergeron I found the PostCSS import plugin. It can find and inline stylesheets in node_modules and in your own code.
So, my workflow will be:
npm install my-ui-library
Import the React components you want to use into your JS files import { Button } from 'my-ui-library'
Import the corresponding stylesheets into your CSS files #import 'my-ui-library/Button.css'
That way I'm importing CSS into CSS and JS into JS which feels a lot more natural to me. It might also make sense to just have one stylesheet for all components instead of breaking it up per-component, but that's a detail I can figure out later.
Then, I just need to add PostCSS into my build system to inline everything which has been pretty simple in testing.

AngularJS With Multiple Components and CSS

As I become more familiar with Angular, and the vast number of modules out there for making an application really shine, I am also becoming overwhelmed at understanding the basic logic of CSS overloading, and how to manage the imports to get the desired behavior.
For instance, I have pulled the following libraries into my Angular application; Boostrap, Bootcards, boostrap-select, font-awesome, and some custom bootstrap-wizard libraries for a modal tab-based wizard.
All of these libraries require being defined in the index.html page of my Angular app (both the CSS files the JS files). How do you manage the desired behaviors so that one components styles don't override another components styles? What are the best practices around bringing in multiple components and using them in an Angular app, without negatively affecting the applications previous behaviors?
You have 3 choices:
Place more important CSS files AFTER less important ones so the more important override when both have same attribute names.
Manually go in stylesheet and change attribute names.
Instead of including the stylesheet in index, include it in your html file

Resources