Using Tailwind CSS in Elm and VSCode

VSCode has a fantastic Tailwind CSS plugin, which provides autocompletions, linting and hover previews when using Tailwind classes. Unfortunately the plugin doesn’t come with Elm support right out of the box, so I missed these features writing Tailwind CSS in Elm.

Luckily with a little bit of configuration in VSCode, we can get pretty close to a similar developer experience.

How to configure VSCode

Here’s the quick rundown:

  1. Install the tailwind-intellisense plugin for VSCode
  2. Copy the settings below into your VSCode settings.json file
  3. Open an Elm file and validate that it’s working

settings.json:

{
  // more settings here …

  "editor.quickSuggestions": {
    "strings": true
  },
  "tailwindCSS.includeLanguages": {
    "elm": "html"
  },
  "[elm]": {
    "tailwindCSS.experimental.classRegex": [
      "\\bclass[\\s(<|]+\"([^\"]*)\"",
      "\\bclass[\\s(]+\"[^\"]*\"[\\s+]+\"([^\"]*)\"",
      "\\bclass[\\s<|]+\"[^\"]*\"\\s*\\+{2}\\s*\" ([^\"]*)\"",
      "\\bclass[\\s<|]+\"[^\"]*\"\\s*\\+{2}\\s*\" [^\"]*\"\\s*\\+{2}\\s*\" ([^\"]*)\"",
      "\\bclass[\\s<|]+\"[^\"]*\"\\s*\\+{2}\\s*\" [^\"]*\"\\s*\\+{2}\\s*\" [^\"]*\"\\s*\\+{2}\\s*\" ([^\"]*)\"",
      "\\bclassList[\\s\\[\\(]+\"([^\"]*)\"",
      "\\bclassList[\\s\\[\\(]+\"[^\"]*\",\\s[^\\)]+\\)[\\s\\[\\(,]+\"([^\"]*)\"",
      "\\bclassList[\\s\\[\\(]+\"[^\"]*\",\\s[^\\)]+\\)[\\s\\[\\(,]+\"[^\"]*\",\\s[^\\)]+\\)[\\s\\[\\(,]+\"([^\"]*)\""
    ]
  }

  // … more settings here
}

Examples that should trigger autocompletions

This configuration should display autocompletions in the following situations:

You can copy these to verify it’s working correctly:

div [ class "flex flex-col" ] []

div [ class ("flex flex-col" ++ " text-black bg-white") ] []

div [ class <| "flex flex-col" ++ " text-black bg-white" ] []

div [ class <|
    "flex flex-col"
    ++ " text-black bg-white"
    ] []

div [ classList [ ("flex flex-col", True), ("text-black bg-white", False) ] ] []

div [ classList
      [ ("flex flex-col", True)
      , ("text-black bg-white", False)
      ]
    ] []

How it works

tailwindcss-intellisense added an experimental classRegex setting, which allows passing a list of custom regex patterns to the plugin. It uses these patterns to find Tailwind classes in the code.

Explanation for the changes in settings.json

"tailwindCSS.includeLanguages": {
  "elm": "html"
}

This code enables the Tailwind CSS plugin for .elm files.

Then I’ve added a bunch of regex patterns to tell the VSCode plugin where it can expect to find Tailwind CSS classes inside Elm files:

"[elm]": {
  "tailwindCSS.experimental.classRegex": [
    "\\bclass[\\s(<|]+\"([^\"]*)\"",
    "\\bclass[\\s(]+\"[^\"]*\"[\\s+]+\"([^\"]*)\"",
    "\\bclass[\\s<|]+\"[^\"]*\"\\s*\\+{2}\\s*\" ([^\"]*)\"",
    "\\bclass[\\s<|]+\"[^\"]*\"\\s*\\+{2}\\s*\" [^\"]*\"\\s*\\+{2}\\s*\" ([^\"]*)\"",
    "\\bclass[\\s<|]+\"[^\"]*\"\\s*\\+{2}\\s*\" [^\"]*\"\\s*\\+{2}\\s*\" [^\"]*\"\\s*\\+{2}\\s*\" ([^\"]*)\"",
    "\\bclassList[\\s\\[\\(]+\"([^\"]*)\"",
    "\\bclassList[\\s\\[\\(]+\"[^\"]*\",\\s[^\\)]+\\)[\\s\\[\\(,]+\"([^\"]*)\"",
    "\\bclassList[\\s\\[\\(]+\"[^\"]*\",\\s[^\\)]+\\)[\\s\\[\\(,]+\"[^\"]*\",\\s[^\\)]+\\)[\\s\\[\\(,]+\"([^\"]*)\""
  ]
}

And lastly I’ve globally enabled quick suggestions for strings in VSCode, which is recommended by the Tailwind CSS people and I highly recommend it as well. This continues to provide autocompletions when deleting characters of an existing class:

"editor.quickSuggestions": {
  "strings": true
}

Without this setting one has to completely delete a class and start writing it from scratch again for the autocompletions to show up.

This setting can be used for other languages too

The cool thing about this regex setting is that you can use it to enable Tailwind CSS support for pretty much any language. It won’t be as perfect as actually parsing an AST like the plugin does for JavaScript, but this might be good enough for your use cases.

To make it work with a different language, replace [elm] with the VSCode identifier of the language and write regexes that work with its syntax.

If you want to add or test your own regex patterns, note that each regex can only have a single capture group. This group should only capture a string of space separated Tailwind classes without any other characters. That’s apparently a limitation from the plugin and is the reason why I had to add multiple patterns to the configuration to handle more cases like concatenating multiple strings.

I recommend using regextester to easily test multiple patterns at the same time.

Suggestions or feedback?

If you found better and more robust regex patterns for using Tailwind CSS in Elm, please get in touch.

Then I’ll update this post to spread the knowledge, so that everyone can get the best experience writing Tailwind CSS in Elm. ✌️


Update May 16:
I’ve changed the regex for concatenated strings, so that all subsequent strings need to start with an empty space. This prevents tailwind classes to be concatenated incorrectly in the resulting string. The autocompletions not showing up are meant as a warning that a space is missing.

Update May 17:
Martin Janiczek posted a small guide on how to use the same setup with Vim.