Skip to content

B-Teague/morpho

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

38 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Morpho

Small and beautiful CSS-in-JS library

Features

  • Tiny - 1.6 kb
  • Framework Agnostic - use with Hyperapp, React, Vue, Angular or anything that has a class attribute
  • Uniquely scoped class names: .morpho-nnbflx
  • Custom css class name prefixing: .article-header-xj38d
  • Custom default numerical units: 5 -> 5em
  • Vendor Prefixing {-webkit-box-direction: normal; box-direction: normal;}
  • List values: [width, 2] -> transition: width 2s;
  • @media queries @media (max-width: 450px){}
  • @keyframes @keyframes morpho-nnbflx {}
  • Nesting .morpho-dx8a25 {} h1 .morpho-dx8a25 {}
  • Dynamic Prop values props => ({color: props.color})
  • Pseudo Selectors and elements .morpho-5tqubj:hover {}
  • Combinators .morpho-ra155c + .morpho-ra155c {}
  • Styled Components styled("div", { borderRadius: "5px" })
    • Style Unstyled Components styled(Button, { color: "tomato" })
    • Extend Styled Components styled(GreenButton, { fontSize: 10 })

Setup

Install morpho library

npm i morpho

With a module bundler like Rollup or Webpack, import morpho into your application

import morpho from "morpho"

If a bundler is not being used, morpho can be imported in a <script> tag as a module.

<script type="module">
  import morpho from "https://unpkg.com//to be determined//"
</script>

Getting Started

const options = {} //See options below

const { css, keyframes } = morpho(options);

const generatedClassName = css({
  color: "blue"
})

//Hyperapp
const Component = (props, children) => {
  return h("div", {class: generatedClassName}, children)
}

//React
const Component = (props) => {
  return <div className={generatedClassName}>Hello World</div>
}

//Vue
<div v-bind:class="[activeClass]"></div>
data: {
  activeClass: generatedClassName,
}

//Angular
<div [ngClass]="{[generatedClassName]: true}">

Options

{
  prefix: "morpho"
  unit: "em",
  cssProps: {
    border: {
      vendor: ["-webkit-", "-moz-"],
      unit: "%"
    }
  }
}
  • prefix - This option is used to specific the global custom prefix for generated css class names. Can be overridden by each css function call css({}, "customPrefix"). Default value is "morpho".

  • unit - This option is used to specify the global default numerical unit. Examples include: "%", "rem", or "px". Default value is "px".

  • cssProps - Use this option to fully customize how each css property will apply vendor prefixing or default numerical values. For example, if you want the css property transition to use the "-webkit-" prefix and a default unit in milliseconds "ms", you would initialize this option to:

    cssProps: {
      transition: {
        vendor: ["-webkit-"], //Accepts and applies a list of vendor prefixes
        unit: "ms" //Appends a unit to a numerical value.  Ex: 5 -> 5ms
      }
    }

    Note: cssProps will override settings from morpho-vendor and morpho-unit

  • Uniquely scoped class names

    .morpho-nnbflx
  • Styled components

    • For any framework that supports JSX or exposes an h() function, you can use the morpho-style library to create styled components
    import { morpho } from "morpho"
    const { css, keyframes } = morpho(options);
    
    import {morphoStyle} from "morpho-style"
    const {styled} = morphoStyle(css, h, styleOptions) //Requires morpho's css function and the JSX h function
    
    const Button = styled("div", {
      margin: "1em",
      padding: "0.25em 1em",
      borderRadius: "3px"
    });
  • Vendor Prefixing

    • If you wish to support vendor prefixing, you can use the morpho-vendor library which has a predefined list of css properties based on data from browserlist and mdn-browser-compat-data
    import { morpho } from "morpho"
    import { vendorProps } from "morpho-vendor"
    
    const { css, keyframes } = morpho({vendorProps});
    
    const vendorClassName = css({
      boxDirection: "normal"
    })
    .morpho-en4vga {
      -webkit-box-direction: normal;
      box-direction: normal;
    }
  • Custom default units

    • If you want morpho to default numerical values with unit, you can use the predefined list from morpho-unit. Note - This list currently only contains css properties that are unitless. The global default will append "px". Todo - Add additional default units to several css properties based on CSS Best Practices
    import { morpho } from "morpho"
    import { unitProps } from "morpho-unit"
    
    const { css, keyframes } = morpho({cssProps: unitProps});
    
    const vendorClassName = css({
      border: 5
    })
    .morpho-en4vga {
     border: 5px;
    }
  • Extend a component

    const GreenButton = styled(Button, {
      color: "tomato",
    });
  • Style an unstyled component

    const Button = (props) => h("div", {class: props.class}, props.children);
    
    const OrangeButton styled(Button, {
      backgroundColor: "orange"
    })
  • Custom class name prefixing

    const Fancy = styled("div", {
        borderRightWidth: 5
    },"article-header")
    
    const className = css({borderRightWidth: 5}, "article-header")
    .article-header-nnbflx
  • Media queries

    @media (max-width: 450px) {
      .morpho-yi32xy {
        font-size: 32px;
      }
    }
  • Keyframes

    keyframes({
      from: {
        transform: 'scale(2)'
      },
      to: {
        transform: 'scale(4)'
      },
    })
    @keyframes morpho-nnbflx {
      from {
        transform: scale(2);
      }
    
      to {
        transform: scale(4);
      }
    }
  • Numeric values

    const Fancy = styled("div", {
      width: 5,
      columns: 10
    })
  • List of values

    const Fancy = styled("div", {
      transition: ["width", 2]
    })
    .morpho-ta4jzb {
      -webkit-transition: width 2s;
      transition: width 2s;
    }
  • Repeat properties using nested arrays

    const Fancy = styled("div", {
      position: [["-webkit-sticky"], ["sticky"]]
    })
    .morpho-ta4jzb {
      position: -webkit-sticky;
      position: sticky;
    }
  • Nesting

    const Fancy = styled("div", {
      width: 5,
      "h1 &": {
        color: "orange",
        tag: {
          fontSize: "21px",
          "& h2": {
            border: "5px"
          }
        }
      }
    })
    .morpho-dx8a25 {width: 5%;}
    h1 .morpho-dx8a25 {color: orange;}
    h1 .morpho-dx8a25 tag {font-size: 21px;}
    h1 .morpho-dx8a25 tag .morpho-dx8a25 h2 {border: 5px;}
  • Dynamically set css values from props

    const Button = styled("div", props => ({
      color: props.myColor || "green",
      width: props.size || "5px"
    }))
    Button({ myColor: "orange", size: "20px" });
    .morpho-qbjka {
      color: orange;
      width: 20px;
    }
  • Pseudo selectors and elements

    const Link = styled("div", {
      color: "blue",
      "&:hover": {
        color: "red"
      }
    })
    .morpho-5tqubj:hover {
      color: red;
    }
    .morpho-5tqubj {
      color: blue;
    }
  • Combinators

    const Fancy = styled("div", {
      color: "#123456",
      "& + &": {
        color: "#32AB71"
      }
    })
    .morpho-ra155c + .morpho-ra155c {
      color: #32AB71;
    }
    .morpho-ra155c {
      color: #123456;
    }

Credits

A lot of inspiration and work for this library comes from Picostyle. Some of the work I added to Picostyle including css export is also found here.

Differences between morpho and picostyle

Morpho adds a lot of additional features that are not found in Picostyle including: list values, default numeric units, vendor prefixing, nesting, and dynamic values from props.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published