What is it
Features
Responsiveness
Dynamic styles
API
DynCSS
Simple, dynamic CSS rules to give life to your sites.
GithubDocsExample
Install
$ bower install dyn-css
Include
...
<script src='bower_components/dyn-css/dyncss.js'
        type='text/javascript' />
...

Less than 20K, uncompressed and unminified. Requires only jQuery.

Enjoy
i.fa.fa-gamepad {
  -dyn-webkit-transform:   
     '"rotate(#{@win-scrollTop}deg) "';
}

What is it?

DynCSS parses your CSS for -dyn-(attribute) rules. These rules are Javascript expressions evaluated on browser's events like scroll and resize. The result is applied to the CSS attribute you have specified as suffix.

For example, this will center vertically .header, dynamically changing margin-top as the window is resized:

.header {
 -dyn-margin-top: '(@win-height - @el-height)/2.0';
}

Here, @win-height is the dynamic height of the window and @el-height is the dynamic height of the current element (.header in this case). The header of this page has been centered in this way.

You can even create parallax effects by using the window's scrollTop and dynamically applying a CSS transform:

.header {
 -dyn-webkit-transform:   '"translate( 0px , #{-1*@win-scrollTop}px) "';
}

Since the webkit-transform value is a string, the above snippet creates one by interpolating the dynamic value with #{..}.

Features

You can make dynamic any CSS property — provided that it is writable by jQuery's .css() method. You do this by appending the -dyn- prefix and specifying a quoted Javascript expression.

You can use placeholders to access dynamic information about the document; here's a list of built-in placeholders you can use:

Prefixes Description
@win-foo dynamically evaluates window.foo()
@el-foo dynamically evaluates $(current-selector).css(foo)
@jq-foo dynamically evaluates $(current-selector).foo()

The syntax should be parsable by any CSS preprocessor. For example, I am using it with lessc for this website.

Custom functions

You can introduce custom functions to be evaluated at run-time, by adding them to window.dynCss.lib. For example, here's how you can introduce a center function that returns the centers of the current window:

window.dynCss.lib.center = function() {
 return {x: window.width()/2, y: window.height()/2 };
}

To use it in a rule, invoke it with the @ prefix:

 -dyn-margin-left: '@center().x';

Virtual properties - new

To enable more precise positioning of elements, the following dynamic properties of position=fixed elements have been introduced:

property name affects
-dyn-fixed-vertical-center top
-dyn-fixed-horizontal-center left

They take implicitly into account the size of the element in order to center it horizontally; for example:

.element {
 position: fixed;
 -dyn-fixed-vertical-center: '@fixedVerticalCenter(".element2")';
}

will vertically align .element to .element2 (another fixed element).

Responsiveness

DynCSS allows to easily program responsiveness in your CSS. To do so you define a list of breakpoints and the dynamic variable to watch (which is typically the size of the window). You can do this in a <script> tag in your HTML; here's how you set two breakpoints at 481 and 961 on the window's width variable @win-width:

<script> 
 window.dynCss.api.setBreakpoints([481,961],'@win-width');
</script>

Now, you can define how each property behaves above an below the breakpoints; for example, we can change dynamically the font size:

.header__title {
  -dyn-font-size: '@selectFrom(["3em", "4em", "5em"])';
}

selectFrom is a built-in function that returns one of the elements of the input list by using the breakpoints specified with setBreakpoints. Here, the font size will be 3em under 480px, 4em under 960px, and 5em above 960px.

Dynamic styles

DynCSS allows to add a class dynamically to all elements of a given selector, based on a condition to be evaluated at run-time; this is useful to build scroll spies. You can specify the class name to be added with -dyn-set-state-(class-name):

.to-be-highlighted {
 -dyn-set-state-highlight: '@isVerticallyVisible("#my-section")';
}

here, we add a .highlight class to all elements .to-be-highlighted whenever the function @isVerticallyVisible returns true. We assume that isVerticallyVisible receives a selector and checks whether it is in or out of the view port.

Here's a custom definition of isVerticallyVisible in Livescript, but you can write your own of course:


isVerticallyVisible = (el, threshold) ->
 r         = jQuery(el)[0].getBoundingClientRect();
 w         = jQuery(window)
 vp        = {}
 vp.top    = w.scrollTop()
 vp.bottom = w.scrollTop() + w.height()
 if not threshold?
  threshold := w.height()/3
  value = 
  | r.top >= 0 and r.top < (threshold)   => true
  | r.top < 0 and r.bottom > (threshold) => true
  | otherwise                            => false

 return value

API

Here are some built-in functions you can use in your -dyn-* rules:

@shouldAppear
@shouldAppear({when: expr, isHigherThan: val})
Returns a value that approaches 1.0 when expr approaches val.
0
`expr` is lower than 0
expr/val
`expr` is higher than 0 but lower than `val`
1
`expr` is higher `val`

This snippet turns up element visibility when scrolling position (@win-scrollTop) is reaching a half of the window's height:

.header {
 -dyn-opacity: '@shouldAppear({when: @win-scrollTop, isHigherThan: @win-height/2})';
}

Use isLowerThan instead of isHigherThan to make elements appear on scroll up.

@shouldDisappear
@shouldDisappear({when: expr, isHigherThan: val})
Returns a value that approaches 0.0 when expr approaches val.
1
`expr` is lower than 0
1 - (expr/val)
`expr` is higher than 0 but lower than `val`
0
`expr` is higher `val`

This snippet turns down opacity when scrolling position (@win-scrollTop) is reaching a fourth of the window's height:

.header {
 -dyn-opacity: '@shouldDisappear({when: @win-scrollTop, isHigherThan: @win-height/4})';
}

Use isLowerThan instead of isHigherThan to make elements disappear on scroll up.

@selectFrom
@selectFrom(array)
Returns the element of `array` associated with the currently active breakpoint (i.e., the one with the same index).

Here, we set the font size to 3em under the first breakpoint, 4em under the second, and 5em above the second.

.header__title {
 -dyn-font-size: '@selectFrom(["3em", "4em", "5em"])';
}

Breakpoints should be set in Javascript by using the appropriate setBreakpoints method:

<script> 
 window.dynCss.api.setBreakpoints([321, 480],'@win-width');
</script>

sets two breakpoints at window's width (@win-width) equal to 320 and 480 pixels.

@transitionToOne
@transitionToOne({when: expr, start: val, end: val}, power)
Returns a value that starts at 0, when `expr` is lower than `start`, and approaches 1.0, when `expr` approaches `end`.
0
`expr` is lower than `start`
(expr/val)^power
`expr` is higher than `start` but lower than `end`
1
`expr` is higher `end`

This snippet turns down opacity when scrolling position (@win-scrollTop) is reaching 400px. The transition follows an sqrt law (power=.5)

.header {
 -dyn-opacity: '1-@transitionToOne({when : @win-scrollTop , start: 0, stop: 400 }, .5)';
}
@if
@if(condition, v1, v2)
Returns v1 if condition is true, v2 otherwise.

Here, we remove the element when scroll-top is higher than its bottom.

.element-to-be-removed {
 -dyn-display: '@if(@win-scrollTop > @jq-offset.bottom, "none", "block")';
}
@morph
@morph(factor, v1, v2)
Returns the convex combination (1-factor)*v1 + factor*v2.

factor can be the state of a transition. This snippet resizes the width of .element by using the state returned by @transitionToOne.

.element {
 -dyn-width: '@morph(transitionToOne(...), 200, 300)';
}