mostly filebased Content Presentation System

442 lines
11KB

  1. /// Grid Math Engine
  2. /// ================
  3. /// The `su` functions give you direct access to the math layer,
  4. /// without any syntax-sugar like shorthand parsing, and normalization.
  5. /// If you prefer named arguments, and stripped-down syntax,
  6. /// you can use these functions directly in your code –
  7. /// replacing `span`, `gutter`, and `slice`.
  8. ///
  9. /// These functions are also useful
  10. /// for building mixins or other extensions to Susy.
  11. /// Apply the Susy syntax to new mixins and functions,
  12. /// using our "Plugin Helpers",
  13. /// or write your own syntax and pass the normalized results along
  14. /// to `su` for compilation.
  15. ///
  16. /// @group su-math
  17. ///
  18. /// @see su-span
  19. /// @see su-gutter
  20. /// @see su-slice
  21. /// @ignore _su-sum
  22. /// @ignore _su-calc-span
  23. /// @ignore _su-calc-sum
  24. /// @ignore _su-needs-calc-output
  25. // Su Span
  26. // -------
  27. /// Calculates and returns a CSS-ready span width,
  28. /// based on normalized span and context data –
  29. /// a low-level version of `susy-span`,
  30. /// with all of the logic and none of the syntax sugar.
  31. ///
  32. /// - Grids defined with unitless numbers will return `%` values.
  33. /// - Grids defined with comparable units
  34. /// will return a value in the units provided.
  35. /// - Grids defined with a mix of units,
  36. /// or a combination of untiless numbers and unit-lengths,
  37. /// will return a `calc()` string.
  38. ///
  39. /// @group su-math
  40. /// @see susy-span
  41. ///
  42. /// @param {number | list} $span -
  43. /// Number or list of grid columns to span
  44. /// @param {list} $columns -
  45. /// List of columns available
  46. /// @param {number} $gutters -
  47. /// Width of a gutter in column-comparable units
  48. /// @param {0 | 1 | -1} $spread -
  49. /// Number of gutters spanned,
  50. /// relative to `span` count
  51. /// @param {0 | 1 | -1} $container-spread [$spread] -
  52. /// Number of gutters spanned,
  53. /// relative to `columns` count
  54. /// @param {integer} $location [1] -
  55. /// Optional position of sub-span among full set of columns
  56. ///
  57. /// @return {length} -
  58. /// Relative or static length of a span on the grid
  59. @function su-span(
  60. $span,
  61. $columns,
  62. $gutters,
  63. $spread,
  64. $container-spread: $spread,
  65. $location: 1
  66. ) {
  67. $span: su-valid-span($span);
  68. $columns: su-valid-columns($columns);
  69. $gutters: su-valid-gutters($gutters);
  70. $spread: su-valid-spread($spread);
  71. @if (type-of($span) == 'number') {
  72. @if (not unitless($span)) {
  73. @return $span;
  74. }
  75. $location: su-valid-location($span, $location, $columns);
  76. $span: su-slice($span, $columns, $location, $validate: false);
  77. }
  78. @if _su-needs-calc-output($span, $columns, $gutters, $spread, not 'validate') {
  79. @return _su-calc-span($span, $columns, $gutters, $spread, $container-spread, not 'validate');
  80. }
  81. $span-width: _su-sum($span, $gutters, $spread, $validate: false);
  82. @if unitless($span-width) {
  83. $container-spread: su-valid-spread($container-spread);
  84. $container: _su-sum($columns, $gutters, $container-spread, $validate: false);
  85. @return percentage($span-width / $container);
  86. }
  87. @return $span-width;
  88. }
  89. // Su Gutter
  90. // ---------
  91. /// Calculates and returns a CSS-ready gutter width,
  92. /// based on normalized grid data –
  93. /// a low-level version of `susy-gutter`,
  94. /// with all of the logic and none of the syntax sugar.
  95. ///
  96. /// - Grids defined with unitless numbers will return `%` values.
  97. /// - Grids defined with comparable units
  98. /// will return a value in the units provided.
  99. /// - Grids defined with a mix of units,
  100. /// or a combination of untiless numbers and unit-lengths,
  101. /// will return a `calc()` string.
  102. ///
  103. /// @group su-math
  104. /// @see susy-gutter
  105. ///
  106. /// @param {list} $columns -
  107. /// List of columns in the grid
  108. /// @param {number} $gutters -
  109. /// Width of a gutter in column-comparable units
  110. /// @param {0 | 1 | -1} $container-spread -
  111. /// Number of gutters spanned,
  112. /// relative to `columns` count
  113. ///
  114. /// @return {length} -
  115. /// Relative or static length of one gutter in a grid
  116. @function su-gutter(
  117. $columns,
  118. $gutters,
  119. $container-spread
  120. ) {
  121. @if (type-of($gutters) == 'number') {
  122. @if ($gutters == 0) or (not unitless($gutters)) {
  123. @return $gutters;
  124. }
  125. }
  126. @if _su-needs-calc-output($gutters, $columns, $gutters, -1, not 'validate') {
  127. @return _su-calc-span($gutters, $columns, $gutters, -1, $container-spread, not 'validate');
  128. }
  129. $container: _su-sum($columns, $gutters, $container-spread);
  130. @return percentage($gutters / $container);
  131. }
  132. // Su Slice
  133. // --------
  134. /// Returns a list of columns
  135. /// based on a given span/location slice of the grid –
  136. /// a low-level version of `susy-slice`,
  137. /// with all of the logic and none of the syntax sugar.
  138. ///
  139. /// @group su-math
  140. /// @see susy-slice
  141. ///
  142. /// @param {number} $span -
  143. /// Number of grid columns to span
  144. /// @param {list} $columns -
  145. /// List of columns in the grid
  146. /// @param {number} $location [1] -
  147. /// Starting index of a span in the list of columns
  148. /// @param {bool} $validate [true] -
  149. /// Check that arguments are valid before proceeding
  150. ///
  151. /// @return {list} -
  152. /// Subset list of grid columns, based on span and location
  153. @function su-slice(
  154. $span,
  155. $columns,
  156. $location: 1,
  157. $validate: true
  158. ) {
  159. @if $validate {
  160. $columns: su-valid-columns($columns);
  161. $location: su-valid-location($span, $location, $columns);
  162. }
  163. $floor: floor($span);
  164. $sub-columns: ();
  165. @for $i from $location to ($location + $floor) {
  166. $sub-columns: append($sub-columns, nth($columns, $i));
  167. }
  168. @if $floor != $span {
  169. $remainder: $span - $floor;
  170. $column: $location + $floor;
  171. $sub-columns: append($sub-columns, nth($columns, $column) * $remainder);
  172. }
  173. @return $sub-columns;
  174. }
  175. // Su Sum
  176. // ------
  177. /// Get the total sum of column-units in a layout.
  178. ///
  179. /// @group su-math
  180. /// @access private
  181. ///
  182. /// @param {list} $columns -
  183. /// List of columns in the grid
  184. /// @param {number} $gutters -
  185. /// Width of a gutter in column-comparable units
  186. /// @param {0 | 1 | -1} $spread -
  187. /// Number of gutters spanned,
  188. /// relative to `columns` count
  189. /// @param {bool} $validate [true] -
  190. /// Check that arguments are valid before proceeding
  191. ///
  192. /// @return {number} -
  193. /// Total sum of column-units in a grid
  194. @function _su-sum(
  195. $columns,
  196. $gutters,
  197. $spread,
  198. $validate: true
  199. ) {
  200. @if $validate {
  201. $columns: su-valid-span($columns);
  202. $gutters: su-valid-gutters($gutters);
  203. $spread: su-valid-spread($spread);
  204. }
  205. // Calculate column-sum
  206. $column-sum: 0;
  207. @each $column in $columns {
  208. $column-sum: $column-sum + $column;
  209. }
  210. $gutter-sum: (ceil(length($columns)) + $spread) * $gutters;
  211. $total: if(($gutter-sum > 0), $column-sum + $gutter-sum, $column-sum);
  212. @return $total;
  213. }
  214. // Su Calc
  215. // -------
  216. /// Return a usable span width as a `calc()` function,
  217. /// in order to create mixed-unit grids.
  218. ///
  219. /// @group su-math
  220. /// @access private
  221. ///
  222. /// @param {number | list} $span -
  223. /// Pre-sliced list of grid columns to span
  224. /// @param {list} $columns -
  225. /// List of columns available
  226. /// @param {number} $gutters -
  227. /// Width of a gutter in column-comparable units
  228. /// @param {0 | 1 | -1} $spread -
  229. /// Number of gutters spanned,
  230. /// relative to `span` count
  231. /// @param {0 | 1 | -1} $container-spread [$spread] -
  232. /// Number of gutters spanned,
  233. /// relative to `columns` count
  234. /// @param {bool} $validate [true] -
  235. /// Check that arguments are valid before proceeding
  236. ///
  237. /// @return {length} -
  238. /// Relative or static length of a span on the grid
  239. @function _su-calc-span(
  240. $span,
  241. $columns,
  242. $gutters,
  243. $spread,
  244. $container-spread: $spread,
  245. $validate: true
  246. ) {
  247. @if $validate {
  248. $span: su-valid-span($span);
  249. $columns: su-valid-columns($columns);
  250. $gutters: su-valid-gutters($gutters);
  251. $spread: su-valid-spread($spread);
  252. $container-spread: su-valid-spread($container-spread);
  253. }
  254. // Span and context
  255. $span: _su-calc-sum($span, $gutters, $spread, not 'validate');
  256. $context: _su-calc-sum($columns, $gutters, $container-spread, not 'validate');
  257. // Fixed and fluid
  258. $fixed-span: map-get($span, 'fixed');
  259. $fluid-span: map-get($span, 'fluid');
  260. $fixed-context: map-get($context, 'fixed');
  261. $fluid-context: map-get($context, 'fluid');
  262. $calc: '#{$fixed-span}';
  263. $fluid-calc: '(100% - #{$fixed-context})';
  264. // Fluid-values
  265. @if (not $fluid-span) {
  266. $fluid-calc: null;
  267. } @else if ($fluid-span != $fluid-context) {
  268. $fluid-span: '* #{$fluid-span}';
  269. $fluid-context: if($fluid-context, '/ #{$fluid-context}', '');
  270. $fluid-calc: '(#{$fluid-calc $fluid-context $fluid-span})';
  271. }
  272. @if $fluid-calc {
  273. $calc: if(($calc != ''), '#{$calc} + ', '');
  274. $calc: '#{$calc + $fluid-calc}';
  275. }
  276. @return calc(#{unquote($calc)});
  277. }
  278. // Su Calc-Sum
  279. // -----------
  280. /// Get the total sum of fixed and fluid column-units
  281. /// for creating a mixed-unit layout with `calc()` values.
  282. ///
  283. /// @group su-math
  284. /// @access private
  285. ///
  286. /// @param {list} $columns -
  287. /// List of columns available
  288. /// @param {number} $gutters -
  289. /// Width of a gutter in column-comparable units
  290. /// @param {0 | 1 | -1} $spread -
  291. /// Number of gutters spanned,
  292. /// relative to `span` count
  293. /// @param {bool} $validate [true] -
  294. /// Check that arguments are valid before proceeding
  295. ///
  296. /// @return {map} -
  297. /// Map with `fixed` and `fluid` keys
  298. /// containing the proper math as strings
  299. @function _su-calc-sum(
  300. $columns,
  301. $gutters,
  302. $spread,
  303. $validate: true
  304. ) {
  305. @if $validate {
  306. $columns: su-valid-span($columns);
  307. $gutters: su-valid-gutters($gutters);
  308. $spread: su-valid-spread($spread);
  309. }
  310. $fluid: 0;
  311. $fixed: ();
  312. $calc: null;
  313. // Gutters
  314. $gutters: $gutters * (length($columns) + $spread);
  315. // Columns
  316. @each $col in append($columns, $gutters) {
  317. @if unitless($col) {
  318. $fluid: $fluid + $col;
  319. } @else {
  320. $fixed: _su-map-add-units($fixed, $col);
  321. }
  322. }
  323. // Compile Fixed Units
  324. @each $unit, $total in $fixed {
  325. @if ($total != (0 * $total)) {
  326. $calc: if($calc, '#{$calc} + #{$total}', '#{$total}');
  327. }
  328. }
  329. // Calc null or string
  330. @if $calc {
  331. $calc: if(str-index($calc, '+'), '(#{$calc})', '#{$calc}');
  332. }
  333. // Fluid 0 => null
  334. $fluid: if(($fluid == 0), null, $fluid);
  335. // Return map
  336. $return: (
  337. 'fixed': $calc,
  338. 'fluid': $fluid,
  339. );
  340. @return $return;
  341. }
  342. // Needs Calc
  343. // ----------
  344. /// Check if `calc()` will be needed in defining a span,
  345. /// if the necessary units in a grid are not comparable.
  346. ///
  347. /// @group su-math
  348. /// @access private
  349. ///
  350. /// @param {list} $span -
  351. /// Slice of columns to span
  352. /// @param {list} $columns -
  353. /// List of available columns in the grid
  354. /// @param {number} $gutters -
  355. /// Width of a gutter
  356. /// @param {0 | 1 | -1} $spread -
  357. /// Number of gutters spanned,
  358. /// relative to `span` count
  359. /// @param {bool} $validate [true] -
  360. /// Check that arguments are valid before proceeding
  361. ///
  362. /// @return {bool} -
  363. /// `True` when units do not match, and `calc()` will be required
  364. @function _su-needs-calc-output(
  365. $span,
  366. $columns,
  367. $gutters,
  368. $spread,
  369. $validate: true
  370. ) {
  371. @if $validate {
  372. $span: su-valid-span($span);
  373. $columns: su-valid-columns($columns);
  374. $gutters: su-valid-gutters($gutters);
  375. }
  376. $has-gutter: if((length($span) > 1) or ($spread >= 0), true, false);
  377. $check: if($has-gutter, append($span, $gutters), $span);
  378. $safe-span: _su-is-comparable($check...);
  379. @if ($safe-span == 'static') {
  380. @return false;
  381. } @else if (not $safe-span) {
  382. @return true;
  383. }
  384. $safe-fluid: _su-is-comparable($gutters, $columns...);
  385. @return not $safe-fluid;
  386. }