Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/emotion-js/facepaint
Responsive style values for css-in-js.
https://github.com/emotion-js/facepaint
css css-in-js emotion javascript
Last synced: 6 days ago
JSON representation
Responsive style values for css-in-js.
- Host: GitHub
- URL: https://github.com/emotion-js/facepaint
- Owner: emotion-js
- Created: 2017-10-22T05:03:56.000Z (about 7 years ago)
- Default Branch: master
- Last Pushed: 2022-10-09T12:50:21.000Z (about 2 years ago)
- Last Synced: 2024-12-14T02:04:49.910Z (13 days ago)
- Topics: css, css-in-js, emotion, javascript
- Language: JavaScript
- Size: 43.9 KB
- Stars: 595
- Watchers: 8
- Forks: 19
- Open Issues: 14
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
- awesome-list - facepaint - in-js. | emotion-js | 534 | (JavaScript)
- awesome-emotion - facepaint - Responsive style values for css-in-js (Libraries)
README
# facepaint
#### Dynamic style values for css-in-js.
```javascript
import { css } from 'emotion'
import facepaint from 'facepaint'const mq = facepaint([
'@media(min-width: 420px)',
'@media(min-width: 920px)',
'@media(min-width: 1120px)'
])const myClassName = css(mq({
color: ['red', 'green', 'blue', 'darkorchid'],
}))
```## Install
```bash
npm i facepaint -S
```**or**
```bash
yarn add facepaint
```## API
#### facepaint `function`
```javascript
facepaint(selectors: Array) : DynamicStyleFunction
```**Arguments**
* *breakpoints*
```javascript
const mq = facepaint([
'@media(min-width: 420px)',
'@media(min-width: 920px)',
'@media(min-width: 1120px)'
])
```* *options*
```javascript
const mq = facepaint(
[...],
{
literal: true|false,
overlap: true|false
}
)
```
- **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:
```javascript
const mq = facepaint([
'@media(min-width: 420px)'
'@media(min-width: 920px)'
], { literal: true })
const expandedStyles = mq({
color: ['red', 'green']
})
```
The output of `expandedStyles` will be:
```javascript
{
'@media(min-width: 420px)': {
color: 'red'
},
'@media(min-width: 920px)': {
color: 'green'
}
}
```
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:
```javascript
const mq = facepaint([
'@media(min-width: 420px)'
], { overlap: true })
const expandedStyles = mq({
color: ['red', 'red']
})
```
The value of `expandedStyles` would not contain any media query breakpoints. This is an optimization to remove bytes from the final code.
```javascript
{ color: 'red' }
```
vs.
```javascript
{
color: 'red',
'@media(min-width: 420px)': {
color: 'red'
}
}
```
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.
```javascript
const style1 = css(mq({ color: ['red', 'red'] }))
const style2 = css({ color: 'blue' })
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.
```javascript
{
color: 'blue',
'@media(min-width: 420px)': {
color: 'red'
}
}
```
Due to our `overlap: true` optimization however, the final output will be the following.
```javascript
{ 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](#emotion)
- [styled-components](#styled-components)
- [pseudo selectors](#pseudo-selectors)### emotion
**[CodeSandbox Demo](https://codesandbox.io/s/lxqmwmyzql)**
```javascript
import { css } from 'emotion'
import facepaint from 'facepaint'const mq = facepaint([
'@media(min-width: 420px)',
'@media(min-width: 920px)',
'@media(min-width: 1120px)'
])const myClassName = css(mq({
backgroundColor: 'hotpink',
textAlign: 'center',
width: ['25%', '50%', '75%', '100%'],
'& .foo': {
color: ['red', 'green', 'blue', 'darkorchid'],
'& img': {
height: [10, 15, 20, 25]
}
}
}))
```**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.**
```css
.css-rbuh8g {
background-color: hotpink;
text-align: center;
width: 25%;
}@media (min-width:420px) {
.css-rbuh8g {
width: 50%;
}
}@media (min-width:920px) {
.css-rbuh8g {
width: 75%;
}
}@media (min-width:1120px) {
.css-rbuh8g {
width: 100%;
}
}.css-rbuh8g .foo {
color: red;
}@media (min-width:420px) {
.css-rbuh8g .foo {
color: green;
}
}@media (min-width:920px) {
.css-rbuh8g .foo {
color: blue;
}
}@media (min-width:1120px) {
.css-rbuh8g .foo {
color: darkorchid;
}
}.css-rbuh8g .foo img {
height: 10px;
}@media (min-width:420px) {
.css-rbuh8g .foo img {
height: 15px;
}
}@media (min-width:920px) {
.css-rbuh8g .foo img {
height: 20px;
}
}@media (min-width:1120px) {
.css-rbuh8g .foo img {
height: 25px;
}
}
```### styled-components
```javascript
import styled from 'styled-components'
import facepaint from 'facepaint'const mq = facepaint([
'@media(min-width: 420px)',
'@media(min-width: 920px)',
'@media(min-width: 1120px)'
])const Div = styled('div')`
${mq({
backgroundColor: 'hotpink',
textAlign: 'center',
width: ['25%', '50%', '75%', '100%'],
'& .foo': {
color: ['red', 'green', 'blue', 'papayawhip'],
'& img': {
height: ['10px', '15px', '20px', '25px']
}
}
})};
`
```**The following css is generated.**
```css
.c0 {
background-color: hotpink;
text-align: center;
width: 25%;
}.c0 .foo {
color: red;
}.c0 .foo img {
height: 10px;
}@media (min-width:420px) {
.c0 {
width: 50%;
}
}@media (min-width:920px) {
.c0 {
width: 75%;
}
}@media (min-width:1120px) {
.c0 {
width: 100%;
}
}@media (min-width:420px) {
.c0 .foo {
color: green;
}
}@media (min-width:920px) {
.c0 .foo {
color: blue;
}
}@media (min-width:1120px) {
.c0 .foo {
color: papayawhip;
}
}@media (min-width:420px) {
.c0 .foo img {
height: 15px;
}
}@media (min-width:920px) {
.c0 .foo img {
height: 20px;
}
}@media (min-width:1120px) {
.c0 .foo img {
height: 25px;
}
}
```## Pseudo Selectors
**[CodeSandbox Demo](https://codesandbox.io/s/j5q3m3qy5)**
```javascript
import { css } from 'emotion'
import facepaint from 'facepaint'const pseudo = facepaint([':hover', ':focus', ':active'])
const myClassName = css(
pseudo({
backgroundColor: 'hotpink',
textAlign: 'center',
width: ['25%', '50%', '75%', '100%'],
'& .foo': {
color: ['red', 'green', 'blue', 'darkorchid'],
'& img': {
height: [10, 15, 20, 25]
}
}
})
)
``````css
.css-1guvnfu {
background-color: hotpink;
text-align: center;
width: 25%;
}.css-1guvnfu:hover {
width: 50%;
}.css-1guvnfu:focus {
width: 75%;
}.css-1guvnfu:active {
width: 100%;
}.css-1guvnfu .foo {
color: red;
}.css-1guvnfu .foo:hover {
color: green;
}.css-1guvnfu .foo:focus {
color: blue;
}.css-1guvnfu .foo:active {
color: darkorchid;
}.css-1guvnfu .foo img {
height: 10px;
}.css-1guvnfu .foo img:hover {
height: 15px;
}.css-1guvnfu .foo img:focus {
height: 20px;
}.css-1guvnfu .foo img:active {
height: 25px;
}
```