项目作者: emotion-js

项目描述 :
Responsive style values for css-in-js.
高级语言: JavaScript
项目地址: git://github.com/emotion-js/facepaint.git
创建时间: 2017-10-22T05:03:56Z
项目社区:https://github.com/emotion-js/facepaint

开源协议:

下载


facepaint

Dynamic style values for css-in-js.

  1. import { css } from 'emotion'
  2. import facepaint from 'facepaint'
  3. const mq = facepaint([
  4. '@media(min-width: 420px)',
  5. '@media(min-width: 920px)',
  6. '@media(min-width: 1120px)'
  7. ])
  8. const myClassName = css(mq({
  9. color: ['red', 'green', 'blue', 'darkorchid'],
  10. }))

Install

  1. npm i facepaint -S

or

  1. yarn add facepaint

API

facepaint function

  1. facepaint(selectors: Array<Selector>) : DynamicStyleFunction

Arguments

  • breakpoints

    1. const mq = facepaint([
    2. '@media(min-width: 420px)',
    3. '@media(min-width: 920px)',
    4. '@media(min-width: 1120px)'
    5. ])
  • options

    1. const mq = facepaint(
    2. [...],
    3. {
    4. literal: true|false,
    5. overlap: true|false
    6. }
    7. )
    • literal boolean (Default: false) - output should match arguments given to facepaint exactly

      By default, the first value in a value array is applied without a media query or selector and the rest of the values are applied as children of media queries or selectors. When literal is set to true the values given to a specific css property mapped 1:1 with the arguments provided to facepaint.

      Given the following:

      1. const mq = facepaint([
      2. '@media(min-width: 420px)'
      3. '@media(min-width: 920px)'
      4. ], { literal: true })
      5. const expandedStyles = mq({
      6. color: ['red', 'green']
      7. })

      The output of expandedStyles will be:

      1. {
      2. '@media(min-width: 420px)': {
      3. color: 'red'
      4. },
      5. '@media(min-width: 920px)': {
      6. color: 'green'
      7. }
      8. }

      The output is missing any styles on the base style object because the values are mapped to the arguments supplied to facepaint literally.

  • overlap boolean (Default: false) - overlap values that occur in multiple media queries or slots

    Given the following:

    1. const mq = facepaint([
    2. '@media(min-width: 420px)'
    3. ], { overlap: true })
    4. const expandedStyles = mq({
    5. color: ['red', 'red']
    6. })

    The value of expandedStyles would not contain any media query breakpoints. This is an optimization to remove bytes from the final code.

    1. { color: 'red' }

    vs.

    1. {
    2. color: 'red',
    3. '@media(min-width: 420px)': {
    4. color: 'red'
    5. }
    6. }

    The downside of enabling this option is that when attempting to overwrite the value of color in another style definition the expected media query will be missing.

    1. const style1 = css(mq({ color: ['red', 'red'] }))
    2. const style2 = css({ color: 'blue' })
    3. const composedStyles = css(style1, style2)

    style1‘s output will NOT contain the media query and value for red at 420px due to the overlap: true optimization.

    The developer that created composedStyles might expect the following output.

    1. {
    2. color: 'blue',
    3. '@media(min-width: 420px)': {
    4. color: 'red'
    5. }
    6. }

    Due to our overlap: true optimization however, the final output will be the following.

    1. { color: 'blue' }

Returns

facepaint returns a function that can be exported and used throughout
your app to dynamically style based on your provided selectors.

  • The function accepts any number of arrays or objects as arguments.
  • Nested arrays are flattened.
  • Boolean, undefined, and null values are ignored.

Examples

emotion

CodeSandbox Demo

  1. import { css } from 'emotion'
  2. import facepaint from 'facepaint'
  3. const mq = facepaint([
  4. '@media(min-width: 420px)',
  5. '@media(min-width: 920px)',
  6. '@media(min-width: 1120px)'
  7. ])
  8. const myClassName = css(mq({
  9. backgroundColor: 'hotpink',
  10. textAlign: 'center',
  11. width: ['25%', '50%', '75%', '100%'],
  12. '& .foo': {
  13. color: ['red', 'green', 'blue', 'darkorchid'],
  14. '& img': {
  15. height: [10, 15, 20, 25]
  16. }
  17. }
  18. }))

Note that the first value is considered a default value and is not a child of a media query at-rule.

The following css is generated.

  1. .css-rbuh8g {
  2. background-color: hotpink;
  3. text-align: center;
  4. width: 25%;
  5. }
  6. @media (min-width:420px) {
  7. .css-rbuh8g {
  8. width: 50%;
  9. }
  10. }
  11. @media (min-width:920px) {
  12. .css-rbuh8g {
  13. width: 75%;
  14. }
  15. }
  16. @media (min-width:1120px) {
  17. .css-rbuh8g {
  18. width: 100%;
  19. }
  20. }
  21. .css-rbuh8g .foo {
  22. color: red;
  23. }
  24. @media (min-width:420px) {
  25. .css-rbuh8g .foo {
  26. color: green;
  27. }
  28. }
  29. @media (min-width:920px) {
  30. .css-rbuh8g .foo {
  31. color: blue;
  32. }
  33. }
  34. @media (min-width:1120px) {
  35. .css-rbuh8g .foo {
  36. color: darkorchid;
  37. }
  38. }
  39. .css-rbuh8g .foo img {
  40. height: 10px;
  41. }
  42. @media (min-width:420px) {
  43. .css-rbuh8g .foo img {
  44. height: 15px;
  45. }
  46. }
  47. @media (min-width:920px) {
  48. .css-rbuh8g .foo img {
  49. height: 20px;
  50. }
  51. }
  52. @media (min-width:1120px) {
  53. .css-rbuh8g .foo img {
  54. height: 25px;
  55. }
  56. }

styled-components

  1. import styled from 'styled-components'
  2. import facepaint from 'facepaint'
  3. const mq = facepaint([
  4. '@media(min-width: 420px)',
  5. '@media(min-width: 920px)',
  6. '@media(min-width: 1120px)'
  7. ])
  8. const Div = styled('div')`
  9. ${mq({
  10. backgroundColor: 'hotpink',
  11. textAlign: 'center',
  12. width: ['25%', '50%', '75%', '100%'],
  13. '& .foo': {
  14. color: ['red', 'green', 'blue', 'papayawhip'],
  15. '& img': {
  16. height: ['10px', '15px', '20px', '25px']
  17. }
  18. }
  19. })};
  20. `
  21. <Div></Div>

The following css is generated.

  1. .c0 {
  2. background-color: hotpink;
  3. text-align: center;
  4. width: 25%;
  5. }
  6. .c0 .foo {
  7. color: red;
  8. }
  9. .c0 .foo img {
  10. height: 10px;
  11. }
  12. @media (min-width:420px) {
  13. .c0 {
  14. width: 50%;
  15. }
  16. }
  17. @media (min-width:920px) {
  18. .c0 {
  19. width: 75%;
  20. }
  21. }
  22. @media (min-width:1120px) {
  23. .c0 {
  24. width: 100%;
  25. }
  26. }
  27. @media (min-width:420px) {
  28. .c0 .foo {
  29. color: green;
  30. }
  31. }
  32. @media (min-width:920px) {
  33. .c0 .foo {
  34. color: blue;
  35. }
  36. }
  37. @media (min-width:1120px) {
  38. .c0 .foo {
  39. color: papayawhip;
  40. }
  41. }
  42. @media (min-width:420px) {
  43. .c0 .foo img {
  44. height: 15px;
  45. }
  46. }
  47. @media (min-width:920px) {
  48. .c0 .foo img {
  49. height: 20px;
  50. }
  51. }
  52. @media (min-width:1120px) {
  53. .c0 .foo img {
  54. height: 25px;
  55. }
  56. }

Pseudo Selectors

CodeSandbox Demo

  1. import { css } from 'emotion'
  2. import facepaint from 'facepaint'
  3. const pseudo = facepaint([':hover', ':focus', ':active'])
  4. const myClassName = css(
  5. pseudo({
  6. backgroundColor: 'hotpink',
  7. textAlign: 'center',
  8. width: ['25%', '50%', '75%', '100%'],
  9. '& .foo': {
  10. color: ['red', 'green', 'blue', 'darkorchid'],
  11. '& img': {
  12. height: [10, 15, 20, 25]
  13. }
  14. }
  15. })
  16. )
  1. .css-1guvnfu {
  2. background-color: hotpink;
  3. text-align: center;
  4. width: 25%;
  5. }
  6. .css-1guvnfu:hover {
  7. width: 50%;
  8. }
  9. .css-1guvnfu:focus {
  10. width: 75%;
  11. }
  12. .css-1guvnfu:active {
  13. width: 100%;
  14. }
  15. .css-1guvnfu .foo {
  16. color: red;
  17. }
  18. .css-1guvnfu .foo:hover {
  19. color: green;
  20. }
  21. .css-1guvnfu .foo:focus {
  22. color: blue;
  23. }
  24. .css-1guvnfu .foo:active {
  25. color: darkorchid;
  26. }
  27. .css-1guvnfu .foo img {
  28. height: 10px;
  29. }
  30. .css-1guvnfu .foo img:hover {
  31. height: 15px;
  32. }
  33. .css-1guvnfu .foo img:focus {
  34. height: 20px;
  35. }
  36. .css-1guvnfu .foo img:active {
  37. height: 25px;
  38. }