CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-emotion

Framework-agnostic CSS-in-JS library for generating styles, animations, and global CSS

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

Emotion

Emotion is a performant and flexible CSS-in-JS library designed for writing CSS styles with JavaScript. It provides a framework-agnostic API for generating class names, animations, global styles, and composing CSS with optimized performance and great developer experience.

Package Information

  • Package Name: emotion
  • Package Type: npm
  • Language: JavaScript/TypeScript
  • Installation: npm install emotion

Core Imports

import { css, cx, injectGlobal, keyframes } from "emotion";

For CommonJS:

const { css, cx, injectGlobal, keyframes } = require("emotion");

For Babel macro (compile-time optimization):

import { css, cx, injectGlobal, keyframes } from "emotion/macro";

Basic Usage

import { css, cx, keyframes, injectGlobal } from "emotion";

// Generate CSS class name
const buttonStyle = css`
  background-color: hotpink;
  font-size: 24px;
  border-radius: 4px;
  padding: 8px 12px;
  &:hover {
    color: white;
  }
`;

// Apply styles to element
const button = document.createElement('button');
button.className = buttonStyle;
button.textContent = 'Click me';

// Compose class names
const activeStyle = css`
  font-weight: bold;
  border: 2px solid blue;
`;
button.className = cx(buttonStyle, isActive && activeStyle);

// Create animations
const bounce = keyframes`
  from, 20%, 53%, 80%, to {
    transform: translate3d(0,0,0);
  }
  40%, 43% {
    transform: translate3d(0, -30px, 0);
  }
`;

// Inject global styles
injectGlobal`
  * {
    box-sizing: border-box;
  }
  body {
    margin: 0;
    font-family: sans-serif;
  }
`;

Architecture

Emotion is built around several core concepts:

  • Style Generation: The css function transforms style inputs into unique class names
  • Style Composition: The cx function provides intelligent class name merging with emotion-aware precedence
  • Global Styling: injectGlobal allows injection of global styles into the document head
  • Animation Support: keyframes generates unique animation names for CSS animations
  • Caching System: Internal cache manages style deduplication and performance optimization
  • Multiple Input Formats: Supports template literals, objects, and arrays for maximum flexibility

Capabilities

CSS Generation

The core functionality for creating CSS class names from various style inputs.

/**
 * Generates CSS class names from style inputs
 * @param template - Template literal or style arguments
 * @param args - Interpolated values for template literals
 * @returns Generated CSS class name
 */
function css(template: TemplateStringsArray, ...args: Array<Interpolation>): string;
function css(...args: Array<Interpolation>): string;

String Styles (Template Literals):

const redText = css`
  color: red;
  font-size: 16px;
  &:hover {
    color: darkred;
  }
`;

// With interpolation
const color = 'blue';
const dynamicStyle = css`
  color: ${color};
  font-size: ${props => props.large ? '24px' : '16px'};
`;

Object Styles:

const buttonStyle = css({
  backgroundColor: 'hotpink',
  fontSize: 24,
  borderRadius: 4,
  '&:hover': {
    color: 'white'
  }
});

// With dynamic properties
const conditionalStyle = css({
  display: 'flex',
  color: isError ? 'red' : 'black',
  fontSize: isLarge ? 20 : 14
});

Array of Styles:

const combinedStyle = css([
  {
    backgroundColor: 'hotpink',
    fontSize: 24
  },
  isActive && {
    fontWeight: 'bold'
  },
  `
    border-radius: 4px;
    &:hover {
      opacity: 0.8;
    }
  `
]);

Class Name Composition

Intelligent composition of class names with emotion-aware precedence handling.

/**
 * Composes class names with proper precedence handling
 * @param classNames - Class name arguments (strings, objects, arrays)
 * @returns Composed class name string
 */
function cx(...classNames: Array<ClassNamesArg>): string;

Basic Composition:

const baseStyle = css`
  color: black;
  font-size: 16px;
`;

const activeStyle = css`
  color: blue;
  font-weight: bold;
`;

// Emotion-aware composition (activeStyle will override baseStyle color)
const combinedClass = cx(baseStyle, isActive && activeStyle);

Conditional Styles:

const buttonClass = cx(
  baseButtonStyle,
  {
    [primaryStyle]: isPrimary,
    [dangerStyle]: isDanger,
    [disabledStyle]: isDisabled
  },
  'external-class-name'
);

Array Composition:

const composedClass = cx([
  baseStyle,
  conditionalStyle,
  isSpecial && specialStyle
]);

Global Styles

Injection of global CSS styles into the document.

/**
 * Injects global styles into the document head
 * @param template - Template literal or style arguments
 * @param args - Interpolated values for template literals
 */
function injectGlobal(template: TemplateStringsArray, ...args: Array<Interpolation>): void;
function injectGlobal(...args: Array<Interpolation>): void;

Template Literal Global Styles:

injectGlobal`
  * {
    box-sizing: border-box;
  }
  
  body {
    margin: 0;
    font-family: 'Helvetica Neue', sans-serif;
    background-color: #f5f5f5;
  }
  
  @font-face {
    font-family: 'CustomFont';
    src: url('./fonts/custom.woff2') format('woff2');
  }
`;

Object Global Styles:

injectGlobal({
  '*': {
    boxSizing: 'border-box'
  },
  body: {
    margin: 0,
    fontFamily: 'sans-serif'
  }
});

Animation Keyframes

Creation of CSS animation keyframes with unique naming.

/**
 * Generates unique animation names for CSS keyframes
 * @param template - Template literal or keyframe arguments
 * @param args - Interpolated values for template literals
 * @returns Unique animation name for use in CSS
 */
function keyframes(template: TemplateStringsArray, ...args: Array<Interpolation>): string;
function keyframes(...args: Array<Interpolation>): string;

Template Literal Keyframes:

const fadeIn = keyframes`
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
`;

const animatedElement = css`
  animation: ${fadeIn} 0.5s ease-in-out;
`;

Object Keyframes:

const slideIn = keyframes({
  '0%': {
    transform: 'translateX(-100%)'
  },
  '100%': {
    transform: 'translateX(0)'
  }
});

const slidingElement = css({
  animation: `${slideIn} 0.3s ease-out`
});

Complex Animations:

const bounce = keyframes`
  from, 20%, 53%, 80%, to {
    transform: translate3d(0,0,0);
  }
  40%, 43% {
    transform: translate3d(0, -30px, 0);
  }
  70% {
    transform: translate3d(0, -15px, 0);
  }
  90% {
    transform: translate3d(0, -4px, 0);
  }
`;

Cache Management

Low-level cache and stylesheet management functions.

/**
 * Clears all generated styles and resets the cache
 */
function flush(): void;

/**
 * Hydrates server-rendered styles on the client
 * @param ids - Array of style IDs to mark as server-rendered
 */
function hydrate(ids: Array<string>): void;

/**
 * Internal emotion cache instance
 */
const cache: EmotionCache;

/**
 * Low-level stylesheet interface
 */
const sheet: StyleSheet;

/**
 * Merges class names with registered styles
 * @param className - Class name to merge
 * @returns Merged class name
 */
function merge(className: string): string;

/**
 * Retrieves registered styles for class names
 * @param registeredStyles - Array to populate with registered styles
 * @param className - Class name to look up
 * @returns Raw class name
 */
function getRegisteredStyles(registeredStyles: Array<string>, className: string): string;

Server-Side Rendering:

// Server-side: collect style tags
const { html, ids, css } = renderToString(<App />);

// Client-side: hydrate
hydrate(ids);

Cache Management:

// Clear all styles (useful for testing)
flush();

// Access low-level sheet
sheet.speedy(false); // Disable fast insertion for debugging

Types

/**
 * Any valid style interpolation value
 */
type Interpolation = any;

/**
 * Valid class name arguments for cx function
 */
type ClassNamesArg =
  | undefined
  | null
  | string
  | boolean
  | { [className: string]: boolean | null | undefined }
  | ArrayClassNamesArg;

/**
 * Array of class name arguments
 */
interface ArrayClassNamesArg extends Array<ClassNamesArg> {}

/**
 * Emotion cache interface for storing styles and metadata
 */
interface EmotionCache {
  registered: { [key: string]: string };
  inserted: { [key: string]: boolean };
  sheet: StyleSheet;
  key: string;
}

/**
 * Low-level stylesheet interface
 */
interface StyleSheet {
  insert(rule: string): void;
  flush(): void;
  speedy(value: boolean): void;
  tags: Array<HTMLStyleElement>;
  isSpeedy: number;
  ctr: number;
}

/**
 * Object-based style interpolation
 */
interface ObjectInterpolation {
  [key: string]: any;
}

/**
 * Array-based style interpolation
 */
interface ArrayInterpolation extends Array<Interpolation> {}

/**
 * Function-based style interpolation
 */
interface FunctionInterpolation {
  (props?: any): Interpolation;
}

/**
 * Component selector for styled components
 */
interface ComponentSelector {
  __emotion_styles: any;
}

Babel Macro

Emotion provides a Babel macro for compile-time optimizations:

// Import from macro for build-time optimizations
import { css, cx, keyframes, injectGlobal } from "emotion/macro";

// Same API, but with compile-time CSS extraction and optimization
const optimizedStyle = css`
  color: red;
  font-size: 16px;
`;

Benefits of Babel Macro:

  • Build-time CSS extraction
  • Smaller bundle sizes
  • Improved runtime performance
  • Source map support
  • Better debugging experience

Error Handling

Emotion gracefully handles various edge cases:

  • Invalid styles: Falsy values are ignored in object styles
  • Type coercion: Boolean values are converted appropriately
  • Auto-prefixing: Vendor prefixes are added automatically
  • Duplicate styles: Cache prevents style duplication
  • Memory management: Styles can be flushed when needed

Performance Features

  • Heavy caching: Styles are cached to prevent regeneration
  • Fast insertion: Optimized DOM insertion in production
  • Style deduplication: Identical styles share class names
  • Lazy evaluation: Styles are only generated when needed
  • Memory efficient: Unused styles can be garbage collected

Install with Tessl CLI

npx tessl i tessl/npm-emotion
Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/emotion@10.0.x
Publish Source
CLI
Badge
tessl/npm-emotion badge