GithubHelp home page GithubHelp logo

stormwarning / tailwindcss-capsize Goto Github PK

View Code? Open in Web Editor NEW
81.0 3.0 3.0 703 KB

✂️ Tailwind CSS utility classes for trimming whitespace above & below capital letters.

License: ISC License

JavaScript 2.45% TypeScript 97.55%
tailwindcss-plugin capsize typography leading-trim hacktoberfest

tailwindcss-capsize's Introduction

tailwindcss-capsize

npm version

A TailwindCSS plugin that generates leading-trim utility classes using Capsize.

npm install --save-dev tailwindcss-capsize

leading-trim?

A proposed CSS property to remove the extra space from text bounding boxes, which affects optical alignment. This article from Microsoft Design outlines the problem and how the proposed solution works.

Configuration

This plugin requires a fontMetrics key added to your Tailwind theme. It should be an object with keys matching those in your fontFamily definitions, and each key should have an object of the following shape:

{
	ascent: number
	descent: number
	lineGap: number
	unitsPerEm: number
	capHeight: number
}

These values can be determined by using the Capsize website, fontkit, FontDrop!, or some other means.

A full example

// tailwind.config.js
module.exports = {
	theme: {
		fontFamily: {
			sans: ['Inter', 'sans-serif'],
		},
		fontMetrics: {
			sans: {
				capHeight: 2048,
				ascent: 2728,
				descent: -680,
				lineGap: 0,
				unitsPerEm: 2816,
			},
		},
		fontSize: { ... },
		lineHeight: { ... },
		...
	},
	plugins: [require('tailwindcss-capsize')],
}

Usage

The new .capsize utility class should be applied to the direct parent element surrounding a text node. This class requires font-family, font-size, and line-height utilities to be applied at some point above it in the cascade in order for the required custom properties to be available.

<!-- Example using default TailwindCSS config -->

<p class="font-sans text-base leading-none capsize">Lorem ipsum dolor</p>

Options

rootSize

type: number (optional, default: 16)

The plugin assumes a root font-size of 16px when converting from rem values. To use a different value, pass it in (without units) to the plugin options.

require('tailwindcss-capsize')({ rootSize: 12 })

className

type: string (optional, default: 'capsize')

The default .capsize utility class can be replaced with a custom class name if preferred.

require('tailwindcss-capsize')({ className: 'leading-trim' })

mode

type: 'modern' | 'classic' (optional, default: 'modern')

By default the plugin replaces the fontFamily, fontSize, and lineHeight core plugins, adding custom properties to the output of each which are used in the calc() expressions in the utility class.

.font-sans {
+	--ascent-scale: 0.9688;
+	--descent-scale: 0.2415;
+	--cap-height-scale: 0.7273;
+	--line-gap-scale: 0;
+	--line-height-scale: 1.2102;
	font-family: Inter, sans-serif;
}

If you need to support browsers that don’t support custom properties, setting mode to 'classic' will handle all the calculation at build-time before the CSS is output. This will require that the markup matches a specific selector format.

require('tailwindcss-capsize')({ mode: 'classic' })

Tips and tricks

Text truncation and line clamping

Sometimes an interface calls for truncating text to a single line or clamping text to a specified number of lines. Applying these methods to the same element that the default .capsize class is applied to will cause issues since the class assigns pseudo ::before and ::after elements to that element.

<!-- ❌ Does NOT work -->

<p class="font-sans text-base leading-none capsize truncate">
	Text to be truncated to a single line
</p>

To solve this, a child element to the element with the .capsize class should wrap the text. This element should receive the styling to truncate or line clamp.

<!-- ✅ Does work! -->

<p class="font-sans text-base leading-none capsize">
	<span class="truncate">Text to be truncated to a single line</span>
</p>

Related

🔡 tailwindcss-opentype — Utility classes for advanced typographic features.

tailwindcss-capsize's People

Contributors

andriytyurnikov avatar dependabot[bot] avatar dylanvann avatar essejmclean avatar github-actions[bot] avatar stormwarning avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

tailwindcss-capsize's Issues

Relative font-size support

I am exploring some approaches to responisve typography, and I am trying to use tricks like

.rescale-from-rem {
  font-size: calc(100% / 1.428);
}

.autoscaled-base {
  font-size: calc(1rem / 4 * 8);
}

Which results in

--font-size-px: NaN

I am not sure, what is going on here. Is implementation somehow reliant on pixel values?

--font-size-px is returned as pixel value, breaks calc in mode: 'modern'

The --font-size-px CSS custom property gets returned after being run through TailwindCSS's internals as a pixel value.

This creates an issue with the various CSS calcs that use the --font-size-px CSS custom property since certain units cannot be mixed (addition + and subtraction - in this use case).

This happens because the fontSizeActual variable in the plugin.ts file is passed as a number and postcss-js (which TailwindCSS uses under the hood to parse plugins) converts this to a pixel value as is common behaviour with most CSS-in-JS solutions.

I've created a pull request (#128) that solves this issue by wrapping fontSizeActual with String() and edited the tests to check that the values for --font-size-px are truly flat values (i.e. --font-size-px: 16;, not --font-size-px: 16px;).

Separately I want to thank @stormwarning for releasing v3.0.0 - this update has vastly improved the size of my CSS files when working with themes that utilize many font sizes and line heights.

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

github-actions
.github/workflows/main.yml
  • actions/checkout v3
  • actions/setup-node v3.1.1
  • actions/cache v3.0.2
.github/workflows/release.yml
  • actions/checkout v3
  • actions/setup-node v3.1.1
  • changesets/action v1
npm
package.json
  • @capsizecss/core ^3.0.0
  • @changesets/cli 2.27.1
  • @zazen/changesets-changelog 2.0.3
  • @zazen/eslint-config 6.8.0
  • @zazen/prettier-config 1.0.0
  • eslint 8.56.0
  • husky 4.3.x
  • jest-diff 29.7.0
  • lint-staged 15.2.2
  • prettier 3.2.5
  • tailwindcss 3.4.3
  • typescript 5.4.5
  • vitest 1.5.0
  • tailwindcss >= 1.5
  • node >=10

  • Check this box to trigger a request for Renovate to run again on this repository

Ability to adjust the capsize spacing based on the font weight

I have been using this awesome library in a few projects, but there's always been one minor 'imperfection' I started to accept as a trade-off and for which there might be a solution.

For the default font weight, the metrics are pixel perfect. However, when the font becomes thinner or thicker, the capsize measurements for the normal font weight remain applied, instead of being able to adjust to this change. When font is bold, it's usually a bit taller, and vice versa.

Is this feasible to achieve? Could we potentially pass different font metrics for every font weight or be able to compute these based on a specific parameter and keep the changes in the config minimal? Not sure whether there's any sort of relativeness between font weights, or whether we would need unique measurements for each.

The whole idea appears to be very similar (at least I hope it is!) to how the capsize class already adjusts the spacing based on the font size.


Thank you for your work, it made transforming the designs into UIs using TailwindCSS much more predictable 💙

Build fails in JIT mode.

I love the idea for this plugin but unfortunately it throws errors during build in JIT mode.

ERROR in ./resources/styles/app.scss
Module build failed (from ./node_modules/mini-css-extract-plugin/dist/loader.js):
ModuleBuildError: Module build failed (from ./node_modules/postcss-loader/dist/cjs.js):
TypeError: plugin is not a function
    at registerPlugins (/Users/christianmagill/Code/Sites/site/wp-content/themes/site/node_modules/tailwindcss/lib/jit/lib/setupContextUtils.js:540:7)
    at createContext (/Users/christianmagill/Code/Sites/site/wp-content/themes/site/node_modules/tailwindcss/lib/jit/lib/setupContextUtils.js:583:3)
    at getContext (/Users/christianmagill/Code/Sites/site/wp-content/themes/site/node_modules/tailwindcss/lib/jit/lib/setupContextUtils.js:644:17)
    at /Users/christianmagill/Code/Sites/site/wp-content/themes/site/node_modules/tailwindcss/lib/jit/lib/setupTrackingContext.js:177:57
    at /Users/christianmagill/Code/Sites/site/wp-content/themes/site/node_modules/tailwindcss/lib/jit/processTailwindFeatures.js:54:7
    at /Users/christianmagill/Code/Sites/site/wp-content/themes/site/node_modules/tailwindcss/lib/jit/index.js:25:56
    at LazyResult.runOnRoot (/Users/christianmagill/Code/Sites/site/wp-content/themes/site/node_modules/postcss/lib/lazy-result.js:333:16)
    at LazyResult.runAsync (/Users/christianmagill/Code/Sites/site/wp-content/themes/site/node_modules/postcss/lib/lazy-result.js:385:26)
    at LazyResult.async (/Users/christianmagill/Code/Sites/site/wp-content/themes/site/node_modules/postcss/lib/lazy-result.js:215:30)
    at LazyResult.then (/Users/christianmagill/Code/Sites/site/wp-content/themes/site/node_modules/postcss/lib/lazy-result.js:200:17)
    at processResult (/Users/christianmagill/Code/Sites/site/wp-content/themes/site/node_modules/webpack/lib/NormalModule.js:700:19)
    at /Users/christianmagill/Code/Sites/site/wp-content/themes/site/node_modules/webpack/lib/NormalModule.js:806:5
    at /Users/christianmagill/Code/Sites/site/wp-content/themes/site/node_modules/loader-runner/lib/LoaderRunner.js:399:11
    at /Users/christianmagill/Code/Sites/site/wp-content/themes/site/node_modules/loader-runner/lib/LoaderRunner.js:251:18
    at context.callback (/Users/christianmagill/Code/Sites/site/wp-content/themes/site/node_modules/loader-runner/lib/LoaderRunner.js:124:13)
    at Object.loader (/Users/christianmagill/Code/Sites/site/wp-content/themes/site/node_modules/postcss-loader/dist/index.js:96:7)

Here's my config... If I remove Capsize compilation works.

module.exports = {
  // mode: 'jit',
  purge: {
    content: [
      './app/**/*.php',
      './resources/**/*.{php,vue,js}',
    ],
  },
  darkMode: false, // or 'media' or 'class'
  theme: {
    fontFamily: {
      sans: ['Inter', 'sans-serif'],
    },
    fontMetrics: {
      sans: {
        capHeight: 2048,
        ascent: 2728,
        descent: -680,
        lineGap: 0,
        unitsPerEm: 2816,
      },
    },
    aspectRatio: {
      none: 0,
      square: [1, 1],
      "16/9": [16, 9],
      "4/3": [4, 3],
      "21/9": [21, 9],
    },
    extend: {
      colors: {},
    },
  },
  variants: {
    aspectRatio: ['responsive'],
    extend: {},
  },
  plugins: [
    // require('@tailwindcss/typography'),
    // require('@tailwindcss/aspect-ratio'), // https://github.com/tailwindlabs/tailwindcss-aspect-ratio
    // require('tailwindcss-skip-link')(), // https://github.com/opdavies/tailwindcss-plugin-skip-link
    // require('tailwindcss-debug-screens'), // https://github.com/jorenvanhee/tailwindcss-debug-screens
    // require('tailwindcss-elevation')(['responsive']), // https://github.com/jonaskay/tailwindcss-elevation
    // require('@tailwindcss/line-clamp'), // https://github.com/tailwindlabs/tailwindcss-line-clamp
    require('tailwindcss-capsize'), // https://github.com/stormwarning/tailwindcss-capsize
  ],
};


Dropping support for TailwindCSS < 3

I'm considering removing the classic mode that allows this plugin to work with older versions of Tailwind.

Since the latest (and likely any future) version of Tailwind uses JIT and doesn't allow the older method of building all the styles at once, I can remove a bunch of code and ensure tests can run against the latest version. Officially, the latest version will be supported, but Tailwind v2 in JIT mode should continue to work as well.

Precision loss

if (value.endsWith('px')) return parseInt(value.replace('px', ''))

When font-size is set in fractions of pixels, precision loss happens in normaliseValue function, which enforces integers on px values via usage of parseInt. Therefore value of actualPixels is always with loss of precision.

Missing TypeScript Types

I recently switch to having a tailwind.config.ts (because you can) and i noticed that this plugin throws an error because types are not correctly generated:

image

The index.d.ts generated as the main type location specified by the package.json lacks any type definitions.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.