Giter Site home page Giter Site logo

glamor's Introduction

glamor

Join the chat at https://gitter.im/glamor-css/Lobby

build status

css in your javascript

npm install glamor --save

usage

import { css } from 'glamor'

// make css rules
let rule = css({
  color: 'red',
  ':hover': {
    color: 'pink'
  },
  '@media(min-width: 300px)': {
    color: 'green',
    ':hover': {
      color: 'yellow'
    }
  }
})

// add as data attributes
<div {...rule} {...another}>
  zomg
</div>

// or as classes
<div className={`${rule} ${another}`}>
  zomg
</div>

// merge rules for great justice
let mono = css({
  fontFamily: 'monospace'
})

let bolder = css({
  fontWeight: 'bolder'
})

<div {...css(mono, bolder)}>
  bold code!
</div>

motivation

This expands on ideas from @vjeux's 2014 css-in-js talk. We introduce an api to annotate arbitrary dom nodes with style definitions ("rules") for, um, the greater good.

features

  • fast / efficient, with a fluent api
  • framework independent
  • adds vendor prefixes / fallback values
  • supports all the pseudo :classes/::elements
  • @media queries
  • @supports statements
  • @font-face / @keyframes
  • escape hatches for parent / child / contextual selectors
  • dev helper to simulate pseudo classes like :hover, etc
  • server side / static rendering
  • tests / coverage
  • experimental - write real css, with syntax highlighting and linting

(thanks to BrowserStack for providing the infrastructure that allows us to run our build in real browsers.)

docs

extras

speedy mode

there are two methods by which the library adds styles to the document -

  • by appending css 'rules' to a browser backed stylesheet. This is really fast, but has the disadvantage of making the styles uneditable in the devtools sidebar.
  • by appending text nodes to a style tag. This is fairly slow, but doesn't have the editing drawback.

as a compromise, we enable the former 'speedy' mode NODE_ENV=production, and disable it otherwise. You can manually toggle this with the speedy() function.

characteristics

while glamor shares most common attributes of other inline style / css-in-js systems, here are some key differences -

  • uses 'real' stylesheets, so you can use all css features.
  • rules can be used as data-attributes or classNames.
  • simulate pseudo-classes with the simulate helper. very useful, especially when combined when hot-loading and/or editing directly in devtools.
  • really fast, by way of deduping rules, and using insertRule in production.

todo

profit, profit

I get it

glamor's People

Contributors

arunoda avatar christopherbiscardi avatar donaldpipowitch avatar electerious avatar emmatown avatar fhelwanger avatar gitter-badger avatar jlesquembre avatar jozanza avatar kamilwaheed avatar kripod avatar kryops avatar kyleamathews avatar maxdeviant avatar mayase avatar mjackson avatar natew avatar otbe avatar renatorib avatar rszewczyk avatar sarbbottam avatar seldo avatar shikharkapoor avatar threepointone avatar timdeschryver avatar timdorr avatar tsriram avatar vdanchenkov avatar vutran avatar yamafaktory avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

glamor's Issues

Warn about usage for animation

I just tried to use it for animation and ended up with a pile of silly css rules 😹

<div {...style({ width: x })}/>

I guess we need to show a dev warning for this case. I can address it later when I got better feel of the library.

benchmarks

  • number of rules that can be appended per second
  • renderStaticOptimized vs renderStatic stats

Error trying to load babel plugin react-hot-loader/babel

I installed using --save and you have react-hot-loader specified as a dev-dep. Unless I explicitly install it I get:

ERROR in ./~/glamor/lib/index.js
Module build failed: ReferenceError: Unknown plugin "react-hot-loader/babel" specified in "/Users/tshugart/Sites/skatejs/skatejs.github.io/node_modules/glamor/package.json.env.development" at 0, att
empted to resolve relative to "/Users/tshugart/Sites/skatejs/skatejs.github.io/node_modules/glamor"

I could be wrong but it seems that since I'm in "development" it seems your babel env config gets loaded, but since dev deps aren't installed, it can't find the plugin specified in there.

Not sure the best way to fix this without compromising dev ergonomics on your end. You could specify react-hot-loader as a standard dependency so that it's picked up in dev mode for consumers. Thoughts?

alternatives to 'pretty' classnames

because we use the data attribute name purely as an indexing scheme and don't 'accept' names in our function calls, we don't generate 'pretty' classnames, which might make debugging hard. keeping this issue open for alternate solutions.

Specificity confusion in Glamor with multiple inlined style/media

I have a div that I'm adding some styles too:

        <div
          {...style({
            paddingTop: rhythm(1),
            textAlign: 'center',
            maxWidth: 960,
            margin: '0 auto',
          })}
          {...media(presets.tablet, {
            paddingTop: rhythm(3),
          })}
        >

The media paddingTop should always win but when it's at rhythm(3) (Typography.js helper function) it doesn't but if I change it to rhythm(3.5) it does.

Screenshots from chrome devtools:

rhythm(3.0)
screen shot 2016-09-16 at 2 55 47 pm

rhythm(3.5)
screen shot 2016-09-16 at 2 56 14 pm

It looks like it's just the hash length for the media query attribute that's changing?

Allow definition of global styles with objects and helpers

Currently we can do

insertRule('html, body { padding: 0 }')

It would be great to support same definition as in createElement helper. Something like:

global('html, body', { padding: 0 })
global('a', [ { color: 'red'}, hover({ color: 'blue' }) ])

TypeError: undefined is not an object (evaluating 'this.sheet.insertRule') on mobile safari

This error occurs in only on our (sourcegraph.com) production set up, when glamor is in speedy mode. If its relevant, we also use TypeScript.

This can be reproduced in latest Safari and Chrome on iOS 10.0.1 on iPad and iPhone.

It does not appear to be an issue on some other mobile devices, e.g., Nexus 5x / Chrome.

This is the JS error I am getting on my iPad in Safari:

3f5c9cb0-802c-11e6-8be3-898359706305

For now, we've disabled speedy mode, but it is, of course slower.

Hover stops working on resize [chrome]

This could easily be something in my setup, but I created a Codepen pen to kick the tires of glamor by porting my Aphrodite example/pen and I noticed the following:

Hovering over "This turns red on hover" works until I resize the Codepen preview divider and/or sometimes the entire browser window (or DevTools pane).

It's odd as sometimes I can reproduce it consistently on 1 resize (especially the Codepen preview divider) and sometimes it takes a while (10+ resizes). Takes a refresh to restore hovering after I cause the issue.

This also seems to occur in the Debug mode of the pen, but it took a lot of resizing to reproduce.

linting

dev only linting would be nice

performance considerations

parent issue/scratchpad for all things perf

things that can affect performance

  • many rules
  • many unused rules
  • hashing
  • large ranges of rules in short period of time (like animations, or app startup)

things to lookout for

  • selector performance
  • cpu cycles
  • memory / gc pressure
  • redraws/reflows

things that can help

  • static optimizations (#2)
  • recover unused rules
  • cache cache cache

typescript/flow annotations

once the hairball is refactored, must consider adding flow and/or ts typings to the lib. because apparently that's a thing now.

keeping this issue open for the same. please contribute!

"other" frameworks

frameworks that use jsx/virtual dom should be able to use this out of the box. however, not sure how to apply these data attributes in angular/ember templates. keeping this issue open to investigate; please help/contribute!

Flash of unstyled content

I’ve found that when the React tree is rendered there is a flash of unstyled content with just the React HTML and without the glamor styles. Is there a suggestion on how to fix this?

Great library by the way! I think this approach makes use of the best of all other CSS-in-JS approaches.

Edge cases

I've tested some edge cases and here is what we have currently:

style({})
// returns 
{ 'data-css-120drhm': '*' }
// inserts to stylesheet
'[data-css-120drhm] { null }'

select(' a', {})
// returns 
{ 'data-css-p8xeo9': '*' }
// inserts
'[data-css-p8xeo9] a { null }'

merge()
// returns 
{ 'data-css-120drhm': '[]' }
// inserts nothing to stylesheet

merge({})
// returns 
{ 'data-css-11ra3p3': '[{:}]' }
// inserts nothing to stylesheet

media('()', {})
// returns
{ 'data-css-11qittp': '*mq({:})' }
// inserts to stylesheet 
`
@media (){
      [data-css-11qittp] { null }
}`

media('()')
// returns 
{ 'data-css-1853dek': '*mq()' }
// inserts nothing to stylesheet

keyframes('bounce', {})
// returns 
'bounce_nc5hzc'
// inserts to stylesheet 
`
@-webkit-keyframes bounce_nc5hzc { }
@-moz-keyframes bounce_nc5hzc { }
@-o-keyframes bounce_nc5hzc { }
@keyframes bounce_nc5hzc { }
`

fontFace({})
// returns
undefined 
// inserts nothing to stylesheet

fontFace({fontStyle: 'normal'})
// returns
undefined 
// inserts to stylesheet
'@font-face { font-style:normal;}'

cssFor()
// returns 
''
// inserts nothing to stylesheet

attribsFor()
// returns 
''
// inserts nothing to stylesheet

I suggest:

  1. For style/select/merge/media invocations from above return empty object. Add nothing to stylesheet.
  2. Keyframes - keep as is
  3. fontFace - current behaviour looks bad, but I'm not sure how to fix it.
  4. cssFor and attribsFor are fine

memory leak for styles that change across many values

since we generate/add css rules to the dom as soon they're computed, style objects that change over many different values will leave behind unused rules in the dom. while there exists a function remove to remove rules based on the generated hash/refs, I can't think of a simple way to expose it. Hopefully this is an edge case and doesn't affect many people. If so, the recommendation is to use use regular style prop for styles that change over many different values.

of note: this problem is not unique to this lib.

hot loading opts

hot loading 'works' right now, but it does reinsert unneeded rules into the sheet. must fix.

container queries

parent issue for container queries.

  • what's the perf profile for such a thing?
  • what does it add to glamor's weight? can it be a separate module?
  • etc etc

feel free to add/discuss stuff here.

animation helpers redux

[no promises on this, just tracking possible solutions]

glamor used to have a keyed function that would let you define rules that would be replaced when it was redefined on the same key. this made it possible to 'reclaim' rules that weren't being 'used', with the onus on the developer to manage these keys. It was meant to be a helper for people wanting to use css for animations (not just @keyframes). however, it crippled glamor's internal design, and made it hard to optimize for the larger set of use cases.

That said, there is a small set of use cases where it useful (eg - aphrodite/#141), so maybe we can make a separate module that does just this?

warn if :hover has precedence than :active

via #33, some good feedback on how these selectors depend on their specificity. we should be able to warn users if they get the order wrong.

:active must always be more specific then :hover and so they must be ordered appropriately in the style sheet

cli for extracting css from a module

the goal is to make these work -
glamor ./src/app.js -cc ./src/app.css #css only
glamor -./src/app.js -d lib #html/css/ids
cat src/*.js | glamor | jq #pipe in and out

alternatives/validation to async batching updates

I'm unwilling to async-ify the application of styles like aphrodite, but I'm willing to figure out alternatives -

  • is this a real issue? can we benchmark it?
  • how much pressure is released by server side rendering/bootstrapping?
  • how much does hashing help?
  • can static opts help? (#2)
  • can we hook into react's batching mechanism?
  • if insertRule() has better perf (despite bad dx #8), can we use that in prod instead?

env-specific vendor prefixes

on server side, it should do the current behavior, which is adding all prefixes
on browser, only needed prefixes

docs rewrite

goals for the rewrite are -

  • explain the why (the 'css as values' spiel)
  • explain the how, geared for beginners
  • deep dive into advanced usecases
  • how it's better than CSS (and it is!)
  • start work on something nicer looking than an .md file (github-pages, maybe?
  • cleanup of /docs folder

Cannot read property 'cssRules' of undefined

Hi the idea of this lib is really great! I want to start using it instead of Radium.

I'm having trouble running the code, I'm getting 'Cannot read property 'cssRules' of undefined' on the following line: insertSheetRule(cssrule(type, style, id), sheet.cssRules.length);

I'm doing a simple test:

import {style} from '@threepointone/react-css'

export default class Test extends React.Component {
  render() {
    return <div
        {...style({ color: 'red', cursor: 'pointer' })}
      >
        TEST
      </div>
  }
}

possible static optimizations

The basic idea here is to process the javascript and replace function calls with values, deduping common declarations and avoiding cpu cycles. If we could detect all functional calls to style/<pseudo>/media, and the arguments passed to them were constant objects with primitive values (eg -{color:'red'}), we could then hoist the function call to the very top of the program, deduping on 'equal' values, and replacing the callsite with the resulting {[data-*]:<id>} object.
Further ideas in jsxstyle.

refactor

  • merge / media to get cleaner
  • abstractify cache/inserted logic
  • fix #21

How to use with Shadow DOM

Since glamor mutates a stylesheet in the head - I don't see any options how to suppress that and instead generate a string or use an alternate style tag - I'm wondering how this could be used to work with a style tag in a shadow root since global styles can't leak into a shadow root?

A way to do this might be to buffer the calls and return a string:

import { buffer, style } from 'glamor';

const div = document.createElement('div');
const css = buffer(() => {
  return {
    declaration1: style({ backgroundColor: 'orange' }),
    declaration2: style({ backgroundColor: 'black' }),
  };
});

div.attachShadow({ open: true });
div.shadowRoot.innerHTML = `
  <style>${css.toString()}</style>
  <div ${css.declaration1}>
    <span ${css.declaration2}>in shadow root</span>
  </div>
`;

I've thought about being able to supply a custom style element, however, that would couple the implementation to the actual DOM and in my case, I'm using web components with a virtual DOM.

Placeholder selector is not vendor prefixed

It seems placeholder styles are not working in Chrome, seemingly because the selector ::placeholder is not supported (needs to be ::-webkit-input-placeholder) and as far as I could tell from a quick look through the code, the selectors are not processed by the prefixer, only rules are.

Question is, since the cases where the selector needs to be prefixed somehow are quite rare and tricky to handle in a generic way (for example, to get placeholder styling to work cross-browser you need to duplicate the rule blocks iirc), is it better to handle these things case by case or find some more generic solution (i.e pass all selectors through a prefixer)?

can't edit css in devtools(!)

because of this chrome issue, the generated css cannot be edited in chrome devtools, and it doesn't look like that'll get fixed any time soon.

not all hope is lost though, we can simply reconstruct the css like aphrodite does it. must also investigate batching with react's loop, preventing aphrodite's async problem.

Pre-built CSSPropertyOperations

Is there a reason for pre-building 'CSSPropertyOperations' instead of requiring it from React or copy/pasting the original files?

Webpack complains about its format:

WARNING in ./~/glamor/lib/CSSPropertyOperations.js
Critical dependencies:
26:78-86 This seems to be a pre-built javascript file. Though this is possible, it's not recommended. Try to require the original source to get better results.
 @ ./~/glamor/lib/CSSPropertyOperations.js 26:78-86

Thanks!

deeply merged rule in media query doesn't live update label during hot loading

very specific bug - if there's a multinested merge() inside a media(), and that inner merge has a custom label, then editing it with hot loading enabled does not change the label in the dom. I've narrowed it down to this testcase -

export class App extends React.Component {
  render() {
    return <div {...media('(min-width: 500px)', 
      merge( 'container', 
        merge('inner',
          { color: 'red' }, 
          hover({ color: 'blue' }))))} />
  }
}

in the above, editing 'container' works fine, but editing 'inner' doesn't reflect in the dom after the hot update.

this points to be some hashing error in either merge() or media()

to be clear, editing the styles works fine, just the label doesn't update.

[project] - scan www for css selector usage

to be more specific - I'd like to scan the top 1000 (10000?) sites, extract the css from them, and count the number of rules in them. this will give as indication as whether we should use more stylesheets behind-the-scenes, or whether we're fine with just one.

re-examine/redo @font-face

the current implementation is rather weak, and doesn't participate well in the hashing goodness; further I haven't really used it extensively yet. open to ideas.

coverage

bring back coverage reports for tests

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.