tailwindlabs / discuss

A place to ask questions, get help, or share what you've built with Tailwind CSS.
MIT License
171 stars 9 forks source link

`@apply` cannot be used with .mt-8 because .mt-8 either does not exist, or it's actual definition includes a pseudo-class like :hover, :active, etc. #71

Closed denjaland closed 7 years ago

denjaland commented 7 years ago

Hi,

First of all - great work on the project. Looking forward to using this, and replacing our old bootstrap based CSS.

I was trying to do the following:

h1, h2, h3, h4, h5, h6 {
    @apply .mt-8;
}

but when I compile (using Laravel Mix), I'm getting the following error:

`@apply` cannot be used with .mt-8 because .mt-8 either does not exist, or it's actual definition includes a pseudo-class like :hover, :active, etc.

How can I apply margins to my headings without having to add classes to all headings?
I agree that most items we can simply apply utility classes, but someting such as h tags would be something I would like to apply the classes to throughout the project :-)

denjaland commented 7 years ago

Just wanted to add that I'm getting the same error, even when using the example from the docs:

.btn {
    @apply .font-bold .py-2 .px-4 .rounded;
}

results in the error

ERROR in ./resources/assets/tailwind/app.css
Module build failed: ModuleBuildError: Module build failed: Syntax Error 

(2:5) `@apply` cannot be used with .font-bold because .font-bold either does not exist, or it's actual definition includes a pseudo-class like :hover, :active, etc.

  1 | .btn {
> 2 |     @apply .font-bold .py-2 .px-4 .rounded;
    |     ^
  3 | }
adamwathan commented 7 years ago

Can you share the whole file? It sounds like Tailwind’s utilities are not being imported into your source file. Are you using a preprocessor like Less or Sass or just plain CSS? If just plain CSS are you trying to use imports but not using postcss-import? On Sat, Nov 25, 2017 at 10:22 AM David Heremans notifications@github.com wrote:

Just wanted to add that I'm getting the same error, even when using the example from the docs:

.btn { @apply .font-bold .py-2 .px-4 .rounded; }

results in the error

ERROR in ./resources/assets/tailwind/app.css Module build failed: ModuleBuildError: Module build failed: Syntax Error

(2:5) @apply cannot be used with .font-bold because .font-bold either does not exist, or it's actual definition includes a pseudo-class like :hover, :active, etc.

1 | .btn {

2 | @apply .font-bold .py-2 .px-4 .rounded; | ^ 3 | }

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/tailwindcss/discuss/issues/71#issuecomment-346946866, or mute the thread https://github.com/notifications/unsubscribe-auth/AEH3bGZ5pDyjl8VJH0_6BBQYPUVmhpRzks5s6DCigaJpZM4QqcfN .

denjaland commented 7 years ago

Hi @adamwathan,

Thanks for your response. In all honesty, everything related to compilation of javascript and css assets is a bit of a blur to me, so thank you for helping me out.

Either way; this is what I have.

package.json (needs to be cleaned up, especially with regards to moving dependencies to devDependencies, but just pasting what we have now...

{
  "private": true,
  "scripts": {
    "dev": "NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "production": "NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
  },
  "devDependencies": {
    "bootstrap-sass": "^3.3.7",
    "gulp": "^3.9.1",
    "jquery": "^3.1.1",
    "laravel-mix": "^1.6.1",
    "locutus": "^2.0.5",
    "lodash": "^4.17.4",
    "node-sass": "^4.7.2",
    "purifycss-webpack": "^0.7.0",
    "tailwindcss": "^0.2.2",
    "vue-progressbar": "^0.7.0",
    "webpack": "^3.8.1"
  },
  "dependencies": {
    "axios": "^0.17.1",
    "babel-preset-es2015": "^6.24.1",
    "clientjs": "^0.1.11",
    "css-loader": "^0.28.7",
    "i18n-iso-countries": "^2.1.1",
    "js-md5": "^0.6.1",
    "laravel-echo": "^1.3.1",
    "purify-css": "^1.2.5",
    "pusher-js": "^4.2.1",
    "sass-loader": "^6.0.6",
    "scss-loader": "0.0.1",
    "sweet-modal-vue": "^1.1.0",
    "vee-validate": "2.0.0-rc.17",
    "vue": "^2.5.8",
    "vue-cookie": "^1.1.4",
    "vue-i18n": "^5.0.3",
    "vue-js-modal": "^1.3.4",
    "vue-loader": "^13.5.0",
    "vue-password": "0.0.11",
    "vue-resource-progressbar-interceptor": "^1.1.9",
    "vue-router": "^2.8.1",
    "vue-template-compiler": "^2.5.8",
    "vue-toastr": "^2.0.11",
    "vuex": "^3.0.1",
    "yarn": "^1.3.2"
  }
}

webpack.mix.js:

let mix = require('laravel-mix').mix;
var tailwindcss = require('tailwindcss');

mix.options({
        purifyCss: true, // Remove unused CSS selectors.
    })
    .js('resources/assets/js/app.js', 'public/build/js')
    .minify('public/build/js/app.js')
    .extract(['vue'])
    .postCss('resources/assets/tailwind/app.css', 'public/build/tailwind', [
        tailwindcss('./tailwind.js'),
    ])
    .minify('public/build/tailwind/app.css')
    .version([]);

tailwind/app.css

@import "./tailwind-preflight.css";

@import "fonts.css";
@import "animations.css";
@import "typography.css";
@import "components/components.css";

@import "./tailwind-utilities.css";

tailwind-preflight.css:

@tailwind preflight;

tailwind-utilities.css:

@tailwind preflight;

The components file includes the other components, which is currently just the buttons definition for testing:

.btn {
    @apply .font-bold .py-2 .px-4 .rounded;
}

Again - thanks very much for a great community.

adamwathan commented 7 years ago

Awesome ok, so the problem is right now your compiled CSS is just using plain boring CSS imports which won't work with @apply; Tailwind needs to be able to find those classes in the same tree of styles.

So the solution for you is to add postcss-import to your build chain, which will take all of your @import statements and actually inline them.

Run this:

# Using npm
npm install postcss-import

# Or if using yarn
yarn add postcss-import

Then add postcss-import before Tailwind in your webpack.mix.js file:

  let mix = require('laravel-mix').mix;
  var tailwindcss = require('tailwindcss');
+ let atImport = require('postcss-import');

  mix.options({
          purifyCss: true, // Remove unused CSS selectors.
      })
      .js('resources/assets/js/app.js', 'public/build/js')
      .minify('public/build/js/app.js')
      .extract(['vue'])
      .postCss('resources/assets/tailwind/app.css', 'public/build/tailwind', [
+         atImport(),
          tailwindcss('./tailwind.js'),
      ])
      .minify('public/build/tailwind/app.css')
      .version([]);
denjaland commented 7 years ago

Ok - you're brilliant. I understand everything what you're saying. The thing is I always wonder how one can know that this was the issue. It did fix it, so I'm happy again, and will be able to continue migrating my layout to a new template - thanks so much for your assistance - MUCH appreciated!

adamwathan commented 7 years ago

Cool glad that helps!

Yeah you sort of need to have the right mental model of how @apply works to really understand why that would be the problem.

Basically, @apply can only apply classes from inside the same file, because it scans that file looking for a match.

By using postcss-import you are allowing yourself to keep things in separate files, but have everything get flattened into one file before Tailwind actually sees it, so by that time, @apply will work because all of your classes are now in the same file from Tailwind's perspective.

I'll see if I can think of a way to tweak the error messaging to help make that easier to understand, as well as update the documentation for that directive.

denjaland commented 7 years ago

Maybe add some links to an article in your docs for certain errors. VueJS does that too, and it does help you to keep your error concise, but at the same time direct your users to more detailed information :-)

That being said - thanks again for a great product! So far, love it!

denjaland commented 7 years ago

Closing to keep this great repo clean ;-)

koryteg commented 4 years ago

you can keep this closed but for anyone else getting this error. my problem was that we added a tailwind.js file and instead of extending the default theme, we overwrote the existing one. which mean those classes would actually never get created.

the fix here is to extend the theme instead of overwriting it.

eriknyk commented 4 years ago

how this can be fixed in a regular, i.e react app?

I've tried:

//postcss.config.js
const tailwindcss = require('tailwindcss');
const atImport = require('postcss-import');

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

But I'm still getting the related error:

CssSyntaxError: /Users/erik/Projects/webapp/src/styles/tailwind.css:78:3: `@apply` cannot be used with `.focus\:outline-none` because `.focus\:outline-none` either cannot be found, or its actual definition includes a pseudo-selector like :hover, :active, etc. If you're sure that `.focus\:outline-none` exists, make sure that any `@import` statements are being properly processed *before* Tailwind CSS sees your CSS, as `@apply` can only be used for classes in the same CSS tree.

Any help will be appreciated.

adamwathan commented 4 years ago

Hey! This is explained here in the docs:

https://tailwindcss.com/docs/functions-and-directives#apply

It's important to understand that @apply will not work for inlining pseudo-class or responsive variants of another utility. Instead, apply the plain version of that utility into the appropriate pseudo-selector or a new media query:

/* Won't work: */
.btn {
  @apply block bg-red-500;
  @apply hover:bg-blue-500;
  @apply md:inline-block;
}

/* Do this instead: */
.btn {
  @apply block bg-red-500;
}
.btn:hover {
  @apply bg-blue-500;
}
@screen md {
  .btn {
    @apply inline-block;
  }
}
eriknyk commented 4 years ago

Thank you @adamwathan