Tailwind Setup

v5.x.x

Our general Tailwind setup involves a frontend.config.json, tailwind.config.js and an input.css file.

We use values from this JSON file inside the Tailwind config to separate Tailwind config itself from front end site data. This JSON file is often read by a project's Webpack set up, a project's JavaScript and a project's CMS. This set up is, of course, not mandatory to use these plugins, but they may still prove inspiration for your Tailwind set up all the same.

This documentation site is made using Tailwind and AREA 17 tailwind plugins, this page documents the config files used for this site.

With the introduction of Tailwind 4, the setup of your project changes. Both use the same frontend.config.json.

frontend.config.json

frontend.config.json
{
  "structure": {
    "breakpoints": {
      "xs": "0",
      "sm": "544px",
      "md": "650px",
      "lg": "990px",
      "xl": "1300px",
      "xxl": "1520px"
    },
    "columns": {
      "xs": "4",
      "sm": "4",
      "md": "8",
      "lg": "12",
      "xl": "12",
      "xxl": "12"
    },
    "container": {
      "xs": "auto",
      "sm": "auto",
      "md": "auto",
      "lg": "auto",
      "xl": "auto",
      "xxl": "1440px"
    },
    "gutters": {
      "inner": {
        "xs": "10px",
        "sm": "15px",
        "md": "20px",
        "lg": "30px",
        "xl": "40px",
        "xxl": "40px"
      },
      "outer": {
        "xs": "20px",
        "sm": "30px",
        "md": "40px",
        "lg": "40px",
        "xl": "40px",
        "xxl": "0px"
      }
    }
  },
  "ratios": {
    "1x1": "1:1",
    "16x9": "16:9"
  },
  "spacing": {
    "tokens": {
      "scaler": 4,
      "arbitraries": {
        "400": "400px",
        "600": "600px"
      }
    },
    "groups": {
      "outer-1": {
        "xs": 64,
        "lg": 96
      },
      "inner-1": {
        "xs": 24,
        "md": 40,
        "lg": 64
      },
      "inner-2": {
        "xs": 16,
        "md": 24,
        "lg": 32
      }
    }
  },
  "color": {
    "tokens": {
      "white": "#fff",
      "grey-3": "#f8f8f8",
      "grey-5": "#f2f2f2",
      "grey-10": "#e6e6e6",
      "grey-15": "#d9d9d9",
      "grey-30": "#b3b3b3",
      "grey-54": "#757575",
      "grey-90": "#1a1a1a",
      "black": "#000",
      "blue-01": "#0A152B",
      "blue-02": "#001F5C",
      "blue-03": "#004F91",
      "blue-04": "#313BFB",
      "blue-05": "#81EEF3",
      "blue-06": "#ADD8E6",
      "red-01": "#f00"
    },
    "border": {
      "primary": "grey-90",
      "secondary": "grey-30",
      "tertiary": "grey-54",
      "quaternary": "blue-05",
      "code-example-filename": "blue-05"
    },
    "text": {
      "title": "black",
      "primary": "grey-90",
      "inverse": "white",
      "secondary": "grey-54",
      "accent": "blue-03",
      "code": "black",
      "code-example": "grey-3",
      "code-example-filename": "blue-05",
      "error": "red-01"
    },
    "background": {
      "primary": "grey-10",
      "header": "grey-10",
      "container-demo": "white",
      "footer": "grey-10",
      "banner": "grey-90",
      "accent": "blue-03",
      "column": "blue-05",
      "column-alt": "blue-04",
      "code": "white",
      "code-example": "grey-90",
      "quote": "grey-5"
    },
    "underline": {
      "primary": "grey-54",
      "secondary": "blue-03"
    },
    "scrollbar": {
      "track": {
        "primary": "blue-06"
      },
      "thumb": {
        "primary": "blue-03"
      }
    }
  },
  "typography": {
    "families": {
      "sans": "SuisseIntl, Helvetica, Arial, sans-serif",
      "serif": "\"Times New Roman\", Georgia, serif",
      "mono": "\"Lucida Console\", Courier, monospace"
    },
    "typesets": {
      "h1": {
        "xs": {
          "font-family": "var(--font-sans)",
          "font-weight": "500",
          "bold-weight": "500",
          "font-size": "32px",
          "line-height": "1.2",
          "letter-spacing": "-0.02em",
          "font-smoothing": "true"
        },
        "md": {
          "font-size": "36px"
        },
        "lg": {
          "font-size": "48px"
        }
      },
      "h2": {
        "xs": {
          "font-family": "var(--font-sans)",
          "font-weight": "500",
          "bold-weight": "500",
          "font-size": "20px",
          "line-height": "1.2",
          "letter-spacing": "-0.02em",
          "font-smoothing": "true"
        },
        "md": {
          "font-size": "24px"
        },
        "lg": {
          "font-size": "28px"
        }
      },
      "h3": {
        "xs": {
          "font-family": "var(--font-sans)",
          "bold-weight": "500",
          "font-weight": "500",
          "font-size": "16px",
          "line-height": "1.2",
          "letter-spacing": "-0.02em",
          "font-smoothing": "true"
        },
        "md": {
          "font-size": "20px"
        }
      },
      "h4": {
        "xs": {
          "font-family": "var(--font-sans)",
          "bold-weight": "600",
          "font-weight": "600",
          "font-size": "14px",
          "line-height": "1.2",
          "letter-spacing": "-0.02em",
          "font-smoothing": "true"
        },
        "md": {
          "font-size": "16px"
        }
      },
      "body": {
        "xs": {
          "font-family": "var(--font-sans)",
          "bold-weight": "600",
          "font-size": "14px",
          "line-height": "1.7",
          "font-smoothing": "true"
        },
        "md": {
          "font-size": "16px"
        }
      },
      "ui": {
        "xs": {
          "font-family": "var(--font-sans)",
          "font-size": "12px",
          "line-height": 1.2,
          "font-weight": 400
        }
      },
      "code": {
        "xs": {
          "font-family": "var(--font-mono)",
          "font-size": "14px",
          "line-height": 1.2,
          "font-weight": 400
        }
      }
    }
  }
}
  • structure - here we describe the main layout of the site, its grid and composition, from these :root variables will be made
    • breakpoints - where each of our breakpoints starts
    • columns - how many design columns at each breakpoint
    • container - how wide the main container of the site is (auto or px/vw/rem)
  • gutters - gutters definitions
    • inner - between design columns
    • outer - on the outside of the main container
  • ratios - which ratios should be generated for ratio boxes
  • spacing - define the spacing values for use in Tailwind spacing classes like h-20 and mx-40
    • tokens - people rarely think in rems, they're abstract but as experienced screen developers we've been talking about pixels for years - we rename the spacing tokens to pixel values and use a function to convert them to rems and so mt-16 will give you a margin top of 16px (which in the output CSS will be 1rem)
      Note: not required for Tailwind 4
    • groups - responsive spacing utility classes, create global spacing rules that are responsive and systematised, from these :root variables will be made
  • color - define site colours
    • tokens - these are the colour names, such as red-600, not super human readable, from these :root variables will be made
    • borderColor - apply colour tokens (or arbitrary colours) to human readable systematised named classes, eg: border-primary for your primary border, might map to primary: grey-5, from these :root variables will be made
    • textColor - same for text classes
    • backgroundColor - and background colours
  • typography - define the site type styles
    • families - firstly the families being used, from these :root variables will be made
    • typesets - responsive type sets, where breakpoint overrides can be specified and typography can be systematised

Tailwind 4 tailwind.config.js and input.css

tailwind.config.js
// A17 tailwind plugins
const {
  Setup,
  ColorTokens,
  ApplyColorVariables,
  Typography,
  Container,
  DevTools,
  GridGap,
  GridLayout,
  Spacing,
  Layout,
  GridLine,
  Keyline,
  BackgroundFill,
  StrokeFull,
  Underline,
  FullBleedScroller,
  Scrollbar,
  PseudoElements,
  InteractionMediaQueries,
  RatioBox,
} = require('../index');

// conf
const feConfig = require('./frontend.config.json');

module.exports = {
  content: ['./docs/**/*.html', './docs/*.html'],
  plugins: [
    Setup,
    ColorTokens,
    ApplyColorVariables,
    Typography,
    Container,
    DevTools,
    GridGap,
    GridLayout,
    Spacing,
    Layout,
    GridLine,
    Keyline,
    BackgroundFill,
    StrokeFull,
    Underline,
    FullBleedScroller,
    Scrollbar,
    PseudoElements,
    InteractionMediaQueries,
    RatioBox,
  ],
  theme: {
    screens: feConfig.structure.breakpoints,
    mainColWidths: feConfig.structure.container,
    innerGutters: feConfig.structure.gutters.inner,
    outerGutters: feConfig.structure.gutters.outer,
    columnCount: feConfig.structure.columns,
    fontFamilies: feConfig.typography.families,
    typesets: feConfig.typography.typesets,
    spacingGroups: feConfig.spacing.groups,
    ratios: feConfig.ratios,
    css: feConfig.css,
    colors: feConfig.color.tokens,
    borderColor: ApplyColorVariables(
      feConfig.color.tokens,
      feConfig.color.border
    ),
    textColor: ApplyColorVariables(feConfig.color.tokens, feConfig.color.text),
    backgroundColor: ApplyColorVariables(
      feConfig.color.tokens,
      feConfig.color.background
    ),
    underlineColor: ApplyColorVariables(
      feConfig.color.tokens,
      feConfig.color.underline
    ),
    scrollbarColor: {
      track: ApplyColorVariables(
        feConfig.color.tokens,
        feConfig.color.scrollbar.track
      ),
      thumb: ApplyColorVariables(
        feConfig.color.tokens,
        feConfig.color.scrollbar.thumb
      ),
    },
  },
  extend: {
    spacing: {
      gutter: 'var(--inner-gutter)',
      'outer-gutter': 'var(--outer-gutter, 0px)',
    },
  },
};

And then input this tailwind.config.js and configure the Tailwind theme in CSS:

input.css
@config "./tailwind.config.js";
@import "tailwindcss";

@theme {
  --container-*: initial;
  --breakpoint-*: initial;
  --color-*: initial;
  --font-*: initial;
  --text-*: initial;
  --tracking-*: initial;
  --leading-*: initial;
  --spacing: 1px;
}

@utility container {
  max-width: 100%;
}

Tailwind 3 tailwind.config.js

tailwind.config.js
// A17 tailwind plugins
const {
  setup,
  applyColorVariables,
  backgroundFill,
  colorTokens,
  components,
  container,
  cssInJs,
  devTools,
  fullBleedScroller,
  gridGap,
  gridLayout,
  gridLine,
  interactionMediaQueries,
  keyline,
  layout,
  pseudoElements,
  ratioBox,
  scrollbar,
  spacing,
  spacingTokens,
  strokeFull,
  typography,
  underline,
} = require('../index');

// conf
const feConfig = require('./frontend.config.json');

module.exports = {
  content: ['./docs/**/*.html', './docs/*.html'],
  corePlugins: {
    container: false,
  },
  plugins: [
    setup,
    colorTokens,
    components,
    backgroundFill,
    container,
    cssInJs,
    devTools,
    fullBleedScroller,
    gridGap,
    gridLayout,
    gridLine,
    interactionMediaQueries,
    keyline,
    layout,
    pseudoElements,
    ratioBox,
    scrollbar,
    spacing,
    strokeFull,
    typography,
    underline,
  ],
  theme: {
    screens: feConfig.structure.breakpoints,
    mainColWidths: feConfig.structure.container,
    innerGutters: feConfig.structure.gutters.inner,
    outerGutters: feConfig.structure.gutters.outer,
    columnCount: feConfig.structure.columns,
    fontFamilies: feConfig.typography.families,
    typesets: feConfig.typography.typesets,
    spacingGroups: feConfig.spacing.groups,
    spacing: spacingTokens(feConfig.spacing.tokens),
    colors: feConfig.color.tokens,
    borderColor: applyColorVariables(
      feConfig.color.tokens,
      feConfig.color.border
    ),
    textColor: applyColorVariables(feConfig.color.tokens, feConfig.color.text),
    backgroundColor: applyColorVariables(
      feConfig.color.tokens,
      feConfig.color.background
    ),
    underlineColor: applyColorVariables(
      feConfig.color.tokens,
      feConfig.color.underline
    ),
    scrollbarColor: {
      track: applyColorVariables(
        feConfig.color.tokens,
        feConfig.color.scrollbar.track
      ),
      thumb: applyColorVariables(
        feConfig.color.tokens,
        feConfig.color.scrollbar.thumb
      ),
    },
    ratios: feConfig.ratios,
    components: feConfig.components,
    css: feConfig.css,
    extend: {
      minHeight: ({ theme }) => theme('spacing'),
      maxWidth: ({ theme }) => theme('spacing'),
      spacing: {
        'safe-top': 'env(safe-area-inset-top)',
        'safe-bottom': 'env(safe-area-inset-bottom)',
        'safe-left': 'env(safe-area-inset-left)',
        'safe-right': 'env(safe-area-inset-right)',
        gutter: 'var(--inner-gutter)',
        'outer-gutter': 'var(--outer-gutter, 0px)',
      },
    },
  },
};
input.css
@tailwind base;
@tailwind components;
@tailwind utilities;