12px vertical rhythm with correctly aligned baselines
Styled Components Rhythm
Beautifully aligned type with Styled Components
Installation
npm i @ceteio/styled-components-rhythm
or, with yarn:
yarn add @ceteio/styled-components-rhythm
Usage
import { ThemeProvider, injectGLobal }, styled from 'styled-components';
import styledComponentsRhythm from '@ceteio/styled-components-rhythm';
const rhythm = styledComponentsRhythm({
baseFontSize: 1, // 1rem. Browser default makes this 16px
baseLineHeight: 1.2, // unitless line-height, see: https://css-tricks.com/almanac/properties/l/line-height/#comment-1587658
rhythmHeight: 0.75, // rem units. With browser default, this is 16px * 0.75rem == 12px
capHeights: {
// Calculated with https://codepen.io/sebdesign/pen/EKmbGL?editors=0011
Lato: 0.72,
},
debug: true,
});
injectGLobal`
/* Reset global margins and padding */
h1, p {
margin: 0;
padding: 0;
}
/* Using Lato font https://fonts.google.com/specimen/Lato */
@import url('https://fonts.googleapis.com/css?family=Lato')
${rhythm.global()}
`;
const H1 = styled.h1`
${props => props.theme.setFontWithRhythm('Lato', 3)}
margin-top: ${props => props.theme.rhythmSizing(3)}rem;
`;
const Paragraph = styled.p`
${props => props.theme.setFontWithRhythm('Lato', 1)}
margin-top: ${props => props.theme.rhythmSizing(2)}rem;
`;
export default () => (
<ThemeProvider theme={rhythm.theme}>
<H1>Hello world</H1>
<Paragraph>How are you today?</Paragraph>
<Paragraph>Feeling quite <em>aligned</em>!</Paragraph>
</ThemeProvider>
);
API
Creating Rhythm
The main export is a function which returns a rhythm object suitable for
adding to a Styled Components <ThemeProvider>
:
import styledComponentsRhythm from '@ceteio/styled-components-rhythm';
const rhythm = styledComponentsRhythm(options);
// { theme: ..., global: ... }
options
(Object
)
-
baseFontSize
(Number
): Therem
font size of your root element (ie; the<body>
). -
rhythmHeight
(Number
): Therem
vertical grid size, to which text will have its baseline aligned. Works best when it divides evenly into (baseFontSize
*defaultLineHeight
). -
capHeights
(Object
): Map offont-family
font name -> proportional height of capital letters. Heights can be calculated with this tool. For example:{ Lato: 0.72, }
-
defaultLineHeight
(Number
): Default forsetFontWithRhythm()
below. Must be a unitless value, which will be relative to the font size of an element. -
debug
(Boolean
): Will inject red horizontal lines to body for visually debugging alignments. -
defaultOutputType
(String
): Set the output type ofsetFontWithRhythm()
&global()
.'string'
: Return a css string .'object'
: Return a css style object. Default:'string'
.
Setting the theme
There are two pieces to the puzzle, both of which must be used to have effective
vertical rhythm; rhythm.theme
, and rhythm.global
:
import styledComponentsRhythm from '@ceteio/styled-components-rhythm';
import { injectGlobal, ThemeProvider } from 'styled-components';
const rhythm = styledComponentsRhythm(options);
injectGlobal`${rhythm.global()}`;
return <ThemeProvider theme={rhythm.theme}>...</ThemeProvider>;
theme
(Object
)
Pass this object to a Styled Components ThemeProvider
as the theme:
const rhythm = styledComponentsRhythm(options);
return <ThemeProvider theme={rhythm.theme}>...</ThemeProvider>;
global([outputType]) => String
A string containing global CSS that needs to be applied. Best done using
styled-component's injectGlobal
:
const rhythm = styledComponentsRhythm(options);
injectGlobal`${rhythm.global()}`;
or Emotion's <Global>
component:
<Global styles={rhythm.global('object')} />
Parameters
-
outputType
(String
):'string'
: Return a css string.'object'
: Return a css style object. Default: the value ofdefaultOutputType
.
Using the theme values
You now have access to the following via the theme
prop within a styled
component:
rhythmHeight
The value as passed when creating the theme object.
setFontWithRhythm(fontName, fontSizeRem[, desiredLineHeight[, outputType]]) => String
The main function which will generate the CSS necessary to correctly align the font to a rhythm baseline.
This function makes 2 assumptions:
- All previous elements on the page are also correctly aligned to your vertical rhythm.
- You will not manually set
padding-top
ormargin-bottom
on this element.
Parameters
-
fontName
(String
): Should match the font name as you would declare it in the CSS propertyfont-family
. -
fontSizeRem
(Number
): A multiple ofbaseFontSize
. -
desiredLineHeight
(Number
): Will be rounded to the nearest rhythm line so you don't have to worry. -
outputType
(String
):'string'
: Return a css string.'object'
: Return a css style object. Default: the value ofdefaultOutputType
.
The output is the CSS string to add to the component:
const H1 = styled.h1`
${props => props.theme.setFontWithRhythm('Lato', 3)}
`;
Or as an object using the css prop (in both Styled Components & Emotion):
const H1 = props => (
<h1 css={theme => theme.setFontWithRhythm('Lato', 3, 1, 'object')} />
);
rhythmSizing(multiple) => Number
A simple helper to calculate multiple * rhythmHeight
.
Works great for setting margins or padding:
const H1 = styled.h1`
margin-top: ${props => props.theme.rhythmSizing(3)}rem;
`;
Related Projects
-
capsize
by Seek: "Using font metadata, text can now be sized according to the height of its capital letters while trimming the space above capital letters and below the baseline." -
basekick
by Michael Taranto is another implementation of the same thing, targeted at LESS. - https://www.w3.org/TR/css-rhythm-1/ is a proposal to support vertical rhythm directly in CSS.