0.5.5 • Published 1 year ago

stylight v0.5.5

Weekly downloads
-
License
MIT
Repository
-
Last release
1 year ago

Stylight: simple & reliable CSS-in-JS

A feature-rich CSS-in-JS module for web UI development, with minimal overhead, designed for better developer experience, granularity and simplicity.

Features and examples


  • Renders css-in-js into an actual CSS stylesheet contents, using 'csstype' compliant css-in-js definitions (camelCased style properties, e.g. React's CSSProperties)
// styles.js

import { renderStyleSheet } from 'stylight'

const styles = { menu: { borderBottom: '1px solid #000' } }

renderStyleSheet(styles)

/*

".menu {border-bottom:1px solid #000}"

*/

  • Nested style properties definition straight in JS style objects hierarchy, applying styles to children by using '& <child_id>' (see example below)
// nested_styles.js

import { renderStyleSheet } from 'stylight'

const styles = {
    menu: {
        border: '1px solid #000',
        '& div': {
            backgroundColor: 'red'
        }
    }
}

renderStyleSheet(styles)

/*

"
.menu {border:1px solid #000}
.menu div {background-color:red}
"

*/

  • Property overrides for same CSS property for different target renderer platforms
// gradient.js

import { renderStyleSheet } from 'stylight'

const styles = {

    gradient: {

        // msie
        filter:
        'progid:DXImageTransform.Microsoft.gradient(startColorstr="#23553f",endColorstr="#041316",GradientType=1)',
    
        // overriding same property more than once:
        overrides: [
            
            {
                // fallback (no gradient support)
                background: 'rgb(35,85,63)'
            },
            {
                // moz
                background:
                '-moz-linear-gradient(50deg, rgba(35,85,63,1) 1%, rgba(50,127,131,1) 55%, rgba(4,19,22,1) 100%)'
            },
            {
                // webkit
                background:
                '-webkit-linear-gradient(50deg, rgba(35,85,63,1) 1%, rgba(50,127,131,1) 55%, rgba(4,19,22,1) 100%)'
            },
            {
                // common
                background:
                'linear-gradient(50deg, rgba(35,85,63,1) 1%, rgba(50,127,131,1) 55%, rgba(4,19,22,1) 100%)'
            },
            
        ],

    }

}

renderStyleSheet(styles)

/*

(pretty)

".gradient {
    
    filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#23553f",endColorstr="#041316",GradientType=1);
    
    background:rgb(35,85,63);
    
    background:-moz-linear-gradient(50deg, rgba(35,85,63,1) 1%, rgba(50,127,131,1) 55%, rgba(4,19,22,1) 100%);
    
    background:-webkit-linear-gradient(50deg, rgba(35,85,63,1) 1%, rgba(50,127,131,1) 55%, rgba(4,19,22,1) 100%);
    
    background:linear-gradient(50deg, rgba(35,85,63,1) 1%, rgba(50,127,131,1) 55%, rgba(4,19,22,1) 100%);
    
}"

*/

  • Mixins: applying styles to global object descriptors
// mixins.js

import { renderStyleSheet } from 'stylight'

const styles = {
    foo: {
        mixins: {
            body: { margin: 'none' }
        }
    }
}

renderStyleSheet(styles)

/*

"body {margin:none}"

*/

  • Stylesheets: easily created, efficiently isolated, type completion for class name picker included!
import { createStyleSheet, styledClass } from 'stylight'

const { styledClass, render } = createStyleSheet({

    parent: { margin: 0 },
    child: { border: '1px solid #000' }

})

render() // -> ".parent {margin:0}.child {border:1px solid #000}"

// supports type completion for class name picker 
// from stylesheet property names
styledClass('parent') // -> "parent"
styledClass('child') // -> "child"

  • Stylesheets also support seeding to identify, isolate, obfuscate, compress class names, or even all at once!
import { createStyleSheet, styledClass } from 'stylight'

const { styledClass, render } = createStyleSheet(
    // stylesheet properties
    {

        parent: { margin: 0 },
        child: { border: '1px solid #000' }

    },
    // seed
    'sheet!'

    // by default, seeding algorithm for a seed of string type is `btoa(seed+className)`
    // if you want to apply another algorithm, see custom seeding callback implementation example below
)

render()
/* (pretty) 

"
.c2hlZXQhcGFyZW50 {
    margin: 0;
}

.c2hlZXQhY2hpbGQ= {
    border:1px solid #000;
}
"

*/

styledClass('parent') // -> "c2hlZXQhcGFyZW50"
styledClass('child') // -> "c2hlZXQhY2hpbGQ="

  • Seeding with a custom class name transform function
import { createStyleSheet, styledClass } from 'stylight'

const { styledClass, render } = createStyleSheet(
    // stylesheet properties
    {

        parent: { margin: 0 },
        child: { border: '1px solid #000' }

    },
    (className) => className.substring(0, 1)
)

render() // -> ".p {margin:0}.c {border:1px solid #000}"

styledClass('parent') // -> "p"
styledClass('child') // -> "c"

  • Integration plugin: React

Basic usage (shorthand)

import { renderToString } from 'react-dom/server'

import {

    // A shorthand to provide top-level style rendering context wrap
    Styled,

    // Renderer component for all received style objects during render of previous components that used `useStyle` hook
    StyleRenderer,

    // An actual hook that pushes defined styling objects into top-level context provider
    useStyle

} from 'stylight/react'

// A React component that uses styling hook
const Component = () => {

    // pass individual component's styling into top-level theme provider
    const styled = useStyle({
        obj: { border: '1px solid #000' }
    })


    // supports class names type autocompletion on-the-fly in case of using a hook
    return <div className={
        styled('obj')
    }></div>

}

// Host application that uses style rendering context
const App = () => <Styled>

    {/* Render component that uses styling hook*/}
    <Component/>

    {/* Use the actual renderer on the end of node tree in case we need to synchronously render styles without waiting for next state update & re-render */}
    <StyleRenderer/>

</Styled>

renderToString(<App/>)

/*

(pretty)

"
<div class="obj"></div>
<style>
    .obj {border:1px solid #000}
</style>
"

*/

Extended usage (exposed context):

// react_sample.jsx

import { renderToString } from 'react-dom/server'
import {

    // Creates styles appearance listener instance for styling context provider
    createStyleRenderingContext,

    // Renderer component for all received style objects during render of previous components that used `useStyle` hook
    StyleRenderer,
    
    // A top-level context that provides node tree with access to style appearance listener
    StyleRenderingContext,
    
    // An actual hook that pushes defined styling objects into top-level context provider
    useStyle

} from 'stylight/react'

// A React component that uses styling hook
const StyledComponent = () => {

    // pass individual component's styling into top-level theme provider
    const styled = useStyle({
        obj: { border: '1px solid #000' }
    })


    // supports class names type autocompletion on-the-fly in case of using a hook
    return <div className={
        styled('obj')
    }></div>

}

// Host application that uses style rendering context
const App = () =>

// Create style rendering context provider with an isolated instance of listener
<StyleRenderingContext.Provider value={createStyleRenderingContext()}>
    
    {/* Render component that uses styling hook*/}
    <StyledComponent/>
    
    {/* Use the actual renderer on the end of node tree in case we need to synchronously render styles without waiting for next state update & re-render */}
    <StyleRenderer/>

</StyleRenderingContext.Provider>

renderToString(<App/>)

/*

(pretty)

"
<div class="obj"></div>
<style>
    .obj {border:1px solid #000}
</style>
"

*/

Also

  • Made with Typescript, TOTALLY type completion friendly!

  • Almost zero-dependency: The only dependency is an actual 'csstype' module which is only a typedef package that does not affect bundle sizes at all.

  • Lightweight - minified bundle size is only around 4.4 KB, React integration plugin is about 2.5 KB of additional size.

  • Great performance. No more IDE lags during typechecks of simple stylings applied. You know what I mean if you know what I mean.

  • Integration plugins out of the box: currently only for React


Installation

npm

npm i -S stylight

This will provide stylight core package with plugins included, e.g. stylight/react

Browser (UMD)

<!-- core package -->
<script type="text/javascript" src="https://unpkg.com/stylight@0.5.5/umd/stylight.min.js"></script>
<!-- will provide Stylight UMD global -->

<!-- React plugin -->
<script type="text/javascript" src="https://unpkg.com/stylight@0.5.5/umd/stylight.react.min.js"></script>
<!-- will provide StylightReact UMD global -->

Requirements

There are two conditional requirements for this package to use.

  • Typescript >= 4.1 must be used as default TS server in case of using type completions, and installed as a devdependency for Typescript projects aswell. A package uses Template Literal Types feature introduced in this version, so earlier versions of Typescript used will most likely cause problems. However, for Javascript projects without type completions both in a project and IDE, no Typescript version requirements are applied.
  • In case of using React, versions 16 and higher are considered supported since no tests for lower versions are done. A package relies on React as an optional dependency only, in case React is actually used in a host project

TODO

  • Media queries (DOC)
  • At-rules (other than just media queries)
0.5.4

1 year ago

0.5.3

1 year ago

0.4.4

1 year ago

0.5.5

1 year ago

0.5.2

1 year ago

0.4.3

1 year ago

0.5.1

1 year ago

0.4.2

1 year ago

0.3.0

1 year ago

0.2.1

1 year ago

0.1.2

1 year ago

0.1.1

1 year ago

0.4.1

1 year ago

0.3.2

1 year ago

0.3.1

1 year ago

0.2.2

1 year ago

0.3.3

1 year ago

1.0.0

4 years ago