emotive
TypeScript icon, indicating that this package has built-in type declarations

1.2.4 • Public • Published

Emotive

Dynamic "css in js" without interpolation or language injection.

npm version

size

let myStyle = Css.sheet(
    Css.Display.BLOCK,
    Css.FontSize.em(10),
    Css.Width.px(80),
    Css.Height.AUTO,
    Css.Margin.px(20,10,10),
    Css.Border.set(Length.px(1), Keyword.SOLID, Keyword.BLACK),
    Css.Position.ABSOLUTE,
    Css.Top.cm(50),
    Css.Left.calc(Length.X(50), Length.px(-40))
);

this code is equivalent to JS object:

let myStyle = {
    display: 'block',
    fontSize: '10em',
    width: '80px',
    height: 'auto',
    margin: '20px 10px 10px',
    border: '1px solid black',
    position: 'absolute',
    top: '50cm',
    left: 'calc(50% + -40px)'
};

Install

Install with Npm

npm install --save emotive

or Yarn

yarn add emotive

Index

What does "Emotive" do?

Emotive essentially provides an easy way to write and populate any CSS property without having trouble converting javascript data types into CSS compatbile one. Furthermore it provides a complete list of ready-to-use constants and methods to compose your stylesheets without boring and confusing wrap operations, language injection or value interpolation.

That it means: "No more quotes! No more backticks!".

Do I need this?

Emotive is meant to take full advantage of javascript inline styling; that's the reason why React is the best fit framework in which to use this library.

import Css from 'emotive';
 
const fontsize = 12;
const color = '#ffeeee';
 
let fooStyle = Css.sheet(
    Css.FontSize.px(fontsize),
    Css.FontWeight.BOLDER,
    Css.Color.set(color)
);
 
export const FooComponent = (props) => (
    <span style={fooStyle}>
        Emotive is COOL!
    </span>
);

This does not mean you cannot use Emotive in any other Javascript context.

react-emotive

The npm react-emotive package provide a wrapper for the React environment to easily create "styled components" with Emotive.

import Styled from 'react-emotive';
import Css, {Color} from 'emotive';
 
const MyComp = Styled.div(
    Css.Height.px(200),
    Css.Color.BLUE,
    Css.FontSize.px(50),
    props => Css.BackgroundColor.set(props.bgColor)
);
 
const OtherComp = (props) => (
    <MyComp bgColor={Color.RED}>
        Emotive is cool with React
    </MyComp>
);

Usage

Write styles with Emotive is easy. You know CSS, you know Emotive too. In most cases it's enough to import the generic Css object and use the sheet() method to compose your styles:

import Css from 'emotive';
 
let fooStyle = Css.sheet(
    Css.Display.BLOCK,        // display: flex;
    Css.Position.ABSOLUTE,    // position: absolute;
    Css.FontSize.px(14)       // font-size: 14px;
);

sheet() essentially merges all passed object, each representing an atomic property, and creates a new single one containing all.

Properties

Every CSS property has a corrisponding Javascript object (UpperCamelCase notation) inside the global Css object.

CSS property Emotive JS object
display Css.Display
font-size Css.FontSize
border-top-width Css.BorderTopWidth
z-index Css.ZIndex

As a general rule, use <property>.set() to manually populate the corresponding property value. Remember: it doesn't matter how many parameters you use; Emotive will concat them putting a space in between. Strings and numbers are both accepted and completely interchangeable.

// these sentences are equivalent
Css.Animation.set('myAnim 5s linear 2s 3 alternate')
Css.Animation.set('myAnim 5s linear', '2s 3 alternate')
Css.Animation.set('myAnim', '5s', 'linear', '2s', 3, 'alternate')

The result of such a calls are JS style objects containing the single populated property they represents.

{ animation: 'myAnim 5s linear 2s 3 alternate' }

In fact, they are completely valid styles and can be used as stand-alone single-property sheets.

export const fooComponent = (props) => (
    <span style={Color.RED}>
        Emotive is COOL!
    </span>
);

Constants

Every CSS constant that can set as value for a property is directly available using the corresponding property sub-object (UPPER_CASE notation).

// value set manually
Css.Display.set('block')
Css.Display.set('flex')
Css.Display.set('inline-block')
 
// value set using constant
Css.Display.BLOCK
Css.Display.FLEX
Css.Display.INLINE_BLOCK

Also, all constants are always avaiable inside some JS container:

Emotive object Constants CSS Value
Keyword SOLID, TOP, NONE, ... solid, top, none, ...
Color RED, BLUE, AQUA, ... red, blue, aqua, ...
Unit PX, DEG, CM, ... px, deg, cm, ...
Property DISPLAY, MARGIN_LEFT, ... display, margin-left, ...
Element TABLE, DIV, A, ... table, div, a, ...

You may need to use some CSS constant to populate complex properties, such as border shorthand property.

import {Css, Color, Keyword, Unit } from 'emotive';
 
// these sentences are equivalent
Css.Border.set('1px solid black')
Css.Border.set(1 + Unit.PX, Keyword.SOLID, Color.BLACK)

But there's easier ways to achieve the same result. Just keep reading.

Units

Every CSS unit has a corresponding method with the same name; they are split up in 5 categories, one for every data type.

Emotive object Methods
Length px(), rem(),cm(), ...
Angle deg(), rad(), grad(), ...
Time s(), ms()
Frequency Hz(), kHz()
Resolution dpi(), dpcm(), dppx()

The only exception is the percentage unit that is avaiable too, but with the name of X(), under the Length object.

Values passed to these methods will be concatenated and the unit symbol is appended at the end of each.

import {Css, Length, Time} from 'emotive';
 
Length.cm(10) // 10cm
Time.s(10) // 10s
Length.X(50) // 50%
 
Length.px(20, 10, 15) // 20px 10px 15px
Time.ms(200, 400) // 200ms 400ms
Length.X(50, 20) // 50% 20%

Unit shorthands

Using these methods directly could make properties more difficult to write. For this reason, every emotive property object has a set of specific sub-methods (depending on the property data-type) that automatically applies the corresponding unit to all the passed arguments:

// these sentences are equivalent
Css.Padding.set(Length.X(50, 20))
Css.Padding.X(50,20)
 
// other examples
Css.Margin.cm(2,5,2,4) // margin: 2cm 5cm 2cm 4cm;
Css.Top.X(50) // top: 50%
Css.BorderSize.px(1) // border-size: 1px

Multi-value (list)

Some properties accept a "list" of values, commonly separated by commas in CSS. You can specify theme with arrays:

Css.FontFamily.set(['"Sans Extrabold"', 'sans-serif'])
// font-family: "Sans Extrabold", sans-serif;
 
Css.Transition.set(['width 2s ease', 'height 1s linear'])
// transition: width 2s ease, height 1s linear;

even with shorthands properties:

Css.Font.set(Length.em(1.2), Keyword.BOLDER, ['"Sans Extrabold"', 'sans-serif'])
// font: 1.2em bolder "Sans Extrabold", sans-serif;

If you need to specify a list of complex values, each possibly composed by many argouments, just use nested arrays:

// these sentences are equivalent
Css.Transition.set('width 2s ease, height 1s linear')
Css.Transition.set(['width 2s ease', 'height 1s linear'])
Css.Transition.set([
    [Property.WIDTH, Time.s(2), Keyword.EASE],
    [Property.HEIGHT, Time.s(1), Keyword.LINEAR]
])

Methods

Every CSS method is available as well (lowerCamelCase notation) inside a container called Method They behave similar to the properties, but passed parameters will be rendered with a comma ( , ) between them (instead of a space)

Method.rgb(255,0,0) // rgb(255,0,0);
Method.rotateX(Angle.deg(45)) // rotateX(45deg);

Again, you can use arrays to specify complex parameter (composed by many argouments)

Method.linearGradient(Keyword.TO_TOP_LEFT,
    [Color.BLUE, Length.X(50)],
    [Color.WHITE, Length.X(30)]
)
// background: linear-gradient(to top left, blue 50%, white 30%);

Calculations (calc)

As for all the other methods, CSS' calc() has its own corresponding in Emotive, but it behave slightly different from the other methods in the library.

By default, passed parameters are summed together:

Method.calc(Length.X(50), Length.px(20)) // calc(50% + 20px)
 
const customSize = 20;
Method.calc(Length.X(50), Length.px(15), Length.em(customSize)) // calc(50% + 15px + 20em)

First-level multiplications with constants can be made Javascript-side:

const customSize = 20;
Method.calc(Length.px(15), Length.em(2*customSize)) // calc(15px + 40em)

Subtractions can be written by simply negate the value to subtract:

Method.calc(Length.X(50), Length.px(-20)) // calc(50% + -20px)
 
const size1 = 20;
Method.calc(Length.X(50), Length.px(-size1)) // calc(50% + -20px)
 
// WRONG!
const size2 = Length.px(20);
Method.calc(Length.X(50), -size2) // you cannot negate a string!

Any more complex formula can be written using arrays; parameters passed inside an array are multiplied together:

Method.calc([Length.px(50), 2]) // calc(50px * 2)
 
Method.calc(Length.px(50), [Length.px(20), 2]) // calc(50% + (20px * 2))
 
Method.calc([Length.px(50), .5], [Length.px(-20), 2]) // calc((50% * .5) + (-20px * 2))

As usual, parameters passed into nested arrays restore default behavior, letting arguments to be summed toghether, and so on:

Method.calc([[Length.X(50), Length.px(-20)], 2])// calc((50px + -20px) * 2)
 
Method.calc([[Length.X(50), [2.5, Length.px(-20)]], 2])// calc((50px + (2.5 * -20px)) * 2)

Dont' forget! If you don't need to use Javascript variables inside it, it is always possible to use custom strings:

Method.calc('(50px + -20px) * 2')  // calc((50px + -20px) * 2)

Colors (hex)

Other than classic css' rgb(), rgba(), hsl() and hsla() methods, Emotive also implement two exclusive methods related to hex color format, accessible from the Color object.

hex() method just append a "sharp" # before the passed code, if not present:

// These sencences are equivalent
Color.hex('aabbcc')
Color.hex('#aabbcc')
// #abcdef;
 
// 3/4/8-digit versions
Color.hex('abc') // #ddd;
Color.hex('abcd') // #ddda;
Color.hex('aabbccdd') // #dadadacc;

hexa() method behave the same, but accept an additional decimal parameter representing the alpha value:

Color.hexa('aabbcc', 0) // #dadada00;
Color.hexa('aabbcc', .5) // #dadada7f;
Color.hexa('aabbcc', 1) // #dadadaff;
 
const myColor= Color.hex('abcdef');
Color.hexa(myColor, .25) // #abcdef3f;
Color.hexa(Color.AQUA, .75) // #abcdefbf;

Selectors

Emotive provide a set of constants and methods to create your custom selectors. With the Element object you can write every standard "HTML element" (see Constants)

Pseudo-classes

Pseudo-classes constants (UPPER_CASE notation) and methods (lowerCamelCase notation) are available in an object called Pseudo.Class.

Emotive constant/method Css value
Pseudo.Class.HOVER :hover
Pseudo.Class.FOCUS :focus
Pseudo.Class.lang('en') :lang(en)
... ...

Pseudo-elements

Pseudo-elements constants (UPPER_CASE notation) and methods (lowerCamelCase notation) are available too in an object called Pseudo.Element.

Emotive constant/method Css value
Pseudo.Element.AFTER ::after
Pseudo.Element.BEFORE ::before
Pseudo.Element.slotted('span') ::slotted(span)
... ...

Media Query

Emotive provides a complete set of methods to compose media queries, accessible using the Query object.

Media Types

Every media type is directly accessible as a constant (UPPER_CASE notation)

Emotive constant Css value
Query.ALL all
Query.SCREEN screen
Query.PRINT print
... ...

Media Features

Every media feature is directly accessible as an object (UpperCamelCase notation) The set() method is used to assign a value or simply print the feature.

Emotive method Css value
Query.Hover.set() (hover)
Query.Width.set('15px') (width: 15px)
Query.MinColor.set(10) (min-color: 10)
... ...

As for any Emotive properties object, Media Features objects provide a set of methods and constants to directly populate them with the corresponding value:

Emotive method/constants Css value
Query.Hover.HOVER (hover: hover)
Query.Width.px(15) (width: 15px)
Query.Pointer.NONE (pointer: none)
... ...

Finally, some objects provide a range() method, to easily set corresponding min- and max- features:

 
Query.MinWidth.set('15px'); // (min-width: 15px)
Query.MaxWidth.set('500px'); // (min-width: 500px)
Query.Width.range('15px', '500px'); // ((min-width: 15px) and (min-width: 500px))
 
// or using unit methods
Query.Width.range(
    Length.px(15),
    Length.px(500)
)

Query Combinators

To create more complex query use the combinators methods (lowerCamelCase notation):

Emotive method Css value
Query.and(Query.SCREEN, Query.Width.px(15)) (screen and (width: 15px))
Query.or(Query.SCREEN, Query.PRINTER) (screen, printer)
Query.not(Query.Hover) (not (hover))
Query.only(Query.PRINTER) (only printer)
... ...

Utility

Import table

Below the complete list of all the importable objects and their content.

Emotive object Content
Css Property objects. sheet() method
Method Methods
Length Length and percentage units methods
Angle Angle units methods
Time Time units methods
Frequency Frequency units methods
Resolution Resolution units methods
Keyword Keywords constants
Color Colors constants
Unit Units constants
Property Properties name constants
Query Media Queries

Readme

Keywords

Package Sidebar

Install

npm i emotive

Weekly Downloads

1

Version

1.2.4

License

ISC

Unpacked Size

2.85 MB

Total Files

6

Last publish

Collaborators

  • matteozanoncello