Giter VIP home page Giter VIP logo

styled-components-rhythm's Introduction

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): The rem font size of your root element (ie; the <body>).
  • rhythmHeight (Number): The rem vertical grid size, to which text will have its baseline aligned. Works best when it divides evenly into (baseFontSize * defaultLineHeight).
  • capHeights (Object): Map of font-family font name -> proportional height of capital letters. Heights can be calculated with this tool. For example:
    {
      Lato: 0.72,
    }
  • defaultLineHeight (Number): Default for setFontWithRhythm() 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 of setFontWithRhythm() & 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 of defaultOutputType.

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:

  1. All previous elements on the page are also correctly aligned to your vertical rhythm.
  2. You will not manually set padding-top or margin-bottom on this element.

Parameters

  • fontName (String): Should match the font name as you would declare it in the CSS property font-family.
  • fontSizeRem (Number): A multiple of baseFontSize.
  • 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 of defaultOutputType.

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.

styled-components-rhythm's People

Contributors

jesstelford 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

Watchers

 avatar

styled-components-rhythm's Issues

Correct usage of rhythmSizing? [with codesandbox]

Hey,

thanks for your great library! I am trying to include it in our design system, but I am not sure, if I use it correctly.
Now the output looks correct for me, but only because I fiddled around with the values of rhythmSizing until the different font-sizes matched my grid - which feels completely wrong.

Did I implement this correctly? I am sorry, that I can not specify my question any further :(
Thanks for any hints in the right direction!

https://codesandbox.io/s/modern-leftpad-3kw15

baseline offset?

screenshot 2019-01-27 at 11 24 42
Kudos for this neat module.

I just played around with Fira Sans. There is a one pixel offset between the actual baseline and the baseline grid. Other than that, the result looks great.

Is it possible to provide a baseline-offset?

more context

Rounding bug in line-height calculations

Given:

baseHeight: 16px
capHeight: 0.69
fontSize: 2.8rem
desiredLineHeight: 1

Will give the output:

.foo {
    font-size: 2.8rem;
    line-height: 1.0714285714285714;
}

This line-height then equates to 47.9999999996px (1.07142857142 * 2.8 * 16), which Chrome rounds to 47px, but what we really meant was 48px :(


screen shot 2018-04-19 at 11 50 53 am
with 47.9999px


screen shot 2018-04-19 at 11 51 31 am
with 48px


Note: 47.99999px rounds to 47px, but 47.999999px rounds to 48px (Chrome 65)

A possible workaround might be to use calc, (which has different rounding properties?): calc(1.0714285714285714 * (2.8 * 16px))


screen shot 2018-04-19 at 12 01 08 pm
with calc(1.0714285714285714 * (2.8 * 16px))

Usage section on readme uses old property

First off - this is an awesome module, thank you!

I've noticed that one of the property values on the readme is out of date.

The usage section refers to a baseLineHeight in the options object passed to the styledComponentsRhythm - I think it should be defaultLineHeight. It's a small point but got me lost for 20mins.

Happy to create a PR if it helps.

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.