X-Git-Url: https://jasonwoof.com/gitweb/?p=wfpl.git;a=blobdiff_plain;f=stylus_helpers.styl;h=93b3ae31eed4d38010c8618400b2472b11a56e79;hp=4a351fa856315236415e5c431bd1779bc9160f4f;hb=HEAD;hpb=7a534068e00c59bb72be40399845099982a72064 diff --git a/stylus_helpers.styl b/stylus_helpers.styl index 4a351fa..93b3ae3 100644 --- a/stylus_helpers.styl +++ b/stylus_helpers.styl @@ -1,4 +1,7 @@ -// Copyright 2014 Jason Woofenden -- Public Domain (CC0) +// This program is in the public domain within the United States. Additionally, +// we waive copyright and related rights in the work worldwide through the CC0 +// 1.0 Universal public domain dedication, which can be found at +// http://creativecommons.org/publicdomain/zero/1.0/ // This file contains helpers for using stylus in your project. // @@ -54,12 +57,33 @@ dimensions(w, h) width: _px(w) height: _px(h) +// generate (return) a "calc(Fpx + R%)" to scale linearly with parent +// args: +// pb: pixel width of parent (when biggest) +// ps: pixel width of parent (when smallest) +// cb: pixel width of child (when biggest) +// cs: pixel width of child (when smallest) +linear_scale_calc(pb, ps, cb, cs) + // math explained: (figuring out F and R in calc(Fpx + R%)) + // f + r * pb = cb // known_1: formula(pb) -> cb + // f = cb - r * pb // solve_for_f: subtract (r * pb) from both sides + // f + r * ps = cs // known_2: formula(pb) -> cb + // cb - r * pb + r * ps = cs // substitute solved_for_f into known_2 + // -r * pb + r * ps = cs - cb // subtract cb from both sides + // r * (-pb + ps) = cs - cb // factor out r from left side + // r = (cs - cb) / (-pb + ps) // divide both sides by (-pb + ps) + // r = (cb - cs) / (pb - ps) // multiply left side by -1/-1 + r = (cb - cs) / (pb - ps) + f = cb - r * pb + unquote("calc(" + unit(f, "px") + ' + ' + unit(100 * r, "%") + ")") + // Make children of this element inline-blocks that are spaced evenly accross. // // To create a minimum distance between: don't use word-spacing, it's broken in // firefox. Instead, try padding on the children and negative margin on the // parent. -space_evenly(line_height = 1.2em) +space_evenly(line_height = 1.2) + line_height = unit(line_height, em) text-align: justify & > * display: inline-block @@ -91,11 +115,15 @@ space_evenly(line_height = 1.2em) // // styl: // nav li -// sprite_rollover "images/nav.png" 150 35 2 +// sprites_rollover "images/nav.png" 150 35 2 sprites_rollover(image, width, height, count, v_offset = 0, h_offset = 0) width: unit(width, px) height: unit(height, px) - background-image: url(image) + if image[1] + background: url(image[0]) + background: url(image[1]), linear-gradient(transparent, transparent); + else + background-image: url(image) background-position: top left background-repeat: no-repeat; for n in (0...count) @@ -110,7 +138,11 @@ sprite_rollover(image, width, height, v_offset = 0, h_offset = 0) // see sprites_rollover sprites(image, height, count, v_offset = 0, h_offset = 0) height: unit(height, px) - background-image: url(image) + if image[1] + background: url(image[0]) + background: url(image[1]), linear-gradient(transparent, transparent); + else + background-image: url(image) background-position: top left background-repeat: no-repeat; for n in (0...count) @@ -118,7 +150,14 @@ sprites(image, height, count, v_offset = 0, h_offset = 0) y = - (@height * n) - unit(v_offset, px) background-position: (0 - unit(h_offset, px)) y sprite(image, height, v_offset = 0, h_offset = 0) - sprites(image, height, 1, v_offset, h_offset) + height: unit(height, px) + if image[1] + background: url(image[0]) + background: url(image[1]), linear-gradient(transparent, transparent); + else + background-image: url(image) + background-repeat: no-repeat; + background-position: (0 - unit(h_offset, px)) (0 - unit(v_offset, px)) // Styling for a variable height element with an image background where the // middle repeats vertically. You must split your image into three images, and @@ -208,3 +247,317 @@ noselect() -moz-user-select: none -ms-user-select: none user-select: none + +// Do all the crazy math to get columns to fit properly +// and (optionally) scale for responsive designs. +// +// example: +// +// columns = wfpl_columns({ +// type: 'node', +// name: 'centerer', +// margin: 15px, +// width: 940px, +// child: { +// type: 'node', +// name: 'middler', +// border-width: 1px, +// border-style: solid, +// border-color: black, +// padding-left: 30px, +// padding-right: 18px, +// child: { +// type: 'alternatives', +// full: { +// type: 'series', +// nav: { +// type: 'node' +// width: 219px +// float: left +// }, +// main: { +// type: 'node' +// margin-left: 48px, +// width: 623px +// float: left +// } +// }, +// with_sidebar: { +// type: 'series', +// nav: { +// type: 'node', +// width: 219px +// float: left +// }, +// main: { +// type: 'node', +// margin-left: 48px, +// width: 343px +// float: left +// }, +// sidebar: { +// type: 'alternatives', +// plain: { +// type: 'node' +// margin-left: 30px, +// width: 250px +// float: left +// }, +// bordered: { +// type: 'node' +// margin-left: 30px, +// border-width: 1px, +// border-style: solid +// border-color: red +// padding: 15px, +// width: 218px +// float: left +// } +// } +// } +// } +// } +// }) +// output css from column calculations +// for selector, css in columns.css +// body > {selector} +// {css} +// @media screen and (max-width: (columns.width)) +// // output responsive css from column calculations +// for selector, css in columns.responsive_css +// body > {selector} +// {css} +// +// // as big as it can be +// body > .centerer +// width: auto +// +// // make sure that borders (which won't scale) and rounding errors don't +// // break the layout +// body > .centerer.full > .main, +// body > .centerer.with_sidebar > .sidebar.plain, +// body > .centerer.with_sidebar > .sidebar.bordered +// margin-right: -10px +// +// // switch to 1-column layout +// @media screen and (max-width: (single_column_max)) +// for selector, css in columns.css +// body > {selector} +// if selector == '.centerer' +// margin-top: 0 +// else if selector in hide_in_one_column_mode +// display: none +// else +// border: none +// float: none +// width: auto +// margin: 0 +// padding: 0 +// margin-top: columns['responsive_css']['.centerer']['margin'] +wfpl_columns_helper(top, node, selector, parent_width, expected_width) + css_rules = {} + responsive_css_rules = {} + if node.type == 'node' + left_width = 0px + right_width = 0px + width = null // inner + outer_width = null + if node.name + if selector == '' + selector = '.' + node.name + else + selector += ' > .' + node.name + // callculate width and outer_width + for k, v in node + if match('^(margin|padding|border-width)$', k) + left_width += v + right_width += v + if match('^((margin|padding)-left)|(border-left-width)$', k) + left_width += v + if match('^((margin|padding)-right)|(border-right-width)$', k) + right_width += v + if k != 'type' && k != 'child' && k != 'name' && k != 'outer_width' + css_rules[k] = v + for k, v in node + if k == 'width' + width = v + if k == 'outer_width' + outer_width = v + css_rules['width'] = v - left_width - right_width + if (!width) && (!outer_width) + if parent_width + outer_width = parent_width + else + error("Couldn't figure out width of " + selector); + if outer_width && !width + width = outer_width - left_width - right_width + if width && !outer_width + outer_width = width + left_width + right_width + unless parent_width // should only happen at top level + parent_width = outer_width + top['css'][selector] = css_rules + for k, v in css_rules + if k != 'border-width' && k != 'border-left-width' && k != 'border-right-width' + if typeof(v) == 'unit' && unit(v) == 'px' + responsive_css_rules[k] = floor(unit((v / parent_width) * 100, '%'), 4) + top['responsive_css'][selector] = responsive_css_rules + if 'child' in node + child_width = wfpl_columns_helper(top, node.child, selector, width, width) + _columns_recurser(rargs) + if child_width != width + error(selector + " is the is wrong width. Expected: " + width + ", got: " + rargs.ret.w) + top['widths'][selector] = width + return outer_width + if node.type == 'alternatives' + for name, child in node + if name != 'type' + child_selector = selector + '.' + name + child_width = wfpl_columns_helper(top, child, child_selector, parent_width, expected_width) + if expected_width + if child_width != expected_width + error(child_selector + " is wrong width. Expected: " + expected_width + ", got: " + child_width) + else + expected_width = child_width + unless parent_width + parent_width = child_width + return expected_width + if node.type == 'series' + series_width = 0px + for name, child in node + if name != 'type' + if selector == '' + child_selector = '.' + name + else + child_selector = selector + ' > .' + name + child_width = wfpl_columns_helper(top, child, child_selector, parent_width, null) + series_width += child_width + if expected_width + if series_width != expected_width + error(selector + " series total wrong. expected: " + expected_width + ", got: " + series_width); + return series_width + return // never reached with valid data + +wfpl_columns(hash) + top = { // contains settings, and is returned from porcelain + responsive: responsive + width: null + css: {} + responsive_css: {} + widths: {} + } + top.width = wfpl_columns_helper(top, hash, '', null, null) + return top + +// internal helper +_pct_pos(offset, width, sheet_width) + if width is sheet_width + return 0 + ratio = offset / (sheet_width - width) + if ratio is 0 + return 0 + return unit(ratio * 100, '%') + +// wfpl_spritesheets documentation/example: +// +// wfpl_spritesheets({ +// main: { +// image: sha1['images/sprites.min.svg'] +// y_origin: 'bottom' // invert y coordinates below (thx inkscape) +// w: 200 // width of document (whatever units) +// h: 400 // height of document (whatever units) +// sprites: { +// ".icon": { +// y: 399 // top (regardless of y_origin) +// w: 48 // width of sprite (in doc coords) +// h: 48 // height of sprite (in doc coords) +// gap: 2 // space _between_ rows/columns +// hover: 'right' // can be 'right' or 'down', meaning: direction to +// // move in spritesheet to find the ":hover" graphic +// column: 'three' 'four' 'five' 'six' // key can be 'column' or 'row' +// // values are postfix for class names +// } +// ".logo": { +// y: 100 +// w: 200 +// h: 50 +// } +// } +// } +// }) +// +// HTML: +//