A utility-first CSS framework for rapid UI development.

  • By Tailwind Labs
  • Last update: Jan 5, 2023
  • Comments: 16

Tailwind CSS Tailwind CSS

A utility-first CSS framework for rapidly building custom user interfaces.

Build Status Total Downloads Latest Release License


For full documentation, visit tailwindcss.com.


For help, discussion about best practices, or any other conversation that would benefit from being searchable:

Discuss Tailwind CSS on GitHub

For casual chit-chat with others using the framework:

Join the Tailwind CSS Discord Server


If you're interested in contributing to Tailwind CSS, please read our contributing docs before submitting a pull request.




  • 1

    TypeError: getProcessedPlugins is not a function

    Describe the problem:

    Upgraded from TailwindCSS 1.9.6 to 2.0.1 for my angular project following the instructions on their website. I had previously used the following guide: https://notiz.dev/blog/angular-10-with-tailwindcss#setup to Install the previous version and that worked before.

    Please see error below:

    ERROR in Module build failed (from ./node_modules/postcss-loader/dist/cjs.js):
    TypeError: getProcessedPlugins is not a function
        at /home/greg/angular-website/frontend/node_modules/tailwindcss/lib/processTailwindFeatures.js:71:83
        at LazyResult.runOnRoot (/home/greg/angular-website/frontend/node_modules/postcss/lib/lazy-result.js:276:16)
        at LazyResult.runAsync (/home/greg/angular-website/frontend/node_modules/postcss/lib/lazy-result.js:328:26)
        at async Object.loader (/home/greg/angular-website/frontend/node_modules/postcss-loader/dist/index.js:94:14)
    ERROR in ./src/styles.scss (./node_modules/css-loader/dist/cjs.js??ref--13-1!./node_modules/@angular-devkit/build-angular/node_modules/postcss-loader/src??embedded!./node_modules/resolve-url-loader??ref--13-3!./node_modules/sass-loader/dist/cjs.js??ref--13-4!./node_modules/postcss-loader/dist/cjs.js??ref--17!./src/styles.scss)
    Module build failed (from ./node_modules/postcss-loader/dist/cjs.js):
    TypeError: getProcessedPlugins is not a function
        at /home/greg/angular-website/frontend/node_modules/tailwindcss/lib/processTailwindFeatures.js:71:83
        at LazyResult.runOnRoot (/home/greg/angular-website/frontend/node_modules/postcss/lib/lazy-result.js:276:16)
        at LazyResult.runAsync (/home/greg/angular-website/frontend/node_modules/postcss/lib/lazy-result.js:328:26)
        at async Object.loader (/home/greg/angular-website/frontend/node_modules/postcss-loader/dist/index.js:94:14)
  • 2

    Custom class name completion contexts

    There has been quite a few requests for the extension to support class name completions in contexts other than a standard class(Name) attribute.

    Some examples:

    I just wanted to consolidate all of these requests into a single issue that can be tracked more easily, as I think the solution could be the same for each of them.

    I am reluctant to hard-code each of these cases into the extension because none of them are "official" methods of using Tailwind, and it may become a maintenance burden.

    However, I am open to the idea of adding a user setting which would allow the definition of custom regular expressions. For example for tailwind-rn your regular expression might be something like: /\btailwind\([^)]+/ig

    If you're interested in this feature feel free to "watch" this issue for updates, and post any comments/suggestions you may have.

  • 3

    Add CSS Grid utilities

    This PR adds support for CSS Grid Layout to Tailwind CSS.

    Here is an example of what it looks like to use these new utilities:

    <div class="grid grid-cols-8 col-gap-6 row-gap-6">
      <div class="col-span-3"></div>
      <div class="col-span-3"></div>
      <div class="col-start-4 col-end-8"></div>
      <div class="col-span-4 col-start-2"></div>
      <div class="col-span-6 col-end-9"></div>

    It adds a new grid value to the display core plugin, as well as provides new core plugins for the following CSS properties:

    • grid-template-columns
    • grid-column-gap
    • grid-column
    • grid-column-start
    • grid-column-end
    • grid-template-rows
    • grid-row-gap
    • grid-row
    • grid-row-start
    • grid-row-end


    These utilities take the form grid-cols-{key} where "key" is any value configured under the gridTemplateColumns key in your theme config.

    By default we provide the necessary values to create basic equal width column grids with up to 12 columns:

    gridTemplateColumns: {
      '1': 'repeat(1, 1fr)',
      '2': 'repeat(2, 1fr)',
      '3': 'repeat(3, 1fr)',
      '4': 'repeat(4, 1fr)',
      '5': 'repeat(5, 1fr)',
      '6': 'repeat(6, 1fr)',
      '7': 'repeat(7, 1fr)',
      '8': 'repeat(8, 1fr)',
      '9': 'repeat(9, 1fr)',
      '10': 'repeat(10, 1fr)',
      '11': 'repeat(11, 1fr)',
      '12': 'repeat(12, 1fr)',

    I've opted to avoid any weird magic here and instead just given the user complete control over the value of this property, so although I'm just using repeat(x, 1fr) here for each value, there's absolutely nothing stopping you from creating something more custom like so:

    gridTemplateColumns: {
      // Would create a class called `grid-cols-header`
      'header': '100px minmax(min-content, 600px) 1fr',

    Providing a basic 12 column grid seemed like the most sensible thing to do by default, as there aren't many other good ideas I can think of that are actually general purpose and not hyper-specific to one site design.


    These utilities take the form col-gap-{key} where "key" is any value configured under the gridColumnGap key in your theme config.

    By default, this uses your spacing config, and therefore matches all of your padding/margin/width/height utilities.


    These utilities take the form col-{key} where "key" is any value configured under the gridColumn key in your theme config.

    By default we only provide values for spanning across columns:

    gridColumn: {
      'span-1': 'span 1 / span 1',
      'span-2': 'span 2 / span 2',
      'span-3': 'span 3 / span 3',
      'span-4': 'span 4 / span 4',
      'span-5': 'span 5 / span 5',
      'span-6': 'span 6 / span 6',
      'span-7': 'span 7 / span 7',
      'span-8': 'span 8 / span 8',
      'span-9': 'span 9 / span 9',
      'span-10': 'span 10 / span 10',
      'span-11': 'span 11 / span 11',
      'span-12': 'span 12 / span 12',

    Again no magic or assumptions here at all — I've included the word span explicitly in each key to make sure the utilities are generated like col-span-5 for our default values, but you can totally do whatever you want here, like:

    gridColumn: {
      'logo-area': 'my-logo-area-label',

    ...to generate a class that fills a named column area like col-logo-area.

    The reason I've duplicated the value (like span 2 / span 2) is so that you can easily override just the grid-column-start or grid-column-end value without losing the span value, like this:

    <div class="col-span-4 col-start-2"></div>

    ...which would create an element that spans 4 columns but starts at grid line 2.


    These utilities take the form col-start-{key} where "key" is any value configured under the gridColumnStart key in your theme config.

    By default we only provide values that match the grid lines created by our default gridTemplateColumns config:

    gridColumnStart: {
      '1': '1',
      '2': '2',
      '3': '3',
      '4': '4',
      '5': '5',
      '6': '6',
      '7': '7',
      '8': '8',
      '9': '9',
      '10': '10',
      '11': '11',
      '12': '12',
      '13': '13',


    These utilities take the form col-end-{key} where "key" is any value configured under the gridColumnEnd key in your theme config.

    By default we only provide values that match the grid lines created by our default gridTemplateColumns config:

    gridColumnEnd: {
      '1': '1',
      '2': '2',
      '3': '3',
      '4': '4',
      '5': '5',
      '6': '6',
      '7': '7',
      '8': '8',
      '9': '9',
      '10': '10',
      '11': '11',
      '12': '12',
      '13': '13',


    These utilities take the form grid-rows-{key} where "key" is any value configured under the gridTemplateRows key in your theme config.

    By default we do not provide any values for this utility at all:

    gridTemplateRows: {}

    That means no grid-rows-{key} utilities are generated by default, and if you'd like to add them you need to customize your config.

    This is because I just could not think of any sensible general purpose default values for this — any real-world use case I could come up with seemed too specific to a given design.


    These utilities take the form row-gap-{key} where "key" is any value configured under the gridRowGap key in your theme config.

    By default, this uses your spacing config, and therefore matches all of your padding/margin/width/height utilities.


    These utilities take the form row-{key} where "key" is any value configured under the gridRow key in your theme config.

    By default we do not provide any values for this utility at all:

    gridRow: {}

    That means no row-{key} utilities are generated by default, and if you'd like to add them you need to customize your config.

    This is for the same reason as grid-template-rows.


    These utilities take the form row-start-{key} where "key" is any value configured under the gridRowStart key in your theme config.

    By default we do not provide any values for this utility at all:

    gridRowStart: {}

    That means no row-start-{key} utilities are generated by default, and if you'd like to add them you need to customize your config.

    This is for the same reason as grid-template-rows.


    These utilities take the form row-end-{key} where "key" is any value configured under the gridRowEnd key in your theme config.

    By default we do not provide any values for this utility at all:

    gridRowEnd: {}

    That means no row-end-{key} utilities are generated by default, and if you'd like to add them you need to customize your config.

    This is for the same reason as grid-template-rows.

    What's not included

    • grid-auto-columns utilities
    • grid-auto-rows utilities
    • grid-auto-flow utilities
    • grid-template-areas utilities

    If you think any of these are super important in a utility context, please reply with a good example and any ideas you have on how it should be included and we can definitely talk about getting it in.

    Try it out

    Here's a simple tailwind.run where I've thrown in the pre-compiled CSS so you can play with it:


    Any feedback appreciated!

  • 4

    Tailwind CSS v1.0 To-Dos

    Have been keeping track of this stuff in my personal to-do tracker but publishing them here in case anyone is interested.

    Naturally a ton of stuff has already been done for v1.0 and deleted from my to-do list, so this is only the stuff remaining as of today.

    Expect this list to grow and change over the next few weeks as I work towards finishing v1.0, but generally these are the things I've got lined up. They aren't in any sort of priority order or anything.


    • [x] Re-evaluate flex-grow/flex-no-grow, etc.
    • [x] Re-assess using postcss-selector-parser for escaping
    • [x] Update plugins to source their config from theme/variants
    • [x] Think about if there's a smarter way to make sure the separator is escaped
    • [ ] ~~Pass theme and variants to plugins explicitly?~~ No measurable benefit, easy to add later
    • [x] Add new shadows
    • [x] Rename config function to theme?
    • [x] Fix letterSpacing classes not being escaped
    • [x] Add 56 as a width?
    • [x] Add extended widths (48, 56, 64) to entire spacing scale?
    • [x] Make flex-* customizable
    • [ ] ~~Remove .clearfix?~~ Nah still useful enough to not make people add it themselves.
    • [x] Add new maxWidth scale
    • [x] Revisit which variants to enable by default for split up text style plugins
    • [x] Make preflight more hardcore, reset headings, etc.
    • [x] Autodetect presence of tailwind.config.js?
    • [ ] ~~Headings should inherit line-height like they inherit font-size and font-weight.~~ Not necessary, browser inherits line-height already for headings.
    • [x] Inherit font-related properties on form controls by default (line-height, font-family, color, maybe others, see sanitize.css for ideas)
    • [x] Use line-height: 1.5 on body or html by default (why not? I never want 1.15 and we set that 🤷‍♂️)
    • [x] Use system font stack by default instead of "sans-serif", I literally never want that either
    • [x] Use fontFamily.mono for pre/code if possible, fall back to monospaced (beware double monospace thing)
    • [x] Add text-6xl? 64px?
    • [x] Add new default color palette
    • [x] Bump sm breakpoint up to 640px?
    • [x] Inherit color and text-decoration on links
    • [x] Reconsider lists core plugin, maybe handle list style only and not padding
    • [ ] ~~Re-evaluate truncate, possibly replace with ellipsis-only utility~~ Class is convenient and useful, could still add ellipsis utility separately though
    • [x] Consider making break-normal handle both properties to provide a nicer experience
    • [x] Get rid of pin utilities in favor of top/right/bottom/left/inset? Unsure if worth break.
    • [x] Consider if container should become a true core plugin instead of an included third-party plugin
    • [x] Split whitespace plugin into whitespace and wordBreak/wordWrap?
    • [x] Rework CLI for new config structure
    • [x] Make sure shadow-outline matches new blue
    • [ ] ~~Error if we find @tailwind preflight in your CSS or keys in the wrong place in your config file to help guide people during the upgrade process?~~ Whatever, can do this if it actually bites people.
    • [ ] ~~Consider if defaultConfig/defaultTheme need to be separate files or even importable? Maybe make it possible to export a function from your config, and we just pass you the defaults?~~ Will keep these exports for now, we could add function syntax later if it feels like a slicker solution since it is non-breaking
    • [x] Make img, canvas, video, etc. block by default, and constrain max width?
    • [ ] ~~Make utilities important by default? I always do this on my own projects~~ Easy to tweak yourself and it's nice that inline-styles override utilities if they aren't important
    • [x] Maybe pass theme function to config callbacks?
    • [ ] Consider trying to make form elements more consistent by default across browsers? BuzzFeed Solid framework pretty good reference for super vanilla looking forms.
    • [x] Fix theme('negativeMargin.5') sort of stuff, maybe by negating all values in the default config in the callback
    • [x] Write upgrade guide
    • [x] Write function/tool to upgrade 0.x config files

    PR Opened

    • [ ] Consider removing border radius on inputs because of the iOS crap, and fixing radio buttons with just a [type="radio"] selector to keep specificity down

    Next (painful)

    Next (straightforward)

    • [ ] Make sure shadow-inset doesn't suck
    • [ ] Update the docs

    Next (could wait until after 1.0)

    • [ ] Add sanity test for a heavily customized config
    • [ ] Allow specifying a base config to extend (extends root level key)
    • [ ] Add disabled variant?
    • [ ] Pass parseSelector to plugins?
  • 5

    Tailwind 2.0 poor performance as part of a webpack PostCSS build system

    Description of the problem

    Tailwind CSS 2.0 builds slowly as part of a HMR webpack build system. It is slower than the release, but that could just be due to the amount of CSS generated increasing.

    I filed a very similar issue a month ago https://github.com/tailwindlabs/tailwindcss/issues/2544 and worked around the problem by splitting the CSS up into separate chunks. Global @apply still worked, and everything was great.

    It's all written up in the article Speeding Up Tailwind CSS Builds

    However with Tailwind CSS 2.0, the technique described in the article breaks.

    Desired solution

    I'm hoping to have the DX of working with Tailwind CSS 2.0 be improved from a HMR build time perspective.

    I realize that you can only optimize your generation of CSS so much, and a PR is in the works to do just that with esbuild. I also realize that part of the slowness here is simply webpack and the surrounding ecosystem being slow when dealing with massive amounts of CSS (though I've optimized that quite a bit here).

    However, the paradigm that Tailwind CSS is using is what generates a massive amount of CSS, and webpack is a very widely used tool that many things are built upon.

    Some way to address the DX here would be great; huge gains can be made using the CSS splitting technique described in the article, maybe there could be a way to restore that functionality to Tailwind 2.x?

    Link to a minimal reproduction:

    I made a new branch with Tailwind 2.0, webpack 5, PostCSS 8, and all the goodness:


    webpack_1  | ℹ 「wdm」: Compiled successfully.
    webpack_1  | ℹ 「wdm」: Compiling...
    webpack_1  | ℹ 「wdm」: assets by status 72.8 KiB [cached] 2 assets
    webpack_1  | assets by status 9.21 MiB [emitted]
    webpack_1  |   assets by info 3.62 MiB [immutable]
    webpack_1  |     asset app.53801fed2ee43ce850f5.hot-update.js 3.62 MiB [emitted] [immutable] [hmr] (name: app)
    webpack_1  |     asset runtime.53801fed2ee43ce850f5.hot-update.js 881 bytes [emitted] [immutable] [hmr] (name: runtime)
    webpack_1  |     asset 53801fed2ee43ce850f5.hot-update.json 37 bytes [emitted] [immutable] [hmr]
    webpack_1  |   assets by path js/*.js 5.6 MiB
    webpack_1  |     asset js/app.js 5.55 MiB [emitted] (name: app)
    webpack_1  |     asset js/runtime.js 43.9 KiB [emitted] (name: runtime)
    webpack_1  |   asset manifest.json 303 bytes [emitted]
    webpack_1  | Entrypoint app 9.21 MiB = js/runtime.js 43.9 KiB runtime.53801fed2ee43ce850f5.hot-update.js 881 bytes js/app.js 5.55 MiB app.53801fed2ee43ce850f5.hot-update.js 3.62 MiB
    webpack_1  | cached modules 711 KiB [cached] 61 modules
    webpack_1  | runtime modules 28.9 KiB 14 modules
    webpack_1  | ./node_modules/css-loader/dist/cjs.js??clonedRuleSet-4.use[1]!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-4.use[2]!../src/css/app.pcss 3.61 MiB [built] [code generated]
    webpack_1  | example-project (webpack 5.4.0) compiled successfully in 2527 ms

    While 2.5s isn't awful, this is in a pretty minimal CSS setup, where I was getting about 1.2s for the equivalent builds in Tailwind 1.x, and using the technique described in the article, the builds were around 182ms

  • 6

    Integrate PurgeCSS directly into Tailwind

    This PR adds a new purge config option for purging unused CSS directly from within Tailwind instead of having to pull in and configure PurgeCSS manually.

    The API is much more opinionated and slimmed down by default, optimizing for the 95% use case:

    // tailwind.config.js
    module.exports = {
      purge: [
      theme: {},
      variants: {},
      plugins: [],

    The purge option accepts an array of filenames/globs to scan for classes, and that's it. This should be enough for most people, but if you are one of those people who just can't help themselves and has to fiddle with everything, you can fine-tune the configuration however you like (keep reading for more on that).

    Things to note:

    • This option is only enabled when NODE_ENV is production. If you want to enable it explicitly based on some other conditional logic, you can use an object syntax and the enabled property, and specify your templates using the content property:

      // tailwind.config.js
      module.exports = {
        purge: {
          enabled: true,
          content: ['./src/**/*.html'],
        // ...
    • Only components and utilities are purged by default. Our base styles are not purged, and no custom CSS authored in your CSS files is purged, including any imports to outside libraries.

      This is to make sure you don't accidentally run into common pitfalls, like forgetting to scan your root HTML template (which is difficult with frameworks like Next.js since it is buried in node_modules) or accidentally purging styles that come from whatever datepicker library you've pulled in as an npm dependency.

      This means we are not purging absolutely everything that could be safely purged, but you get 99% of the benefit with much less manual tuning. You will basically never need to whitelist anything using this approach.

      Essentially we make your CSS file look like this:

      /* purgecss start ignore */
      @tailwind base;
      /* purgecss end ignore */
      @tailwind components;
      /* purgecss start ignore */
      .btn {
        @apply bg-blue-500 px-4 py-2 text-white;
      .alert {
        @apply border p-4 rounded;
      /* purgecss end ignore */
      @tailwind utilities;
      /* purgecss start ignore */
      .custom-utility {
        foo: bar;
      /* purgecss end ignore */

      If you really want to purge everything, you can do so using mode: 'all':

      // tailwind.config.js
      module.exports = {
        purge: {
          mode: 'all',
          content: ['./src/**/*.html'],
        // ...

      You're much more likely to accidentally remove important styles if you do this but I'm not the cops — if it tickles your pickle go for it.

    • We are using a new extractor strategy that tries to be as permissive as possible.

      Here is the new extractor we're using:

      defaultExtractor: content => {
        // Capture as liberally as possible, including things like `h-(screen-1.5)`
        const broadMatches = content.match(/[^<>"'`\s]*[^<>"'`\s:]/g) || []
        // Capture classes within other delimiters like .block(class="w-1/2") in Pug
        const innerMatches = content.match(/[^<>"'`\s.()]*[^<>"'`\s.():]/g) || []
        return broadMatches.concat(innerMatches)

      ...and here is the sample HTML we test our purging against:

      <!-- Basic HTML -->
      <div class="bg-red-500 md:bg-blue-300 w-1/2"></div>
      <!-- Vue dynamic classes -->
      <span :class="{ block: enabled, 'md:flow-root': !enabled }"></span>
      <!-- JSX with template strings -->
        function Component() {
          return <div class={`h-screen`}></div>
      <!-- Custom classes with really weird characters -->
      <div class="min-h-(screen-4) bg-black! font-%#[email protected] w-(1/2+8)"></div>
      <!-- Pug -->

      It works really well and I would be pretty surprised if you ever needed to customize this.

    If you want more control than what we offer, you can pass any options you want directly to PurgeCSS using the options property:

    // tailwind.config.js
    module.exports = {
      purge: {
        enabled: true,
        content: ['./src/**/*.html'],
        // These options are passed through directly to PurgeCSS
        options: {
          whitelist: ['bg-red-500', 'px-4'],
      // ...

    Any options passed to PurgeCSS will override our own options, so for example if you pass content it will override our content property at the top-level.

    Happy purging 🤮

  • 7

    npx tailwindcss init not working

    Describe the problem:

    Using tailwind in post-css compatibility mode

    I've got tailwind 2.0 installed and the build process runs, however now I want to set up a config file so I can add custom colors etcetera. I run the npx tailwindcss init command and it fails with this output.

    λ npx tailwindcss init
    npx: installed 86 in 8.321s
    Cannot find module 'autoprefixer'

    I can see autoprefix in both package.json "autoprefixer": "^9.8.6", and the autoprefixer folder in the node_modules folder.

    Not sure how to resolve this, please advise.

  • 8

    CSS Transitions

    This PR introduces a handful of CSS transition utilities. See the discussion at https://github.com/tailwindcss/tailwindcss/issues/14. It's mostly just a few new generators and updated docs/tests/etc, but it also includes a fix to the variants-and-disabling partial that allows for no variants.

    • [x] Generators
    • [x] Config
    • [ ] Docs
    • [x] Tests
  • 9

    Dev server must be restarted to have classes applied with Snowpack

    What version of @tailwindcss/jit are you using?


    What version of Node.js are you using?


    What browser are you using?


    What operating system are you using?


    Reproduction repository


    Hi there ☺️

    I tried to use this new JIT feature with a new React app built with Snowpack. Unfortunately, I cannot have Snowpack use Tailwind JIT properly.

    I think I might have missed something about the configuration process. When changing a class in a component, I have to stop and restart the dev server. Here are my config files:

    // snowpack.config.js
    module.exports = {
      mount: {
        public: { url: '/', static: true },
        src: { url: '/dist' },
      plugins: [
      routes: [{ match: 'routes', src: '.*', dest: '/index.html' }],
      optimize: {},
      packageOptions: {},
      devOptions: {},
      buildOptions: {},
    // tailwind.config.js
    module.exports = {
      purge: ['./src/**/*.{js,jsx,ts,tsx}', './public/index.html'],
      darkMode: false,
      theme: {
        extend: {},
      variants: {
        extend: {},
      plugins: [],
    // postcss.config.js
    module.exports = {
      plugins: {
        '@tailwindcss/jit': {},
        autoprefixer: {},


  • 10

    Poor performance as part of a webpack PostCSS build system

    Using the latest Tailwind CSS (1.8.13 as of this writing), I'm seeing slowness very similar to https://github.com/tailwindlabs/tailwindcss/issues/1620 & also https://github.com/tailwindlabs/tailwindcss/issues/443, the performance of using HMR with webpack-dev-server and webpack 4 or 5 is quite slow.

    It takes about 10 seconds on my MacBook Pro 2019 just changing a single color in a .pcss file, and it appears externally that it's rebuilding everything each time. The building of Tailwind CSS seems to have gotten slower and slower as the amount of utilities it includes have gone up.

    I'm not sure what the caching implemented in 1.7.2 does, but in a long running process (and maybe it's already doing this but) what if all of the Tailwind-specific imports like:

    @import "tailwindcss/base";

    ...were cached in a long running process, so it just returns the pre-generated blob? I'd imagine you're probably already doing this, but have any instrumentation or profiling been hooked up to the build to determine where the bottlenecks are?

    My postcss.config.js looks like this:

    module.exports = {
        plugins: [
                plugins: [
                path: ['./node_modules'],
                autoprefixer: { },
                features: {
                    'nesting-rules': true

    ...and the whole setup is essentially what's here: https://nystudio107.com/blog/an-annotated-webpack-4-config-for-frontend-web-development#tailwind-css-post-css-config

    It's not doing anything fancy re: the PostCSS part of the build, but its extremely slow compared to the HRM of JavaScript modules, etc.

    I tried removing postcss-preset-env to see if it made a difference, but it doesn't seem to.

    Related: https://stackoverflow.com/questions/63718438/webpack-dev-server-slow-compile-on-css-change-with-tailwind

  • 11

    Transient read failure may cause permanent failure to watch file

    V3.1.18 Tailwind CLI, Visual Studio 2022 as editor. Node v14.18.1 Chrome Window 10 (No Docker or WSL)

    This issue is a very close relative of #7759, but I think it might be quite specialised so I don't want to pollute that one.

    I have a rather odd web project, which has a single HTML file. So the content section of tailwind.config.js looks like this:

      content: [

    I run a tailwind CLI watcher with a command like this:

    npx tailwindcss --output wwwroot/css/tailwind.css --watch -i css/twbase.css

    I am suffering from the problem described in #7759 where the watcher stops watching after a while - anywhere between almost immediately and after lots and lots of successful rebuilds.

    By using the "Process Monitor" utility to observe the filesystem activity on the index.html file, I have observed that when Visual Studio (devenv.exe) is saving index.html, it goes through a rename/replace process which means there is a window of time in which the index.html file does not actually exist. It appears that node.exe (i.e. Tailwind) sometimes tries to read the file during this window and finds it to be missing.

    This apparently causes Tailwind to stop watching that file.


    The blue selected line in the image is Node getting a file-not-found failure doing a CreateFile (it's actually an open-to-read) on index.html in the middle of devenv doing a rename dance. I think that's a smoking gun.

    If I change the content file specification to be a wildcard, then my first impression is that things are much more robust:

      content: [


    1. Is it possible/likely that TW is converting a transient read-failure on a watched file into a permanent failure to watch that file?
    2. If so, could this be fixed?

    Even without the specific Visual Studio rename thing, transient read failures are probably an inescapable feature of Windows, because it's so common that people have tools like anti-virus and cloud-backup and indexers which do lots of automatic file opening.

  • 12

    Add modifiers to `context.getClassList` result

    This PR adds modifier information to the context.getClassList result. This will allow IntelliSense to provide completions for modifiers such as those for line-height.

    Example result:

      // ...
      // ...
          modifiers: ['3', '4', '5', '6', '7', '8', '9', '10', 'none', 'tight', 'snug', 'normal', 'relaxed', 'loose'],
      // ...
  • 13

    Tailwind CSS not working in WSL

    What version of Tailwind CSS are you using?

    I'm using the gem tailwindcss-rails which has tailwindcss v3.2.4

    What build tool (or framework if it abstracts the build tool) are you using?

    I'm not using any build tool since I'm using Rails 7 with import maps.

    What version of Node.js are you using?


    What browser are you using?


    What operating system are you using?

    WSL Ubuntu 20.04

    Reproduction URL tailwind-rails-bug

    Describe your issue

    I'm trying to use tailwindcss in my rails app using the official documentation, but unable to run the app since tailwindcss is not working in my WSL system. I opened an issue Help with tailwindcss-rails setup, the team informed me to open a bug report since the binary file is causing the problem.

  • 14

    Add logical properties support for inline direction

    This PR introduces support for logical properties in the inline direction for all relevant existing utilities, making it easier to build sites that support LTR and RTL layouts without having to use the rtl: variant when you simply need to mirror the styles.

    | New class | Properties | Physical counterpart (LTR) | | -------------- | -------------------------------------------------------- | -------------------------- | | start-* | inset-inline-start | left-* | | end-* | inset-inline-end | right-* | | ms-* | margin-inline-start | ml-* | | me-* | margin-inline-end | mr-* | | ps-* | padding-inline-start | pl-* | | pe-* | padding-inline-end | pr-* | | rounded-s-* | border-start-start-radius
    border-end-start-radius | rounded-l-* | | rounded-e-* | border-start-end-radius
    border-end-end-radius | rounded-l-* | | rounded-ss-* | border-start-start-radius | rounded-tl-* | | rounded-se-* | border-start-end-radius | rounded-tr-* | | rounded-ee-* | border-end-end-radius | rounded-br-* | | rounded-es-* | border-end-start-radius | rounded-bl-* | | border-s-* | border-inline-start-width | border-l-* | | border-e-* | border-inline-end-width | border-r-* | | border-s-* | border-inline-start-color | border-l-* | | border-e-* | border-inline-end-color | border-r-* | | scroll-ms-* | scroll-margin-inline-start | scroll-ml-* | | scroll-me-* | scroll-margin-inline-end | scroll-mr-* | | scroll-ps-* | scroll-padding-inline-start | scroll-pl-* | | scroll-pe-* | scroll-padding-inline-end | scroll-pr-* |


    This PR is limited to supporting the inline direction only, as supporting the block direction introduces potential naming collisions that make the API design more challenging, for example is mb-2 for margin-bottom or margin-block?

    After a bunch of research and talking to people in the community, I'm convinced that in practice supporting the block direction has far fewer benefits than supporting the inline direction, so I've opted to support just the inline direction for now to avoid being blocked on the API and get this feature shipped so people can start benefitting from it today. We can always introduce support for the block direction separately in the future — no need for them to be introduced together and slow down the process.

    Right now we are using the shortest names possible like ps-* but if we eventually add block support and feel like that's too ambiguous, we can always support a more verbose version like p-is-* so that the block direction equivalent can be p-bs-*. My gut is that the block direction stuff will be needed so infrequently that simply making the block direction more verbose and keeping the inline ones terse is actually going to be the better trade-off though.

    This PR does not include support for the logical values of clear or float, as browser support is currently poor. We can of course revisit this in the future and add them another day when support is better.

  • 15

    npx tailwindcss .... --watch is locking my files

    I've installed the latest version of Tailwind (December 2022) and am using this guide : https://chrissainty.com/adding-tailwind-css-v3-to-a-blazor-app/

    using this command: npx tailwindcss -i ./app.css -o ./wwwroot/css/app.css --watch

    While editing the Blazor files, the Powershell terminal compiles my CSS and is somewhat working fine.

    However - at some point i can't save the Razor / CSHTML files in Visual Studio because the files are locked by NPX / Node I then have to close Powershell / Tailwind builder to save my files.

    Ultimately - i would much rather like to work with a pre-compiled subset version of Tailwind but have had a hard time finding the right way to select which features i want. That way i would have functioning Intellisense in Visual Studio.

  • 16

    feat: add hyphens

    In german language we have many long words. We concat cohesive words without whitespaces. It's pretty easy to have words with 15+ characters. The german language also has strict rules how to hyphenate based on syllables, so the https://tailwindcss.com/docs/word-break does not help at all for normal language.

    So the hyphens rule comes in pretty handy: https://developer.mozilla.org/en-US/docs/Web/CSS/hyphens

    It's pretty straight forward addition, that's requested by a few people:

    • https://github.com/tailwindlabs/tailwindcss/discussions/7286
    • https://github.com/tailwindlabs/tailwindcss/discussions/2243
    • https://github.com/tailwindlabs/tailwindcss/discussions/8508
    • https://github.com/tailwindlabs/tailwindcss/discussions/1846
    • https://github.com/tailwindlabs/tailwindcss/discussions/3985