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

1.9.0 • Public • Published

Scoped Style

Scoped style is a next gen tiny css-in-js library to help you style your components. Use the full power of css that you are used to.

Works With

Installation

npm i scoped-style
// or
yarn add scoped-style

Usage

import scoped from 'scoped-style';
 
// for react
import React from 'react';
const styled = scoped(React.createElement);
//
 
// for Preact
import { h } from 'preact';
const styled = scoped(h);
//
 
// for Hyperapp
import { h } from 'hyperapp';
const styled = scoped(h);
//
 
// for Infernojs
import { createElement } from 'inferno-create-element';
const styled = scoped(createElement);
//
 
// define global css
styled.global`
  * {
    margin: 0;
  }
 
  html,
  body {
    width: 100%;
    height: 100%;
  }
`;
 
// and scoped css
const Button = styled('button')`
  background: ${props => (props.primary ? 'orange' : 'gray')};
  border: none;
  border-radius: 2px;
  :hover,
  :focus,
  :active {
    padding: 10px;
  }
  @media screen and (max-width: 640px) {
    background: blue;
    :hover,
    :focus,
    :active {
      padding: 5px;
    }
  }
`;
 
// keyframes
const spin = styled.keyframes`
  to {
    transform: rotate(360deg);
  }
`;
 
const Loader = styled('div')`
  border: 3px solid hsla(185, 100%, 62%, 0.2);
  border-top-color: #3cefff;
  border-radius: 50%;
  width: 2em;
  height: 2em;
  animation: ${() => spin} 1s linear infinite;
`;
 
// styling children
const BlueChildren = styled('div')`
  > * {
    color: blue;
  }
`;
 
const App = ({ children }) => (
  <div>
    <Button primary>Login</Button>
    <Loader />
    <BlueChildren>{children}</BlueChildren>
  </div>
);
 
// Your rendering code

Configuration

generateID - application code

Scoped style lets you choose the way class names are generated. This is possible via generateID method which can be replaced by your own implementation:

// <componentName>.styles.js
 
import { h } from 'preact';
import scoped from 'scoped-style';
 
// These two lines below are responsible for achieving custom class name generation
const defaultGenerateID = scoped.generateID;
scoped.generateID = () => `my-app-prefix-${defaultGenerateID()}`;
 
const styled = scoped(h);
 
export const Container = styled('section')`
  padding: 10px;
  color: #000;
`;
 
export const AppDescription = styled('h1')`
  color: #0f0f0f;
`;

Having added that you should end up with something like this:

Custom class names generation

Support and limitations

Combinators

Supported :

Not supported :

Selectors

Selectors must be used in with a combinator.

We support them all :

Pseudo selectors

We support them all.

Warning, if you are using the content property : special characters (like ) are not suppoted, you must convert them (via http://enc.joyho.net/ for example) and it will work (content: "\\25C0";).

Questions, bugs and feature requests

You have a question about usage, feel free to open an issue.

You found a bug, feel free to open an issue.

You've got a feature requests, feel free to open an issue.

Advanced example : radio button, checkbox

const Label = styled('label')`
  position: relative;
  padding-left: 2rem;
  padding-right: 0.75rem;
  margin-bottom: 0.75rem;
  cursor: pointer;
  font-size: 1rem;
  user-select: none;
 
  > input {
    position: absolute;
    opacity: 0;
    cursor: pointer;
    height: 0;
    width: 0;
  }
 
  > input[type='checkbox'] ~ span {
    position: absolute;
    top: 0.2rem;
    left: 0;
    height: 1rem;
    width: 1rem;
    background-color: #eee;
  }
 
  > input[type='radio'] ~ span {
    position: absolute;
    top: 0.2rem;
    left: 0;
    height: 1rem;
    width: 1rem;
    background-color: #eee;
    border-radius: 50%;
  }
 
  :hover > input ~ span {
    background-color: #ccc;
    transition: 0.2s;
  }
 
  > input:checked ~ span {
    background-color: #0080b3;
  }
 
  :active > span {
    transform: scale(0);
  }
 
  > span:after {
    content: '';
    position: absolute;
    display: none;
  }
 
  > input:checked ~ span:after {
    display: block;
  }
 
  > input[type='checkbox'] ~ span:after {
    left: 0.25rem;
    top: 0.05rem;
    width: 0.25rem;
    height: 0.6rem;
    border: solid white;
    border-width: 0 0.2rem 0.2rem 0;
    transform: rotate(45deg);
  }
 
  > input[type='radio'] ~ span:after {
    left: 0.3rem;
    top: 0.3rem;
    width: 0.4rem;
    height: 0.4rem;
    border-radius: 50%;
    background: white;
  }
`;
 
const Radio = ({ name, checked, onChange }) => (
  <Label>
    {name}
    <input type="radio" checked={checked} onChange={onChange} />
    <span></span>
  </Label>
);
 
const Checkbox = ({ name, checked, onChange }) => (
  <Label>
    {name}
    <input type="checkbox" checked={checked} onChange={onChange} />
    <span></span>
  </Label>
);

Scoped function second parameter

import scoped from 'scoped-style';

scoped can take a second parameter : a callback who "render" the css generated by styled function.

The default callback is exported via scoped.defaultCallback.

SSR example

Client :

import { createElement } from 'inferno-create-element';
import scoped from './scoped-style';
 
if (typeof global !== 'undefined') {
  global.scopedStyleCSS == '';
}
 
const styler = css => {
  if (typeof document !== 'undefined') {
    scoped.defaultCallback(css);
  } else if (typeof global !== 'undefined') {
    global.scopedStyleCSS += css;
  }
};
 
export const styled = scoped(createElement, styler);

Server :

app.get('*', (req, res) => {
  // first render the root component to string via the SSR function of your framework
  const content = renderToString(<App {...props} />);
  res.send(`
    <!DOCTYPE html>
    <html>
 
    <head>
      <meta name="viewport" content="width=device-width, height=device-height, initial-scale=1">
      <meta content="text/html; charset=utf-8">
      <title>
        Citral
      </title>
      <style type="text/css">
        ${global.scopedStyleCSS /* then use the generated styles string */}
      </style>
    </head>
 
    <body>
      ${content}
      <script type="text/javascript" src="${fs
        .readdirSync(path.join(__dirname, 'client'))
        .find(file => /^[a-z0-9]+\.bundle\.js$/.test(file))}"></script>
    </body>
 
    </html>
  `);
});

Readme

Keywords

none

Package Sidebar

Install

npm i scoped-style

Weekly Downloads

5

Version

1.9.0

License

MIT

Unpacked Size

28.5 kB

Total Files

5

Last publish

Collaborators

  • sadick254