jetpak-css
v1.0.2
Published
An agile powerup to get your app off the ground.
Downloads
3
Readme
jetpak-css
A dynamic css injection tool for javascript web-apps
A free powerup to launch your app off the ground.
Contents
- Usage
- Initialize the Global Class
- Adding css
- StyleObject
- Theme Support
- Update the DOM
- Helper Exports
- Debugging
- Full Examples
- Downsides & Disclaimers
Usage
- Install Jetpak
npm install --save jetpak-css
- Initialize the global JetpakCss at the top level of your app structure.
- Use the
css
function throughout your app to dynamically load css into your app. - Run the update function to inject newly added styles into the DOM.
Global Class
const jetpak = new JetpakCss(InitializationConfig)
InitializationConfig:
| Key | Description | Type | | :-----------: |:------------------------------------------------:| :------:| | theme | Theme Configuration Object | ThemeConfig (see below) | | baseStyle | Default style object to initialize with | StyleConfig (see below) |
Usage:
Initialize the class in the root js file of your app so it begins at runtime in the browser:
import { JetpakCss } from 'jetpak-css'
import theme from './theme'
const jetpak = new JetpakCss({
theme,
style: {
// StyleObject containing styles like reset.css and other non-component-specific code
},
})
// ...the rest of your app initialization here
Initializing the JetpakCss
class creates a globally accessible instance of Jetpak. From here, invocations of css() adds to the globals styles stored in this class. Later, running the update function will stringify and inject the style it into the head of your app. This will add window.__JETPAK__
but you shouldn't need to look at this, except when debugging your styles.
Adding css
const classes = css(StyleObject)
This is the function you use most with Jetpak. It takes in a StyleObject
which is an object that Jetpak parses to generate a css string. It's similar to other css-in-javascript solutions, and takes some ways of doing things from sass/scss.
css() returns usable classes
This function returns an object of ClassNames that generated when the css parsed. This object will not contain anything but classnames.
For example, you could have a component structured like this:
const classes = css({
arcticMonkeys: {
color: 'blue',
'&:hover': {
color: 'black',
},
'> alexTurner': {
fontWeight: 200,
}
},
span: {
display: 'inline-block',
},
})
return [
div({
class: classes.arcticMonkeys,
render: [
div({
class: classes.alexTurner,
render: 'Tranquility Base'
})
]
}),
span('Hotel & Casino')
]
( This example uses the arsnl app framework )
You would see this as the css output (this injected into the <head>
of the page on the next jetpak.update()
):
.arctic-monkeys {
color: blue;
}
.arctic-monkeys:hover {
color: black;
}
.arctic-monkeys > .alex-turner {
fontWeight: 200,
}
span {
display: inline-block;
}
and this as the html output:
<div class="arctic-monkeys">
<div class="alex-turner">
Tranquility Base
</div>
</div>
<span>
Hotel & Casino
</span>
StyleObject
The StyleObject
is the config of style properties that gets passed into the css()
function.
A simple example:
import { css } from 'jetpak-css'
const classes = css({ body: { background: 'red' }})
A complex example:
import { css, px, em, colors } from 'jetpak-css'
const classes = css({
appLogo: {
margin: px(100),
svg: {
height: px(150),
width: px(150),
},
},
button: {
padding: em(1),
color: colors.skyblue,
'&:hover, &:focus': {
color: colors.steelblue,
},
'&:not(:disabled), &:not(.disabled)': {
cursor: 'pointer',
},
},
'@media only screen (max-width: 600px)': {
button: {
padding: em(0.5),
}
}
})
| Feature | Input Example | Output Example | Notes |
| :------: |:------:|:------:|:------:|
| Tag Names | div
, span
, body
, etc... | div
, span
, body
, etc... | Jetpak knows what valid html5 tag names look like so it doesn't turn them into classes accidentally. |
| Nested Selectors | { ul: { li: { listStyle: 'none'}}}
| ul li { list-style: none; }
| You can nest selectors like scss and jetpak will figure out what css you mean to generate. |
| & | { button: { &:disabled: { opacity: 0.8, &.old { color: 'yellow' }}}}
| button:disabled { opacity: 0.8; } button:disabled.old { color: yellow; }
| Any selector starting with an &
is expected to be an extension of its parent. When generating the style, it will replace the &
with it's parent selector.|
| Camel To Kebab | { '#someIdHere': { fontWeight: 500 } }
| #some-id-here { font-weight: 500; }
| Class names, IDs, and css property names all get turned from camel to kebab case, if they weren't already that way. |
| Attribute Selectors | { '[disabled="true"] someClassHere': { color: '#ccc' } }
| [disabled="true"] .some-class-here { color: #ccc; }
| Attribute selectors are maintained as typed, and aren't altered by the parser. |
| Media Queries | { '@media only screen (max-width: 940px)': { body: { color: 'green' } } }
| @media only screen (max-width: 940px) { body { color: green; } }
| Any key starting with @media
must be a top-level property in the style object hierarchy and are not altered by the parser. Media queries are to the end of the stylesheet to come last syntactically. |
With Theme Support
You can get quick access to the theme object in the initialized JetpakCss
global class by passing in a StyleObject
generator function. The only argument passed into it is the theme.
import { css } from 'jetpak-css'
const classes = css((theme) => {
return {
body: {
background: theme.appBackground,
color: theme.appTextColor,
}
}
})
You can put whatever you want in the theme object. Jetpak doesn't do anything with it but pass it into each css function call if the config object it receives is passed in the form of a function.
Update the DOM
As you add css({})
invocations throughout your app the JetpakCss
Class will collect all of your style into one object. When your app is rendering a new markup change to the DOM you'll want to call the update()
method on the JetpakCss
Class. This will compile all of the css and inject it into the style-tag it generated in the <head>
of your site. If no style has changed, it will not update the DOM to avoid unnecessary repainting.
// This is the main app file of an arsnl app
import { App } from 'arsnl'
import { getBaseStyles, createTheme } from 'arsnl-kit'
import { JetpakCss } from 'jetpak-css'
import themeConfig from './theme'
import rootComponent from './App'
import routes from './routes'
const theme = createTheme(themeConfig)
const style = getBaseStyles(theme)
const jetpak = new JetpakCss({ theme, style })
new App({
id: 'app-root',
routes,
component: rootComponent,
onAfterRender: () => {
jetpak.update()
},
})
( This example uses the arsnl app framework )
Note: onAfterRender
in this example would be run at the end of every render digest cycle, similar to componentDidMount
and componentDidUpdate
in a ReactComponent
.
Debugging
Downsides & Disclaimers
- Cases for parsing selectors in the
StyleObject
are probably missing. - Calling
jetpak.update()
could become a big-memory-operation with large apps, yet to be officially tested seeing as this package is new.