Grease

Grease takes the friction out of building fast, adaptable, aesthetic websites.

Why Grease?

Grease combines a trio of ultra-fast tools (11ty, Lightning CSS, and Esbuild) with a modern, declarative CSS architecture that frees you from browser micro-management. It’s light enough for small sites, but has everything you need to tackle large projects without getting bogged down in slow builds, dependency hell, and bloated front-ends. Key benefits:

  • Fast in-browser design. Fast tools and a custom-property-powered composable CSS architecture makes designing in browser a joy, and scaffolding new pages fast.
  • Zero-config entrypoints. Import everything into monolithic CSS and JS bundles? Break out page bundles? Inline critical CSS? YES.
  • No fillers, no additives. Grease takes a platform-first approach and keeps dependencies to minimum so you can focus on building, not bundling.
  • Expressive color. Grease includes a comprehensive color system that lets you easily support light & dark mode, custom themes, composable themes, and all of the above.
  • Fluid, variable type. A straightforward fluid type system makes it easy to keep your type game on point across a wide range of devices and screen sizes.
  • Batteries included. Production-ready odds & ends come in the box. Sitemaps, canonical URL support, no-index support, metadata, etc.

Getting started

  1. Clone the Grease repository on Github.
  2. Install with npm install.
  3. To start the local dev server, run npm start.
  4. Grease is pre-configured for Netlify deployment. You can use the publish:prod script and _public output directory to deploy elsewhere.

Working with CSS

Grease uses a practical, declarative approach to writing modern CSS, using three breakpoints (small, medium, large), and three cascade layers:

  1. base is where you define the default presentation characteristics for your project. Tailoring the custom media queries, custom properties, typeface, and base elements alone should get you halfway there. A kitchen sink demo is included to make it easy to see the impact of your changes across a wide variety of elements.
  2. components is where you define commonly repeated objects that live across your project. Components care little about their position on any given page.
  3. utilities is for CSS that manipulates elements and components. Grease aims to cover the small subset of attributes that are highly variable (page position, type characteristics, spacing) as opposed to making every property available. This approaches delivers the key benefits of utility css (breaking the linear ratio between page count and lines of CSS, less repetition) without the tooling complexity of build-dependent approaches.

Syntax, draft specs

Components in Grease use a modified BEM syntax, which uses a terse block --modifier1 --modifier2 syntax instead of block--modifier1 block--modifier2.

Lightning is configured to transpile draft custom media syntax, but nothing else. Adjust as need be for the project at hand.

Breaking up CSS

Grease gives you three options for including CSS:

  1. In the main bundle. Global stuff goes here.
  2. As route-specific bundles. Add a CSS file to source/css/pages (or any folder not prefixed by an underscore) to create a new entrypoint. Assign the path to stylesheet in template frontmatter to use it.
  3. As style tags. For critical CSS or page-specific one-offs, Grease includes an 11ty bundle that processes CSS with Lightning and adds it to a style tag in the page head.

Working with JS

Like with CSS, Grease supports config-free javascript bundles. A main bundle is included by default, and you can add JS files to source/js (or any sub-folder not prefixed by an underscore) to create a new bundles. Assign paths to javascript in template frontmatter to use them.

Grease is designed to use the web platform directly, and assumes ESM. Several custom elements are included; a scroll detector, an element that collapses and expands details elements at different viewport sizes, and an element that triggers animations on viewport entry.

Layout

Layout with Grease is handled primarily by grid and flex utilties. Both are opt-in, which makes it easy to mix in more specific layout needs (or wholesale replace with a different approach). Use margin and padding utilities to finnesse interplay between elements.

Grid

Rapidly compose responsive layouts with an infinitely nestable 12 column+2 “bleed” column grid that collapses to 1 column +2 bleed columns @small. Add the .grid class to a parent container to opt in.

<section class="grid">
  <div class="start-1 span-6"></div>
  <div class="start-auto bleed-end"></div>
</section>

<section class="grid">
  <div class="span-1/3"></div>
  <div class="span-1/3"></div>
  <div class="span-1/3"></div>
</section>

Grid children

  • .start-{1-12/auto} sets the column start positon @md+
  • .span-{1-12} sets how many columns the element spans at @medium+
  • .bleed, .bleed-{start/end} makes elements stick to page edges @sm+
  • .place-{start/center/end} set placement of content within a grid

Flex

Add the .flex or .inline-flex class to a parent container to opt in.

  • .gap-{sm/md/lg} sets row and column gap
  • .column-gap-{sm/md/lg} sets column gap
  • .align-items-{start/center/end} sets alignment
  • .justify-{start/center/between/end} sets justification
  • .no-wrap prevents items from wrapping
  • .column switches to a vertical orientation
  • Append @sm or @md to properties to apply at specific breakpoints

Margin

  • .mt-{0/xs-xxl/flex} sets block start margin
  • .mb-{0/xs-xxl/flex} sets block end margin
  • .ml-{0/xs-xxl/flex} sets inline start margin
  • .mr-{0/xs-xxl/flex} sets inline end margin
  • Prepend - to set negative margin
  • Append @md to apply at medium+

Padding

  • .pt-{0/xs-xxl/flex} sets block start padding
  • .pb-{0/xs-xxl/flex} sets block end padding
  • .pl-{0/xs-xxl/flex} sets inline start padding
  • .pr-{0/xs-xxl/flex} sets inline end padding
  • Append @md to apply at medium+

Typography

Grease uses a semi-fluid type system that attempts to do most of the heavy-lifting for you. Set --size-base, --size-scale-sm, and --size-scale-md in @root.css and Grease takes it from there. Line height defaults to --leading-fluid, which decreases as type size increases. A secondary step-based system steps in when you need fine-grained control.

Typographic utilities

  • .size-{xxxs-xxxxl} adjusts font size
  • .weight-{200-800} adjusts font weight
  • .measure-{xs-xl} limits width to a maximum number of character
  • {.left/.center/.right} changes text alignment
  • .leading-{flush/xxs-lg} adjusts line height
  • .tracking-{sm-xl} adjusts letter spacing
  • .balance attempts to balance multiple lines of text
  • .italic, .uppercase, .unlisted, .undecorated do what they suggest

Color & opacity

Grease includes a fully featured color system built around modern features like relative color, light-dark(), and color-mix() that lets you implement page themes, component themes, and light/dark mode without having to micro-manage color. Here’s how it works:

  1. Set your key colors, like --primary, --secondary, and --neutral in @root.css. These colors, along with --50 to --900 tint & shade presets form your base color system.
  2. Create color “presets” like --color-text, --color-bg, etc with baked in light and dark support, and use them liberally to reduce micro-management and make theme-friendly components. To define presets, use relative color syntax along with light-dark(), like so:
--color-text: light-dark(
  oklch(from var(--primary) var(--700)),
  oklch(from var(--primary) var(--300) / 50%)
)
  1. Make component-level exceptions by using the same strategy above. Remember that you can always use calc() expressions instead of tint & shade presents, like so:
border-color: light-dark(
  oklch(from var(--secondary) calc(l * 1.5) c h),
  oklch(from var(--secondary) calc(l / 1.5) c h)
)
  1. Use color and opacity utilities to make context-specific adjustments and one-offs.
  2. Create additional themes by creating a class in css/_base/themes.css that redefines your base colors and your color presets. Add the class to the HTML element using the theme front matter key for a page-level theme, or to elements for component-level theming. You can also use .light or .dark to force light or dark mode at the page or component level.

Color & opacity utilities

  • .color does nothing on it’s own; use with modifiers below
  • .--{text/bg/border/accent} sets a remap target
  • .--use-{text/bg/border/accent} remaps to a different part’s color
  • .--{primary/secondary/neutral}-{50-900} remaps to a specific color
  • .set-{text/bg} sets color
  • .text-{10-90} adjusts text opacity
  • .bg-{10-90} adjusts background opacity
  • .border-{10-90} adjusts border opacity

Animation

Grease includes a simple, tiny, composable animation system:

  1. Define a CSS animation and a utility class that invokes it.
  2. Use the class name as the value for the data-aos attribute on the element you want to animate.
  3. Grease will animate in the element when it enters the viewport. If multiple elements appear at once, Grease builds in a brief stagger (taking into consideration any existing delays).

By adding animation to elements and sub-elements, you can quickly scaffold out surprisingly complex animations from a handful of simple primitives. For instances where it’s inconvenient to add an attribute directly to an element, use data-aos-children to apply the animation class to all direct children of the element.