Skip to content
Statically typed DSL for writing css in reason.
Reason C++ HTML
Branch: master
Clone or download

Latest commit

dependabot Bump acorn from 5.7.3 to 5.7.4 (#187)
Bumps [acorn](https://github.com/acornjs/acorn) from 5.7.3 to 5.7.4.
- [Release notes](https://github.com/acornjs/acorn/releases)
- [Commits](acornjs/acorn@5.7.3...5.7.4)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Latest commit dbef2ea Mar 20, 2020

Files

Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
bs-css-dom prepare for release 12.1.0 Mar 20, 2020
bs-css-emotion prepare for release 12.1.0 Mar 20, 2020
bs-css prepare for release 12.1.0 Mar 20, 2020
.gitignore #183 - Remove emotion dependency in bs-css Mar 4, 2020
CHANGELOG.md udpate CHANGELOG Mar 20, 2020
LICENSE add LICENSE (#7) Dec 19, 2017
README.md Update README for #181 (#182) Mar 4, 2020
package.json Add bs-css-emotion and bs-css-dom Mar 1, 2020
yarn.lock Bump acorn from 5.7.3 to 5.7.4 (#187) Mar 20, 2020

README.md

bs-css

Statically typed DSL for writing css in reason.

The bs-css library contains type css core definitions, it has different implementations:

  • bs-css-emotion is a typed interface to Emotion
  • bs-css-dom is a typed interface to ReactDOMRe.Style

If you know another implementation that can be added, send a link in an issue or create a PR.

Installation

npm install --save bs-css-emotion
or
yarn add bs-css-emotion

In your bsconfig.json, include "bs-css" and "bs-css-emotion" in the bs-dependencies.

You can replace bs-css-emotion with bs-css-dom in the above instructions if you prefer to use React styles.

Usage for bs-css-emotion

module Styles = {
  /* Open the Css module, so we can access the style properties below without prefixing them with Css. */
  open Css;

  let card = style([
    display(flexBox),
    flexDirection(column),
    alignItems(stretch),
    backgroundColor(white),
    boxShadow(Shadow.box(~y=px(3), ~blur=px(5), rgba(0, 0, 0, 0.3))),
    /* You can add non-standard and other unsafe style declarations using the `unsafe` function, with strings as the two arguments. */
    unsafe("-webkit-overflow-scrolling", "touch"),
    /* You can place all your theme styles in Theme.re and access as normal Reason module */
    padding(Theme.basePadding)
  ]);

  let title = style([
    fontSize(rem(1.5)),
    color(Theme.textColor),
    marginBottom(Theme.basePadding)
  ]);

  let actionButton = disabled =>
    style([
      background(disabled ? darkgray : white),
      color(black),
      border(px(1), solid, black),
      borderRadius(px(3)),
    ])
};

<div className=Styles.card>
  <h1 className=Styles.title> (ReasonReact.stringToElement("Hello")) </h1>
  <button className=Styles.actionButton(false)>
</div>

Global css

You can define global css rules with global

Css.(
  global("body", [margin(px(0))])
);

Css.(
  global("h1, h2, h3", [color(rgb(33, 33, 33))])
);

Keyframes

Define animation keyframes;

let bounce = Css.(keyframes([
  (0, [ transform( scale(0.1, 0.1) ),  opacity(0.0) ]),
  (60, [ transform( scale(1.2, 1.2) ),  opacity(1.0) ]),
  (100, [ transform( scale(1.0,1.0) ), opacity(1.0) ])
]));

let styles = Css.(style([
  animationName(bounce),
  animationDuration(2000),
  width(px(50)),
  height(px(50)),
  backgroundColor(rgb(255, 0, 0))
]));

// ...
<div className=styles>
  (ReasonReact.stringToElement("bounce!"))
</div>

Merging styles

You should avoid trying to merge styles in the same list of rules or by concatinating lists. A list of rules is converted into a JS object before being passed to Emotion where every property becomes a key in the object. This means you lose any earlier rule if you have another rule with the same property later in the list. This is especially noticable when writing sub-selectors and media queries

Trying to merge styles by just using List.concat can result in unexpected results.

This example:

let base = Css.[
  padding(px(0)),
  fontSize(px(1))
];
let overrides = Css.[
  padding(px(20)),
  fontSize(px(24)),
  color(blue)
];
let media1 = Css.[
  media("(max-width: 768px)", [
    padding(px(10))
  ])
];
let media2 = Css.[
  media("(max-width: 768px)", [
    fontSize(px(16)),
    color(red)
  ])
];
let mergedStyles = [base, overrides, media1, media2]->List.concat->Css.style;

generates the following:

.css-1nuk4bg {
  padding: 20px;
  font-size: 24px;
  color: #0000ff;
}
@media (max-width: 768px) {
  .css-1nuk4bg {
    font-size: 16px;
    color: #ff0000;
  }
}

As you can see both properties from base are overwritten (as opposed to overridden in css) and the media query in media1 is also lost because the media query from media2 overwrites it.

The merge method

merge safely merges styles by name. Uses Emotion’s cx method.

let mergedStyles =
  Css.(
    merge([
      style([
        padding(px(0)),
        fontSize(px(1))
      ]),
      style([
        padding(px(20)),
        fontSize(px(24)),
        color(blue)
      ]),
      style([
        media("(max-width: 768px)", [
          padding(px(10))
        ])
      ]),
      style([
        media("(max-width: 768px)", [
          fontSize(px(16)),
          color(red)
        ]),
      ]),
    ])
  );

Generates the following:

.css-q0lkhz {
  padding: 0px;
  font-size: 1px;
  padding: 20px;
  font-size: 24px;
  color: #0000ff;
}
@media (max-width: 768px) {
  .css-q0lkhz {
    padding: 10px;
  }
}
@media (max-width: 768px) {
  .css-q0lkhz {
    font-size: 16px;
    color: #ff0000;
  }
}

Nothing is lost and everything ends up in the final stylesheet where normal overrides apply.

Usage for bs-css-dom

Use style instead of classname, for example:

module Styles = {
  /* Open the Css module, so we can access the style properties below without prefixing them with Css. */
  open Css;

  let card = style([
    display(flexBox),
    flexDirection(column),
    alignItems(stretch),
    backgroundColor(white),
    boxShadow(Shadow.box(~y=px(3), ~blur=px(5), rgba(0, 0, 0, 0.3))),
    /* You can add non-standard and other unsafe style declarations using the `unsafe` function, with strings as the two arguments. */
    unsafe("-webkit-overflow-scrolling", "touch"),
    /* You can place all your theme styles in Theme.re and access as normal Reason module */
    padding(Theme.basePadding)
  ]);

  let title = style([
    fontSize(rem(1.5)),
    color(Theme.textColor),
    marginBottom(Theme.basePadding)
  ]);

  let actionButton = disabled =>
    style([
      background(disabled ? darkgray : white),
      color(black),
      border(px(1), solid, black),
      borderRadius(px(3)),
    ])
};

<div style=Styles.card>
  <h1 style=Styles.title> (ReasonReact.stringToElement("Hello")) </h1>
  <button style=Styles.actionButton(false)>
</div>

Where is the documentation?

You can check out Css.rei.

Thanks

Thanks to emotion which is doing all the heavy lifting.

Thanks to bs-glamor which this repo was forked from.

Thanks to elm-css for dsl design inspiration.

You can’t perform that action at this time.