Custom CSS NOT replacing Tailwind CSS Preflight

Hi,

I have a phoenix 1.6.6 app and tailwind 3.6.18 and tailwind css preflight is loading some base styles Preflight - Tailwind CSS

The problem is that my custom css code in app.css is not replacing preflight’s in development. But it works on staging & production. I think my custom css is somehow being loaded before preflight and it should be afterwards — but not sure if this is the problem.

app.css

@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";

<my custom css code>

I think preflight is loaded after @import "tailwindcss/base" so it should be ok. But it isn’t working so I guess I’m missing something. Therefore, how could I make sure my custom css is loaded after preflight?

Or any idea what the problem could be? Thanks!

By the way, I know I can disable tailwind’s preflight — and my custom css works if I do — but I would like to keep it and have custom css to replace a few styles from preflight.

postcss.config.js

module.exports = {
  plugins: {
    "postcss-import": {},
    tailwindcss: {},
    autoprefixer: {},
  }
}

tailwind.config.js

module.exports = {
  mode: 'jit',
  purge: [
    './js/**/*.js',
    '../lib/*_web/**/*.*ex'
  ],
  darkMode: false, // or 'media' or 'class'
  theme: {
    extend: {},
  },
  variants: {
    extend: {},
  },
  plugins: [],
}

Thanks!

I dunno, but my setup works:

@tailwind base;
@tailwind components;
@tailwind utilities;

<my custom css code>

My postcss.config.js

module.exports = {
    plugins: [
        require('tailwindcss/nesting'),
        require('tailwindcss'),
        require('autoprefixer'),
    ],  
};

I think you have to use the @layer base directive for that… Per the documentation:

If you want to add your own default base styles for specific HTML elements, use the @layer directive to add those styles to Tailwind’s base layer.

I think this is also cross-referenced from the docs on the page you posted.
BTW, you can also look at the typography-plugin source code since they do basically the same thing - or open a discussion on the Tailwind repo if that’s the case.

Thank you @derek-zhou and @thiagomajesk for your comments.
I still couldn’t make it work tweaking postcss.config.js or using @layer base.

It seems most custom css is replacing preflight’s, except background-color: transparent; from buttons/submits.
I see on https://github.com/tailwindlabs/tailwindcss/issues/6602 that more people had problems with that.

However, in staging & production does work for me but not in development.
Any idea? Thanks!!

by looking in the tailwindcss documentation, you are able to extend or disable preflight https://tailwindcss.com/docs/preflight

Thanks @odix67 for your comment.

If I disable preflight, it works. However, I’d like to keep it as I use some components from https://tailwindui.com and they rely on the styles of preflight.

By the way, extending preflight doesn’t seem to work either:

app.css

@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";

<other imports>

@layer base {
  button,.button,input[type='button'],input[type='reset'],input[type='submit'] {
    @apply bg-blue-600;
  }
}

<other custom css>

The background-color of my buttons is still transparent as defined by preflight.

Did I miss anything when extending preflight?
Thanks!

Why you insist on:

While all tailwind examples I have seen use the following:

@tailwind base;
@tailwind components;
@tailwind utilities;

@derek-zhou It’s actually a perfectly valid way of using it you are importing multiple files, you can read here why it’s necessary: Using with Preprocessors - Tailwind CSS. I also do this and it shouldn’t be the cause of the problem.

@hectorperez If I may, since this is not an elixir/ phoenix problem I think you should open an issue/ discussion in the tailwind repo, perhaps it’s something that’s already been tracked or discussed. IMHO, your chances of getting better support will increase because there are certainly people more focused on this particular subject over there.

1 Like

Thanks @thiagomajesk.

I asked here because it works in staging & production but not in development so maybe someone here know why.
But I’ll try to ask there too, thanks.

Can you post your CSS build setup for those environments?

@thiagomajesk do you mean the following?

package.json

  ...
  "scripts": {
    "deploy": "NODE_ENV=production tailwindcss --postcss --minify --input=css/app.css --output=../priv/static/assets/app.css; cd .. && mix assets.deploy && rm -f _build/esbuild"
  }

config.exs

config :esbuild,
  version: "0.12.18",
  default: [
    args: ~w(js/app.js --bundle --target=es2016 --outdir=../priv/static/assets),
    cd: Path.expand("../assets", __DIR__),
    env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)}
  ]

In dev.exs I have some watchers that shouldn’t change it:

config :wikir, WikirWeb.Endpoint,
  http: [port: 4000],
  debug_errors: true,
  code_reloader: true,
  check_origin: false,
  watchers: [
    # Start the esbuild watcher by calling Esbuild.install_and_run(:default, args)
    esbuild: {Esbuild, :install_and_run, [:default, ~w(--sourcemap=inline --watch)]},
    npx: [
      "tailwindcss",
      "--input=css/app.css",
      "--output=../priv/static/assets/app.css",
      "--postcss",
      "--watch",
      cd: Path.expand("../assets", __DIR__)
    ]
  ]

Thanks!

By the way, konsalex here recommended me disable preflight and add preflight’s source manually without background-color: transparent;

This is the setup of a a project I’m working on:

package.json scripts:

"scripts": {
    "watch": "npm-run-all --parallel watch:*",
    "deploy": "npm-run-all --parallel deploy:*",
    "watch:stylesheets": "NODE_ENV=development tailwindcss --input=css/app.css --output=../priv/static/css/app.css --postcss --watch",
    "deploy:stylesheets": "NODE_ENV=production tailwindcss --input=css/app.css --output=../priv/static/css/app.css --postcss --minify",
    "watch:static": "cpx 'static/**/*.*' '../priv/static' --verbose --watch",
    "deploy:static": "cpx 'static/**/*.*' '../priv/static' --verbose"
  },

Esbuild config:

config :esbuild,
  version: "0.12.18",
  default: [
    args: ~w(js/app.js --bundle --target=es2017 --outdir=../priv/static/js),
    cd: Path.expand("../assets", __DIR__),
    env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)}
  ]

Watchers config:

watchers: [
    esbuild: {Esbuild, :install_and_run, [:default, ~w(--sourcemap=inline --watch)]},
    npm: ["run", "watch", cd: Path.expand("../assets", __DIR__)]
  ]

Deploy task:

"assets.deploy": [
        "esbuild default --minify",
        "cmd --cd assets npm run deploy",
        "phx.digest"
      ]

Test this setup and see if it helps. One of the main differences from my setup is that I’m still storing everything on “/assets” and then copying to “priv/static”.

@hectorperez BTW, now that I’m recalling I had a similar problem with styles inside directives not getting picked up properly. I can’t repro it right now, but this would definitely be a subject to report on the Tailwind CSS repository. I think since V3 is using Jit as default, no styles are generated at all if they can’t be found, perhaps there’s a thread to pull there.

Hey @hectorperez, I might have found another thing you can try… I’ve upgraded my deps to the latest Tailwindcss version which seems to have fixed the issue I had before with @apply: https://github.com/tailwindlabs/tailwindcss/pull/7232.

Hi @thiagomajesk, thank you for your messages.

I tried your setup — and Tailwind CSS last version — and it’s still not working.

Hey @hectorperez, After publishing my previous comment I noticed a couple of issues with your configuration, for example using the jit and purge options that don’t exist in TailwindCSS V3 anymore. The correct configuration key for that is content. I also made a small repro for you to try which works properly: https://github.com/thiagomajesk/tailwind-repro.

Hi @thiagomajesk, thank you, your repo works!

However, it seems my app has a conflict or something that prevents it from working.

I replaced jit and purge with content and updated some libraries to the versions of your repo but it still doesn’t work in my app.

These are my files now. Maybe I missed something:

app.css

@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";

@import "./custom.css";

custom.css

@layer base {
  button {
    @apply bg-blue-500 hover:bg-blue-300;
  }
}

config

config :esbuild,
  version: "0.14.0",
  default: [
    args: ~w(js/app.js --bundle --target=es2017 --outdir=../priv/static/assets --external:/fonts/* --external:/images/*),
    cd: Path.expand("../assets", __DIR__),
    env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)}
  ]

postcss.config.js

module.exports = {
  plugins: {
    "postcss-import": {},
    "tailwindcss": {},
    "autoprefixer": {},
  },
}

tailwind.config.js

module.exports = {
  content: [
    "./js/**/*.js",
    "./css/**/*.*css",
    "../lib/*_web/**/*.*ex"
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}

dev.exs

config :whatever, WhateverWeb.Endpoint,
  http: [port: 4000],
  debug_errors: true,
  code_reloader: true,
  check_origin: false,
  watchers: [
    # Start the esbuild watcher by calling Esbuild.install_and_run(:default, args)
    esbuild: {Esbuild, :install_and_run, [:default, ~w(--sourcemap=inline --watch)]},
    npm: ["run", "watch", cd: Path.expand("../assets", __DIR__)]
  ]

package.json

{
  "private": "true",
  "devDependencies": {
    "autoprefixer": "^10.4.2",
    "postcss": "^8.4.6",
    "postcss-import": "^14.0.2",
    "tailwindcss": "^3.0.18",
    "alpinejs": "^3.4.2",
    "topbar": "^0.1.3"
  },
  "scripts": {
    "deploy": "NODE_ENV=production tailwindcss --postcss --minify --input=css/app.css --output=../priv/static/assets/app.css; cd .. && mix assets.deploy && rm -f _build/esbuild",
    "watch": "NODE_ENV=development tailwindcss --input=css/app.css --output=../priv/static/assets/app.css --postcss --watch"
  }
}

I also updated esbuild to ~> 0.3 in mix.exs

Thanks!

Have you tried diffing both projects to spot the differences? I think the repro shows that replacing the preflight defaults is indeed possible, so there’s no problem with Phoenix or Tailwind CSS setup.
So, if the repro works and your app still doesn’t, check that everything is properly configured and that should be it. Unfortunately, there’s not much I can do to help you further than that, sorry :wink:.

@thiagomajesk I’ve tried diffing individual a few files.

Don’t worry, I’ll investigate a bit more and if I don’t find why it’s failing I’ll do [1] for now.
Thank you for all your help!

[1]