npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

emotive

v1.2.4

Published

Dynamic "css in js" without interpolation or language injection

Downloads

67

Readme

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 |