chili
is a UI skeleton that embraces natural HTML5 concepts and the wonderful syntax sugar of SASS/Stylus(back soon!™) to simplify and beautify the way you think about CSS.
Components and States, wooooo!
Define abstract components with your preferred class-butchering methodology and reference them anywhere.
+component('h1, h2, h3, .--hdng', headings)
font-weight: bold
article
+component(headings)
font-size: 9001rem
Write nested states for components, opening up new ways to structure your code.
+component('form#contact-us', myForm)
border: 1px solid black
+component('input')
font-family: inherit
+state(':invalid') // state of input
border-color: red
+state('.disabled, [aria-disabled]', myForm) // states of form influencing input
opacity: .5
pointer-events: none
+media('<tablet') // media query for input in form
width: 90%
Use included functions to craft fundamental CSS relations quickly, keep the source footprint minimal and well readable and add visual effects easily.
+component(header)
+size(flex, auto 200px)
+position(fixed, top 20px left)
.logo
+hide-text
+background-retina(logo.png, 200px)
+component(nav)
+distribute(left center, column)
+indent(right 10px bottom 10px, last-child)
+state('.nav-hidden', header)
+ng-animate(leave, fadeOutLeft)
chili
currently requires Ruby SASS due to 3.4 features.
main.sass
should be your central point for importing individual components.
Build paths can be changed in gulpfile.js
.
The build process also autoprefixes properties and optimizes/minifies your selectors.
If you want to import components individually in your project, you have to fill in the components.scss
map and use it with every import, so components can be cross-referenced without compiling the whole stack.
Currently only available in SASS. 1703
chili
comes with a few helpful components to get you started on a project.
Base uses normalize.css or Meyer reset as default and defines 2 top level components - root
(html) and body
. This is useful for referencing top level attributes coming from libraries like Modernizr, states that change the whole page scaffold or any other exception necessary to propagate from a parent node.
.button-submit
+state('.no-js', root)
display: none
.wrapper
+state('.dialog-visible', body)
overflow: hidden
The gulp
build process automagically converts all your .svg
icon sources into webfonts and renders the icons
component. That allows you to easily use custom icons on pseudoelements - variable names are created for each icon based on filename.
// hamburglar.svg
button:before
+icon($icon-hamburglar)
In SASS, media query logic is provided by include-media, which allows very flexible and expressive media conditioning - refer to its documentation for details.
article
max-width: 960px
+media('>phone', '<desktop')
max-width: 480px
Modern CSS transitions and animations are subject to a refined technical lifetime with JavaScript switching display
values and/or adding classes at the right moment. Modern UI frameworks like Angular or React know this and provide features to make this lifetime manageable. chili
currently supports ngAnimate
and CSSTransitionGroup
wrappers for keyframe animations and transitions, effect bank provided by animate.css.
Keyframe animation definitions are only rendered in the resulting CSS when used.
.ng-doodle
+ng-animate(enter, bounceInLeft)
+ng-animate(leave, bounceOutRight)
.react-doodle
+react-animate(fade, enter)
opacity: 1
chili
promotes the pattern of always nesting attributes relevant to your current selector, even if they are modified by a parent. This allows you to maintain a clear writing style, keeping all element variants in their place.
+component('aside.user-info', card)
.avatar // everything possibly related to .avatar in card can be here
color: blue
+state('.--back-visible', card) // aside.user-info.--back-visible .avatar
transform: rotateX(180deg)
+state(header) // header aside.user-info .avatar, assumes a header defined
float: right
+media('<tablet') // @media (max-device-width: 767px) ...
width: 20%
.name
font-weight: bold
If you enjoy flexibility, you might find components helpful for keeping collections identified by multiple properties. Mind that all the nested variations will be output in the compiled CSS, which can grow fast for ex: multiple states on multiple components.
+component('button, .button, [role=button]', btn)
form
+component(btn)
background-color: blue
+state('.disabled, [disabled], [aria-disabled]') // taking it too far, Jim
opacity: .5
pointer-events: none
When you define a component reference, it's saved for later reuse.
+component('html', root)
Because there is no real DOM present, components operate under simple rules - if a component state is called and the target selector is found in the current nest, it's modified by the state. If it's not present, it's expected to be a level above.
+component('#nav-main', nav)
ul
+unstyled-list
.item
display: block
+state('.open', nav) // selector is #nav-main.open ul .item
transform: translateX(-100%)
+state('.wide', root) // selector is body.wide #nav-main ul .item
display: inline-block
float: left
chili
is equipped with many helper functions to simplify your writing style and scaffold your layout in a more expressive way.
Give in, you might like it!
nav
+size(flex, auto 80px)
.icon:before
+size(16px 16px) // knows to add content: '', defaults unset display to block
nav
+position(fixed, left top)
div
+position(absolute, stretch) // keyword for top 0 right 0 etc.
span
+position(relative, right 20px top 20px)
Offset from current top left border position.
.dialog
+position(absolute, left 50% top 50%)
+offset() // recenter default -50%/-50%
Distributes direct children inside current element, translating into flexbox values.
ul
+distribute(left center) // default row
+component(itemWrap)
+distribute(right top, column)
Indents each direct child's margin with optional exclusion.
.gallery
+indent(right 10px bottom 10px)
.vertical-list
+indent(bottom 5em, last-child) // excludes last-child
A super simple grid that changes direct children width to a set amount of columns.
.wrapper
+grid(5) // each .wrapper child has 20% width
chili
extends selector with the .ng-{state}
classes for keyframe animations.
.item
+ng-animate(enter, zoomIn)
+ng-animate(leave, zoomOut)
Transitions are used as nodes instead by omitting the optional properties.
.item
transition: opacity .2s ease-in
+ng-animate(enter)
opacity: 1
+ng-animate(leave)
opacity: 0
chili
for React supports block mixins as nodes to add the necessary React classes.
.item
+react-animate(fade, enter)
opacity: 1
+react-animate(fade, leave)
opacity: 0
Adds high resolution background-image
sources for high DPI screens based on pattern file.png > file@2x.png, file@3x.png
.
// also outputs MQ for logo@2x.png and logo@3x.png along normal background-image
.logo
+background-retina('images/logo.png', 200px auto)
If the default base component is used, font scaling is set to 62.5% and 16px = rem(16)
. All values resulting from em/rem can be further processed.
$indent: rem(10)
.item
padding: $indent * 2
+component(dialog)
:before
+triangle(up)
+position(absolute, left 50% top)
Draws a chevron from current element inside relative parent, recognizes a pseudoelement.