Strip out spacing above and below the first and last lines of a text block
npm install leading-trim
Strip out spacing above and below the first and last lines of a text block
---
By default text elements include vertical space based on its line-height
value. The effect of that extra space may be overlooked or worked around, but
when working with precise scales and layout components, there's probably no room
for random spacing going around your text.
leading-trim is a JavaScript port of EightShapes's
Text Crop mixin
(source). It returns a _CSS
styles object_ ready to be used with any CSS-in-JS library that let's you inject
styles with nested pseudo-elements.

``sh
npm install leading-trim
yarn add leading-trim
`
leading-trim exports a set of functions:
Use it when you're setting your font-family to a custom @font-face
`jsx
import { leadingTrim } from "leading-trim";
leadingTrim({
lineHeight: 1.5, // unitless line-height that you want for the text@font-face
reference: { // reference numbers for the you'll usefont-size
fontSize: 40, // in pxline-height
lineHeight: 1, // unitless `
topCrop: 5, // height to remove from the top in px
bottomCrop: 6, // height to remove from the bottom in px
},
correction: { // (optional) adjust the cropping result
top: 1, // a positive value shortens the crop
bottom: -1, // a negative value expands the crop
},
});
Use them when you're setting your font-family to a typical system font stack:
`css`
body: {
fontfamily: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
}
The reference numbers are already set for this one so you don't have to.correction
Naturally different operative systems will use different fonts, so it's a close
approximation, you can still use for your use-case:
`jsx
import { systemFontLeadingTrim } from "leading-trim";
systemFontLeadingTrim({
lineHeight: 1.5, // unitless line-height that you want for the text`
correction: { // (optional) adjust the cropping result
top: 1, // a positive value shortens the crop
bottom: -1, // a negative value expands the crop
},
})
Same as above but for a monospace font-family stack:
`css`
body: {
fontfamily: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
}
`jsx
import { systemMonoFontReference } from "leading-trim";
systemMonoFontReference({
lineHeight: 1.5, // unitless line-height that you want for the text`
correction: { // (optional) adjust the cropping result
top: 1, // a positive value shortens the crop
bottom: -1, // a negative value expands the crop
},
})
If the reference numbers were correctly matched, you probably won't needcorrection numbers different than -1 or 1.
The output of the above functions is a JS object ready to be used in a CSS-in-JS
library of your choice:
`json`
{
"display": "block",
"lineHeight": 1.5,
"&::after": {
"marginTop": "calc(-0.375em - 1px + -1px)",
},
"&::before": {
"marginBottom": "calc(-0.375em - 1px + 1px)",
},
"&::before, &::after": {
"content": "\\"\\"",
"display": "block",
"height": 0,
"paddingTop": "1px",
"width": 0,
}
}
The code above will work with any font size automatically so it's up to you
if you want to provide it along or just let the element inherit the one from the
parent element.
Check the examples for a more realistic usage.
Disclaimer: My weapon of choice is React so the examples are only
based on that, feel free to PR some other examples using other libraries.
#### Using a custom font
1. Use the EightShapes's
Text Crop mixin tool to obtain the
reference numbers (I got the best results using a line height of 1 and a> 32px
font size)lineHeight
2. Pass your and the reference numbers from the previous step toleadingTrim
the function
3. Inject the styles object that the function outputs using your prefered
CSS-in-JS library
#### Using a system font
Pass your lineHeight to the systemFontLeadingTrim
function and inject the styles object that the function outputs using your
prefered CSS-in-JS library.
To be able to calculate the size of the top and bottom crop for any given
line-height. It's basicaly a rule of 3 so it needs something to compare.
You'll need different reference numbers for each font-family you use (notfont-weights
needed for different as font height is not changing in that
case).
The EightShapes's Text Crop mixin tool
makes it a really easy to get it working fast.
I started learning about this technique when I saw it applied in SEEK's
Braid Design System, since
then I've seen other resources that may help you wrap your head around the
issue:
- michaeltaranto/basekick
- Line-height Crop - a simple CSS formula to remove top space from your text
- EightShapes's Text Crop mixin intro article
- Getting to the bottom of line height in Figma
- How to Tame Line Height in CSS
There's a
a CSS proposal to address this natively using the leading-trim property.
This is not trying to pollyfill that property proposal at all, but it does have
a matching purpose:
> By using
> leading-trim`
> to strip out the spacing above the cap height and below the alphabetic
> baseline, centering the box actually centers the text; and does so reliably,
> regardless of what font is used to render it.
---
Built with TypeScript using tsdx