• Stars
    star
    698
  • Rank 64,841 (Top 2 %)
  • Language
    TypeScript
  • License
    MIT License
  • Created almost 10 years ago
  • Updated about 3 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Make CSS easier and more maintainable by using JavaScript

Free-Style

NPM version NPM downloads Build status Test coverage Bundle size

Free-Style is designed to make CSS easier and more maintainable by using JavaScript.

Installation

npm install free-style --save

Why?

There's a great presentation by Christopher Chedeau you should check out.

Solved by using CSS in JS

  • No global variables (What and where is .button? Why is it conflicting?)
  • Defined dependency systems (CommonJS, Require.js, <script />)
  • Dead code elimination automatically removes unused styles
  • Minification through JavaScript tooling
  • Shared constants and reusable styles
  • Every style is isolated, tested and namespaced to the JS component
  • Extensible - everything from Math to color manipulation already exists!

Also solved with Free-Style

  • Works with third-party DOM components (You can nest regular .class-name in your styles)
  • Consistently generates styles and class names, and will automatically merge duplicate styles
  • Develop components alongside the style (No more hunting CSS files for estranged ul > li > a)
  • Create universal applications and serve styles for only the components rendered (see React Free-Style)
  • Use the CSS you already know ({ '&:hover': { ... } })
  • Automatically namespace @-rule styles ({ '@media (min-width: 500px)': { ... } })
  • Overload CSS properties using arrays ({ backgroundColor: ['red', 'linear-gradient(to right, red 0%, blue 100%)'] })
  • Small and powerful API that works with any ecosystem (~360 SLOC)

But How?

Free-Style generates a consistent hash from the style, after alphabetical property ordering and formatting, to use as the class name. This allows duplicate styles to automatically be merged on duplicate hashes. Every style is "registered" and assigned to a variable, which gets the most out of linters that will warn on unused variables and features like dead code minification. Using "register" returns the class name used for the Style instance and style instances (returned by create()) can be merged together at runtime to output only the styles on page (e.g. React Free-Style). Styles should usually be created outside of the application run loop (e.g. render()) so the CSS string and hashes are only generated once.

Ways to Use

  • typestyle - Popular type-safe interface for working with CSS
  • react-free-style - React implementation that renders styles on the current page (for universal apps)
  • stylin - Simplest abstraction for creating styles, rules, and keyframes, and keeps <style /> in sync
  • ethcss - Library for writing CSS with literal objects
  • This module! - Manually create, compose and manipulate style instances

Usage

var FreeStyle = require("free-style");

// Create a stylesheet instance.
var Style = FreeStyle.create();

// Register a new style, returning a class name to use.
var backgroundStyle = Style.registerStyle({
  backgroundColor: "red",
}); //=> "f14svl5e"

// Inject `<style>` into the `<head>`.
var styleElement = document.createElement("style");
styleElement.textContent = Style.getStyles();
document.head.appendChild(styleElement);

// Render the style by using the class name.
React.render(
  <div className={backgroundStyle}>Hello world!</div>,
  document.body
);

Style

var buttonStyle = Style.registerStyle({
  $displayName: "button",
  backgroundColor: "red",
  padding: 10,
});

console.log(buttonStyle); //=> "button_f65pi0b"

Tip: The string returned by registerStyle is a unique hash of the content and used as the HTML class name. The $displayName is only used during development, and stripped in production (process.env.NODE_ENV === 'production').

Overload CSS Properties

Style.registerStyle({
  background: [
    "red",
    "-moz-linear-gradient(left, red 0%, blue 100%)",
    "-webkit-linear-gradient(left, red 0%, blue 100%)",
    "-o-linear-gradient(left, red 0%, blue 100%)",
    "-ms-linear-gradient(left, red 0%, blue 100%)",
    "linear-gradient(to right, red 0%, blue 100%)",
  ],
}); //=> "f1n85iiq"

Nested Rules

Style.registerStyle({
  color: "red",
  "@media (min-width: 500px)": {
    //=> "@media (min-width: 500px){.fk9tfor{color:blue}}"
    color: "blue",
  },
}); //=> "fk9tfor"

Nested Selectors

Style.registerStyle({
  color: "red",
  ".classy": {
    //=> ".fc1zv17 .classy"
    color: "blue",
  },
}); //=> "fc1zv17"

Parent Selector Reference

Style.registerStyle({
  color: "red",
  "&:hover": {
    //=> ".f1h42yg6:hover"
    color: "blue",
  },
}); //=> "f1h42yg6"

Tip: The ampersand (&) will be replaced by the parent selector at runtime.

Use JavaScript

const ellipsisStyle = {
  whiteSpace: "nowrap",
  overflow: "hidden",
  textOverflow: "ellipsis",
};

const redEllipsisStyle = Style.registerStyle({
  color: "red",
  ...ellipsisStyle,
}); //=> "fvxl8qs"

// Share rule between styles using computed properties.
const mediaQuery = "@media (min-width: 400px)";

const style = Style.registerStyle({
  backgroundColor: "red",
  [mediaQuery]: {
    backgroundColor: "pink",
  },
});

Unique Style Output

Sometimes you need to skip the de-duping behavior of free-style. Use $unique to force separate styles:

Style.registerStyle({
  color: "blue",
  "&::-webkit-input-placeholder": {
    color: `rgba(0, 0, 0, 0)`,
    $unique: true,
  },
  "&::-moz-placeholder": {
    color: `rgba(0, 0, 0, 0)`,
    $unique: true,
  },
  "&::-ms-input-placeholder": {
    color: `rgba(0, 0, 0, 0)`,
    $unique: true,
  },
}); //=> "f13byakl"

Style.getStyles(); //=> ".f13byakl{color:blue}.f13byakl::-webkit-input-placeholder{color:rgba(0, 0, 0, 0)}.f13byakl::-moz-placeholder{color:rgba(0, 0, 0, 0)}.f13byakl::-ms-input-placeholder{color:rgba(0, 0, 0, 0)}"

Rules

const colorAnimation = Style.registerStyle({
  $global: true,
  "@keyframes &": {
    from: { color: "red" },
    to: { color: "blue" },
  },
}); //=> "h1j3ughx"

const style = Style.registerStyle({
  animationName: colorAnimation,
  animationDuration: "1s",
}); //=> "fibanyf"

Global Rules

Style.registerStyle({
  $global: true,
  "@font-face": {
    fontFamily: '"Bitstream Vera Serif Bold"',
    src: 'url("https://mdn.mozillademos.org/files/2468/VeraSeBd.ttf")',
  },
});

Style.registerStyle({
  $global: true,
  "@media print": {
    body: {
      color: "red",
    },
  },
});

Style.registerStyle({
  $global: true,
  body: {
    margin: 0,
    padding: 0,
  },
});

Global Styles

Style.registerStyle({
  $global: true,
  body: {
    margin: 0,
    padding: 0,
    "@print": {
      color: "#000",
    },
  },
  h1: {
    fontSize: "2em",
  },
});

CSS String

Style.getStyles(); //=> ".f65pi0b{background-color:red;padding:10px}"

Useful Libraries

Implementation Details

Debugging

Display names will automatically be removed when process.env.NODE_ENV === "production".

Changes

The only argument to create() is a map of change function handlers. All functions are required:

  • add(style: Container<any>, index: number)
  • change(style: Container<any>, oldIndex: number, newIndex: number)
  • remove(style: Container<any>, index: number)

All classes implement Container, so you can call getStyles(), clone() or get id.

Other Properties and Methods

var OtherStyle = Style.create();

Style.merge(OtherStyle); // Merge the current styles of `OtherStyle` into `Style`.
Style.unmerge(OtherStyle); // Remove the current styles of `OtherStyle` from `Style`.

Legacy Browsers

Version 3 requires support for class, see #82. As of April 2020, that's 95% of browsers. You can import from free-style/dist.es5 for a version compatible with ES5 (IE 11).

License

MIT

More Repositories

1

code-problems

Common code and interview problems solved in multiple languages
JavaScript
3,811
star
2

change-case

Convert strings between camelCase, PascalCase, Capital Case, snake_case and more
TypeScript
2,050
star
3

atom-dash

Dash documentation integration with Atom
CoffeeScript
394
star
4

tslint-config-standard

A TSLint config for JavaScript Standard Style
JavaScript
358
star
5

sql-template-tag

ES2015 tagged template string for preparing SQL statements, works with `pg`, `mysql`, and `sqlite`
TypeScript
343
star
6

co-mocha

Enable support for generators in Mocha tests
JavaScript
216
star
7

react-free-style

Make React components easier and more maintainable by using inline style objects
TypeScript
137
star
8

javascript-stringify

Stringify is to `eval` as `JSON.stringify` is to `JSON.parse`
TypeScript
133
star
9

compose-middleware

Compose an array of middleware into a single function for use in Express, Connect, router, etc
TypeScript
91
star
10

array-flatten

Flatten a multi-dimensional array in JavaScript.
JavaScript
87
star
11

writing

New posts will be on Substack
TypeScript
74
star
12

make-error-cause

Make your own nested errors
TypeScript
66
star
13

node-language-detect

Detect the programming language of any file in JavaScript
JavaScript
56
star
14

dombars

*DEPRECATED* DOM-based templating library with data-binding and built on Handlebars
JavaScript
51
star
15

language-map

JSON version of the programming language map used in Linguist
JavaScript
50
star
16

node-htmlmetaparser

A `htmlparser2` handler for parsing rich metadata from HTML. Includes HTML metadata, JSON-LD, RDFa, microdata, OEmbed, Twitter cards and AppLinks.
HTML
50
star
17

async-middleware

Wrap an asynchronous middleware (or handler) function for Express, Connect, router, etc.
TypeScript
49
star
18

metalsmith-pagination

A Metalsmith plugin for paginating arrays and collections
JavaScript
34
star
19

readable

Make articles readable again
JavaScript
33
star
20

keyboard-manager

Small keyboard shortcut management for DOM-based applications
TypeScript
30
star
21

stylus-type-utils

Stylus typography functions and type conversion
CSS
29
star
22

universal-base64

Small universal base64 functions for node.js and browsers
TypeScript
28
star
23

simulate-event

A library for triggering DOM events.
JavaScript
24
star
24

highlighter

Add syntax highlighting to all files, with built-in syntax highlighting of diffs and patches
JavaScript
21
star
25

node-numbered

Stringify any number into words, and parse number strings back to a number
JavaScript
20
star
26

deque

JavaScript implementation of a double-ended queue
TypeScript
18
star
27

node-immigration

Simple, no-frills migration utility
TypeScript
17
star
28

arity

Set the length of a function in JavaScript
JavaScript
17
star
29

iterative

Functions for working with iterators in JavaScript and TypeScript
TypeScript
17
star
30

node-module-template

My standard node module template
JavaScript
17
star
31

universal-base64url

Small universal base64url functions for node.js and browsers
TypeScript
16
star
32

code-challenge

Command line interface for running code challenges
JavaScript
16
star
33

is-generator

Check whether a given value is a generator function
JavaScript
15
star
34

kroute

Modular Koa router middleware with Express-style routes and middleware mounting
JavaScript
15
star
35

js-functools

Utilities for working with functions in JavaScript, with TypeScript
TypeScript
14
star
36

dotfiles

My OS X config
Ruby
13
star
37

decorator-debug

Simple ES7 decorator for debugging classes and methods
TypeScript
13
star
38

decorator-cache-getter

Simple decorator for caching getters on first access
TypeScript
13
star
39

just-css-properties

An array of all known browser CSS properties
JavaScript
12
star
40

typescript-simple-loader

Feature complete TypeScript loader for webpack
TypeScript
12
star
41

nary

Force a functions arity in JavaScript
TypeScript
12
star
42

metalsmith-snippet

A Metalsmith plugin for extracting snippets from files.
JavaScript
11
star
43

sql-type

Type-safe SQL builder using ES2015 template tags
TypeScript
11
star
44

react-location

Light-weight and universal react routing
TypeScript
11
star
45

atom-alignment

Align selections for Atom `⌘⌥^ ]`
CoffeeScript
10
star
46

react-route

React Location with Path-to-RegExp
TypeScript
9
star
47

promise-finally

Simple wrapper to run promise "finally" logic
TypeScript
7
star
48

variadic

A JavaScript utility for creating variadic functions
JavaScript
7
star
49

retest

Request driven library for testing node.js HTTP servers
JavaScript
7
star
50

node-dombarsify

DOMBars pre-compilation plugin for Browserify.
JavaScript
6
star
51

partial

A functional utility for doing partial application in JavaScript
JavaScript
6
star
52

decorator-when

Simple ES7 decorator for short-cutting method execution
TypeScript
6
star
53

style-helper

Small helpers for working with CSS-in-JS
TypeScript
6
star
54

node-ranged

The missing JavaScript range function
JavaScript
6
star
55

decorator-memoize-one

Simple decorator for caching the result of a function based on the most recent arguments
TypeScript
6
star
56

metalsmith-collections-paginate

[DEPRECATED] Use https://github.com/blakeembrey/metalsmith-pagination
JavaScript
5
star
57

setvalue

Set a nested value from an object by path
TypeScript
5
star
58

dedent-tag

ES2015 tagged template string for removing indent from strings
TypeScript
5
star
59

a-brief-history-of-types-with-typescript

Talk for SF TS Meetup (2018-11-08)
5
star
60

base64url

Base64 URL for node.js buffers
TypeScript
5
star
61

server-address

Listen to a randomly available port and resolve urls relative to the server address
TypeScript
5
star
62

invoke

Functional utility for invoking the same method on every call in JavaScript
JavaScript
5
star
63

getvalue

Get a nested value from an object by path
TypeScript
5
star
64

back-row

A media server for watching movies and shows in a browser, streamed directly from a server
TypeScript
5
star
65

js-template

Fast and simple string templates
TypeScript
5
star
66

code-challenge-euler

Run Project Euler challenges in the command line
JavaScript
4
star
67

co-retest

Simple wrapper for the retest library for co-like interfaces (node.js generators)
JavaScript
4
star
68

node-exiftool2

Wrapper for efficiently working with `exiftool`
TypeScript
3
star
69

token-hash

Generate base64url encoding from the left-most half of the hash of a token.
TypeScript
3
star
70

map-pointer

Map from one object to another using JSON pointers
TypeScript
3
star
71

node-language-command

Look up the command for executing a program in any language
JavaScript
3
star
72

each

Iterate over an object, array or string in JavaScript
JavaScript
3
star
73

authwith

Re-usable authentication library
TypeScript
3
star
74

blakeembrey.me

Personal placeholder page and resume
CSS
3
star
75

node-language-detect-exec

Automatically execute a file in a known programming language using node
JavaScript
3
star
76

filter

Filter an object, array or string in JavaScript
JavaScript
2
star
77

typescript-talk

Presentation on TypeScript
HTML
2
star
78

node-alignment

Naive alignment of a block with variable assignments in JavaScript
TypeScript
2
star
79

hydra-buttons

Consistent cross-browser button implementation
JavaScript
2
star
80

node-immigration-rethinkdb

RethinkDB adapter for immigration
TypeScript
2
star
81

node-language-exec

Execute a file in any programming language using node
JavaScript
2
star
82

hydra-input-groups

Simple groups for inputs and buttons
JavaScript
2
star
83

hydra-form

Simple form style resets and beautification
JavaScript
2
star
84

node-trimmer

Quick module to trim any characters from either side of a string.
JavaScript
2
star
85

exif-date

Parse an EXIF date string into a `Date` object
TypeScript
1
star
86

hydra-code

Simple CSS reset for code blocks.
JavaScript
1
star
87

envify-config

Browserify transform for replacing process.env variables with the config module settings.
JavaScript
1
star
88

hasvalue

Check if a value exists at a nested property path
TypeScript
1
star
89

node-language-spawn

Spawn a file process in any programming language using node
JavaScript
1
star
90

code-challenge-n-queens

Solve various n-queens problems in the terminal
JavaScript
1
star
91

hydra-typography

Simple default typography and font style decisions
JavaScript
1
star
92

node-string-token

Generate a random token of length and characters
TypeScript
1
star
93

get-headers

Retrieve all HTTP(s) headers as an object with original casing
TypeScript
1
star
94

map

Map over an object, array or string in JavaScript
JavaScript
1
star
95

node-bit-string-mask

Mask a string using bits from an input number
TypeScript
1
star
96

node-language-detect-spawn

Automatically spawns a file in a known programming language using node
JavaScript
1
star
97

hydra-grid

Powerful fluid grid generator for Stylus and CSS
JavaScript
1
star
98

popsicle-proxy-agent

Enable proxy support for Popsicle (for node)
TypeScript
1
star