quasarframework / quasar

Quasar Framework - Build high-performance VueJS user interfaces in record time
https://quasar.dev
MIT License
26.03k stars 3.54k forks source link

Resolve Quasar and Tailwind CSS conflicts #6775

Closed gbouteiller closed 3 years ago

gbouteiller commented 4 years ago

Is your feature request related to a problem? Please describe.

This proposal aims to resolve conflicts between Quasar and TailwindCSS with minimum changes. Currently, Quasar and TailwindCSS offer both useful classes. This post is not to discuss the pros and cons (you can debate here) but to ease the use of TailwindCSS with Quasar for those who want to.

After investigation (with the help of CSS compare and CSS sort), we can divide Quasar class names in 4 categories:

Hopefully, the last category contain only 12 classes in 5 files with few differences:

/* Quasar: flex.styl */
.flex{ display: flex; flex-wrap: wrap }
.order-first { order: -10000 }
.order-last { order: 10000 }
/* TailwindCSS */
.flex { display: flex }
.order-first { order: -9999 }
.order-last { order: 9999 }

/* Quasar: mouse.styl */
.cursor-not-allowed { cursor: not-allowed !important }
.cursor-pointer { cursor: pointer !important }
/* TailwindCSS */
.cursor-not-allowed { cursor: not-allowed }
.cursor-pointer { cursor: pointer }

/* Quasar: size.styl */
.block { display: block !important }
.inline-block { display: inline-block !important }
/* TailwindCSS */
.block { display: block }
.inline-block { display: inline-block }

/* Quasar: typography.styl */
.text-justify { text-align: justify; hyphens: auto }
/* TailwindCSS */
.text-justify { text-align: justify }

/* Quasar: visibility.styl */
.hidden { display: none !important }
.invisible { visibility: hidden !important }
.overflow-auto { overflow: auto !important }
.overflow-hidden { overflow: hidden !important }
/* TailwindCSS */
.hidden { display: none }
.invisible { visibility: hidden }
.overflow-auto { overflow: auto }
.overflow-hidden { overflow: hidden }

You can see that:

I forgot to mention the particular case of colors that have the same problem of !important (the way I deal with them is described below).

Describe the solution you'd like

As a preferred solution and personal taste, it is possible with minimal modifications to change these 12 classes to avoid conflicts. For that, we could:

For colors, a clean solution would be (in the case of !important being not that 'important' but a matter of taste) to offer a property in config to add/remove colors (kind of what it is done with brand).

I would also vote for renaming utility classes that only differ from names to have something really robust but it is not mandatory.

Describe alternatives you've considered

For now, for the 12 classes :

For now, I manage colors in this way :

Additional information

Also, I would like t o mention two other important concepts:

damms005 commented 2 years ago

It is simply because of Tailwind's higher specificity. For example, let's take .flex as an example. By default, Quasar and Tailwind have selectors for .flex, hence, conflicts.

However, when you use Tailwind's important selector prefix, say .tw, then the original .flex becomes .tw .flex. This means that while Quasar applies the CSS flex styles to .flex, you are now implicitly overriding it by applying it to .tw .flex. The link I shared above contained linked to this SO and specifically this comment gives more context to this.

Like I said earlier, this is how I override Quasar's styles with Tailwind's in my codebase.

Cheers!

Tofandel commented 2 years ago

Then I did understand correctly and can give you examples of where it doesn't work

/* Quasar */
.hidden { display: none !important }

/* Tailwind with prefix */
.tw .hidden {
    display: none;
}
@media (min-width: 1024px) {
  .tw .lg\:flex {
    display: flex;
  }
  .tw .lg\:\!flex {
    display: flex !important;
  }
}

When you use the class hidden lg:flex you will see that it doesn't behave as expected and it's always hidden even on a large screen because of the !important in quasar

But if you use hidden lg:!flex then you'll get the correct behavior because you get the !important keyword with tailwind

So while overall it does solve some problems of specifity with flex where !important is not used, it fails to solve the parts where quasar uses !important, but there is a workaround using the exclamation mark on the tailwind classes that are conflicting

damms005 commented 2 years ago

Oh. Nice. Now I get your point!

Perhaps, solving this holistically will still involve the Quasar team allowing seamless integration/use of the framework with other CSS tools, aye?

MarkofChina commented 2 years ago

@gbouteiller thanks for clarifying, you make some excellent points, I think debates like this are of value to see all points of view, and I did just see the other issue with more info, sorry I didn't see that before.

While IMO Tailwind is superfluous when working with Quasar, implementing your suggestions could result in some Tailwind fans using Quasar, so your idea could be a net positive for Quasar in this case.

I can't agree more , what you suggest have brought an end to my confusion , I've loved Tailwind for long time, while unfortunately I am frustrated with it's limitation in components, I don't want to cost too much time on designing Vue component , instead, I would like focus on the backend codes. en... Quasar may have a little more limitation in freely-designing, while Tailwind offers more freedom, but it is worthy to use Quasar only in some projects.

mila76 commented 2 years ago

Simple Unocss example of a preset that can make some quasar utility class

`

theme: {
  colors: {},
  size: {
    xs: '4px',
    sm: '8px',
    md: '16px',
    lg: '24px',
    xl: '48px',
  },
},
rules: [
  ['no-shadow', { 'box-shadow': 'none' }],
  ['q-ma-auto', { margin: 'auto' }],
  ['q-pa-auto', { padding: 'auto' }],
  [/^q-m[xy]-(\d+)$/, ([, d]) => ({ 'margin-left': `${d / 4}rem`, 'margin-right': `${d / 4}rem` })],
  [/^q-ma-(\d+)$/, ([, d]) => ({ margin: `${d / 4}rem` })],
  [/^q-p[xy]-(\d+)$/, ([, d]) => ({ 'padding-left': `${d / 4}rem`, 'padding-right': `${d / 4}rem` })],
  [/^q-pa-(\d+)$/, ([, d]) => ({ padding: `${d / 4}rem` })],
  [
    /^q-p[xy]-(.*)$/,
    ([, c], { theme }) => {
      if (theme.size[c]) return { 'padding-left': theme.size[c], 'padding-right': theme.size[c] };
    },
  ],
  [
    /^q-pa-(.*)$/,
    ([, c], { theme }) => {
      if (theme.size[c]) return { padding: theme.size[c] };
    },
  ],
],

` With this kind of thing and some fix on the quasar main css file we can have some trees hake on the big quasar css. User can even prefix the UI css and swap utility class with other system (windi/tailwind for example)

rowild commented 2 years ago

@mila76 How do you get unocss working in quasar at all? (I mean with the new vite feature of the quasar cli.) Where do you import unocss and define presets and attributify?

mila76 commented 2 years ago

Yes i just do it (my previous test is with the vite plugin only) Here a quick guide: npm i -D unocss quasar new boot unocss in src/boot/unocss.js import "uno.css"; in quasar.config.js boot: ["unocss"] and under build section vitePlugins: [["unocss/vite", {}]]

rowild commented 2 years ago

@mila76 Thank you for your quick response! I tried that, but unocss does not seem to work. At least a standard class like ma4 does not generate any CSS, when looking into Chrome's devTools

I'm also trying to understand how to implement themes(as you post them) and how to activate attributify. I put this in quasar.config.js > build options:

vitePlugins: [
        [
          "@unocss/vite",
          {
            attributify: true
          },
        ],

but nothing happens. This is definitely an error because I nowhere import the preset. But what's the proper way to import

import { presetUno, presetAttributify } from 'unocss'

in Quasar (with Vite)?

Can you help me, please?

mila76 commented 2 years ago

I make a simple repo for you I'm not sure how to fully expand because you can't put inport on config file

rowild commented 2 years ago

@mila76 Signore, sei fantastico, grandioso e molto gentile!!! I create y "my-border" class to check, whether it works - and it does!

Most important question: How can I buy you a coffee??? I didn't find anything! If there is a link where I can do so, please post it or send it to robertwildling@gmail.com - really, please do so!

So many questions, though:

Thank you very much! E prego, prego, prego – mandami il "coffee" link per favore (this is Google translate, sorry if this sounds weird :-))

mila76 commented 2 years ago

update my repo to use Attributify Mode default preset have windi/tailwind import "uno.css" is the main entry for unoCss (view unoCSS docs) where the generated css go

rowild commented 2 years ago

@mila76 Again thank you very much! I learned a lot thanks to you! As mentioned before: Please let me know how I can buy you a coffee!

guilhermeaiolfi commented 2 years ago

Is there a plan about this yet?

mila76 commented 2 years ago

For now i see only this Project

stoem commented 2 years ago

I'm not sure why this issue has been closed as it remains unresolved. It doesn't fill me with confidence that the Quasar team has not resolved this after two years. The use of !important on a class with such a common name as .hidden for example is bound to cause issues and in fact is really bad practice.

And rather than solving the problem you close the issue?

pdanpdan commented 2 years ago

What would be the alternate meaning of .hidden :)

stoem commented 2 years ago

I'm not sure if you're not understanding the point I am making or just pretending that you're not. Nobody is looking for an alternative meaning of hidden but the fact that's it's commonly used in many frameworks and overriding it with !important is bad practice. It's also just one instance of where you've decided to hijack commonly used class names.

We've considered Quasar for our project but after reading the responses on this issue over the cause of 2-3 years it is clear that you have no interest in addressing your bad decisions when it comes to CSS. Closing issue after issue won't help the situation.

guilhermeaiolfi commented 2 years ago

@stoem Unfortunately I have to agree here. I've been using quasar for one year now and everything is great, except theming. I was looking for ways to customize it for some time and none of the workarounds are really acceptable. It is a shame because there are some people who won't even consider quasar because of the material design. I read one of the core developers (I don't remember who exactly) saying that it is just CSS, so it is up for us to change it as we we want. But that's not that easy for reasons already brought up here and other issues. Closing this issue without a solution gives a message (Well, I guess that after 2 years, it is more than a message) that who is responsible for quasar don't care about theming.

prodkt commented 2 years ago

Ooof, is there official word from the quasar team that in fact they will leave things as they are and not attempt to solution a world devs can use tailwind in quasar with no conflicts? In our current project we're heading into styling and this is critical and damming information to us. We would not have ever started with quasar knowing this information. It's very unfortunate given quasars flexibility in multiPlatform and yet have a reverse approach when it comes to the styling. Real shame on them if they haven't started solutioning this.

mila76 commented 2 years ago

I think they working on this problem for the 3.0 version... Fixing now is no different to almost break all current production enviroment

stoem commented 2 years ago

I can find no evidence of that. https://github.com/orgs/quasarframework/projects/2

If a fix is underway then why is this issue closed?

devidw commented 2 years ago

@stoem

There is a task in the project called Explore UnoCSS to power Quasar CSS utility classes.

Quoting the task description:

UnoCSS could help us to

make our CSS helpers swappable with another presets (eg. Tailwind) reduce the overall CSS weight drop q- prefix user custom dynamic extensions


Sidenote: I've worked on projects with both, Quasar and UnoCSS and using UnoCSS as an engine to generate CSS utility classes works fantastic.

stoem commented 2 years ago

This looks promising, thanks!

eqoram commented 1 year ago

Are there any updates on this? On the new roadmap (https://github.com/quasarframework/quasar/blob/dev/ROADMAP.md) there is no v3 mentioned anymore and therefore an implementation of UnoCSS is even more unclear. :)

mila76 commented 1 year ago

I make a discussion here Hope we can make this awesome project even more awesome

Melchyore commented 1 year ago

I used to love Quasar and I suggested it many times over other frameworks to the company I'm working for. However, I'm really disappointed since there's still no news about the V3 which will bring "naked" components and all the work is focused on the new docs that doesn't reflect the true power of Quasar, unfortunately... All the other frameworks have beautiful docs that one can browse while enjoying being and they are offering ways to customize styles...

patforg commented 1 year ago

We've been using Quasar for several years and with Unocss for a year now. It would be nice if all Quasar classes had a prefix like q-hidden this would solve the issue.

In the meantime we work around making our own classes when we have a conflict.

.tw-hidden {
  display: none;
}

Then we use tw-hidden instead of hidden. It's not the prettiest solution but it works.

timsayshey commented 1 year ago

It's 3 years later and I was hoping the option to switch off the default quasar sass would have been supported by now but guess not.

That said I have an update to the replacement solution that supports Vite incase it helps anyone:

npm i vite-plugin-filter-replace
const replace = require('vite-plugin-filter-replace').default;

module.exports = configure(function (/* ctx */) {
  return {
   ...
    build: {
      extendViteConf (viteConf) {
        // Add filter-replace to the plugins array
        viteConf.plugins.push(
          replace([
            {
              filter: /client-entry\.js$/,
              replace: {
                from: "import 'quasar/dist/quasar.sass'",
                to: '',
              },
            },
          ]),
        )
      }
   ...
strife-cloud commented 1 year ago

Hey, bump. I revive the issue because it would be really cool to have Quasar + tailwind working together.

jsonMartin commented 1 year ago

Also looking how to integrate Tailwind and Quasar...

TobyMosque commented 1 year ago

Do u guys tried Vuetiful? https://vuetiful.dev/docs/getting-started

akshay-sood commented 1 year ago

Do u guys tried Vuetiful? https://vuetiful.dev/docs/getting-started

I don't think I can thank you enough for this! 🤩

knighttower commented 1 year ago

Hey, jumping on this a little late, but I think that @patforg nailed it on the solution. I started trying to implement a few Quasar components into other existing projects and noticed that the css classes used in the components conflicts with other classes. For instance, a lot of other frameworks (utility, ui etc.) use the classes [row, col, ml, pl, ...] so when dropping in Quasar component the style of the component will break. Ex. Quasar Editor has a class of "row" in the toolbar, but it conflicts with other utilities that also declared that class, thus braking the toolbar: image

I think that maybe not by default, but as an option, if there was a config section where it would allow to declare a "prefix" of all classes that currently don't have the "q-" to incorporate it, it will help tremendously.

.q-row{
  //...
}

And the benefits will be:

Hope this helps.

alucardsam commented 1 year ago

Hello everyone, I found a different solution for these problems. By reading the tailwindcss docs I discovered how to work with third party libraries. So in my tailwind.css file loaded by the file called quasar.config.js (css: ['app.scss', 'tailwind.css']).

comment1

Add this:

comment2

@tailwind base; @tailwind components; .xyz-hidden { @apply hidden; } @tailwind utilities;

Where the class called .xyz-hidden works like hidden by native class from taildwindcss.

I hope it will be useful.

ZackNew commented 11 months ago

I faced this issue while using it in nuxt js and I saw some helpful comments but this is what i did:

in tailwind config file i added prefix: 't-' and whenever i want to use tailwind classes i prefix them with t-.

for example if i want to use the flex class from tailwind i use class="t-flex" and this will not conflict with quasar flex class.

TheProcedural commented 6 months ago

I faced this issue while using it in nuxt js and I saw some helpful comments but this is what i did:

in tailwind config file i added prefix: 't-' and whenever i want to use tailwind classes i prefix them with t-.

for example if i want to use the flex class from tailwind i use class="t-flex" and this will not conflict with quasar flex class.

I totally missed this feature in Tailwind, thank you very much!

lajuffermans commented 3 months ago

Hey, jumping on this a little late, but I think that @patforg nailed it on the solution. I started trying to implement a few Quasar components into other existing projects and noticed that the css classes used in the components conflicts with other classes. For instance, a lot of other frameworks (utility, ui etc.) use the classes [row, col, ml, pl, ...] so when dropping in Quasar component the style of the component will break. Ex. Quasar Editor has a class of "row" in the toolbar, but it conflicts with other utilities that also declared that class, thus braking the toolbar: image

I think that maybe not by default, but as an option, if there was a config section where it would allow to declare a "prefix" of all classes that currently don't have the "q-" to incorporate it, it will help tremendously.

.q-row{
  //...
}

And the benefits will be:

  • No conflict mode
  • Allows to use only some components as dropins into other existing projects
  • Allows slow migration of projects using other frameworks to Quasar
  • Allows integration of Utility atomic frameworks (like Unocss, etc) to complement/enhance the functionality

Hope this helps.

I like this, maybe optionally? We have similar issues because we created a JS Widget in Quasar, so it's embedded in pages that use Tailwind, Bootstrap etc. "row", "column" as class is way to common.