mostly filebased Content Presentation System

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. /// Susy3 API Functions
  2. /// ===================
  3. /// These three functions form the core of Susy's
  4. /// layout-building grid API.
  5. ///
  6. /// - Use `span()` and `gutter()` to return any grid-width,
  7. /// and apply the results wherever you need them:
  8. /// CSS `width`, `margin`, `padding`, `flex-basis`, `transform`, etc.
  9. /// - For asymmetrical-fluid grids,
  10. /// `slice()` can help manage your nesting context.
  11. ///
  12. /// All three functions come with an unprefixed alias by default,
  13. /// using the `susy` import.
  14. /// Import the `susy-prefix` partial instead,
  15. /// if you only only want prefixed versions of the API.
  16. ///
  17. /// This is a thin syntax-sugar shell around
  18. /// the "Su" core-math functions: `su-span`, `su-gutter`, and `su-slice`.
  19. /// If you prefer the more constrained syntax of the math engine,
  20. /// you are welcome to use those functions instead.
  21. ///
  22. /// @group api
  23. /// @see susy-span
  24. /// @see susy-gutter
  25. /// @see susy-slice
  26. /// @see su-span
  27. /// @see su-gutter
  28. /// @see su-slice
  29. /// ## Shorthand
  30. ///
  31. /// All functions draw on the same shorthand syntax in two parts,
  32. /// seperated by the word `of`.
  33. ///
  34. /// ### Span Syntax: `<width>` [`<location>` `<spread>`]
  35. /// The first part describes the
  36. /// **span** width, location, and spread in any order.
  37. /// Only the width is required:
  38. ///
  39. /// - `span(2)` will return the width of 2 columns.
  40. /// - `span(3 wide)` will return 3-columns, with an additional gutter.
  41. /// - location is only needed with asymmetrical grids,
  42. /// where `span(3 at 2)` will return the width of
  43. /// specific columns on the grid.
  44. /// Since these are functions, they will not handle placement for you.
  45. ///
  46. /// ### Context Syntax: `[of <columns> <container-spread> <gutters>]`
  47. /// The second half of Susy's shorthand
  48. /// describes the grid-**context** –
  49. /// available columns, container-spread, and optional gutter override –
  50. /// in any order.
  51. /// All of these settings have globally-defined defaults:
  52. ///
  53. /// - `span(2 of 6)` will set the context to
  54. /// a slice of 6 columns from the global grid.
  55. /// More details below.
  56. /// - `span(2 of 12 wide)` changes the container-spread
  57. /// as well as the column-context.
  58. /// - `span(2 of 12 set-gutters 0.5em)`
  59. /// will override the global gutters setting
  60. /// for this one calculation.
  61. ///
  62. /// A single unitless number for `columns`
  63. /// will be treated as a slice of the parent grid.
  64. /// On a grid with `columns: susy-repeat(12, 120px)`,
  65. /// the shorthand `of 4` will use the parent `120px` column-width.
  66. /// You can also be more explicit,
  67. /// and say `of susy-repeat(4, 100px)`.
  68. /// If you are using asymmetrical grids,
  69. /// like `columns: (1 1 2 3 5 8)`,
  70. /// Susy can't slice it for you without knowing which columns you want.
  71. /// The `slice` function accepts exactly the same syntax as `span`,
  72. /// but returns a list of columns rather than a width.
  73. /// Use it in your context like `of slice(first 3)`.
  74. ///
  75. /// @group api
  76. // Susy Span
  77. // ---------
  78. /// This is the primary function in Susy —
  79. /// used to return the width of a span across one or more columns,
  80. /// and any relevant gutters along the way.
  81. /// With the default settings,
  82. /// `span(3)` will return the width of 3 columns,
  83. /// and the 2 intermediate gutters.
  84. /// This can be used to set the `width` property of grid elements,
  85. /// or `margin` and `padding`
  86. /// to push, pull, and pad your elements.
  87. ///
  88. /// - This is a thin syntax-sugar shell around
  89. /// the core-math `su-span()` function.
  90. /// - The un-prefixed alias `span()` is available by default.
  91. ///
  92. /// @group api
  93. /// @see su-span
  94. /// @see $susy
  95. ///
  96. /// @param {list} $span -
  97. /// Shorthand expression to define the width of the span,
  98. /// optionally containing:
  99. /// - a count, length, or column-list span.
  100. /// - `at $n`, `first`, or `last` location on asymmetrical grids,
  101. /// where `at 1 == first`,
  102. /// and `last` will calculate the proper location
  103. /// based on columns and span.
  104. /// - `narrow`, `wide`, or `wider` for optionally spreading
  105. /// across adjacent gutters.
  106. /// - `of $n <spread>` for available grid columns
  107. /// and spread of the container.
  108. /// Span counts like `of 6` are valid
  109. /// in the context of symmetrical grids,
  110. /// where Susy can safely infer a slice of the parent columns.
  111. /// - and `set-gutters $n` to override global gutter settings.
  112. ///
  113. /// @param {map} $config [()] -
  114. /// Optional map of Susy grid configuration settings.
  115. /// See `$susy` documentation for details.
  116. ///
  117. /// @return {length} -
  118. /// Calculated length value, using the units given,
  119. /// or converting to `%` for fraction-based grids,
  120. /// or a full `calc` function when units/fractions
  121. /// are not comparable outside the browser.
  122. ///
  123. /// @example scss - span half the grid
  124. /// .foo {
  125. /// // the result is a bit under 50% to account for gutters
  126. /// width: susy-span(6 of 12);
  127. /// }
  128. ///
  129. /// @example scss - span a specific segment of asymmetrical grid
  130. /// .foo {
  131. /// width: susy-span(3 at 3 of (1 2 3 5 8));
  132. /// }
  133. @function susy-span(
  134. $span,
  135. $config: ()
  136. ) {
  137. $output: susy-compile($span, $config);
  138. @if map-get($output, 'span') {
  139. @return su-call('su-span', $output);
  140. }
  141. $actual: '[#{type-of($span)}] `#{inspect($span)}`';
  142. @return _susy-error(
  143. 'Unable to determine span value from #{$actual}.',
  144. 'susy-span');
  145. }
  146. // Susy Gutter
  147. // -----------
  148. /// The gutter function returns
  149. /// the width of a single gutter on your grid,
  150. /// to be applied where you see fit –
  151. /// on `margins`, `padding`, `transform`, or element `width`.
  152. ///
  153. /// - This is a thin syntax-sugar shell around
  154. /// the core-math `su-gutter()` function.
  155. /// - The un-prefixed alias `gutter()` is available by default.
  156. ///
  157. /// @group api
  158. /// @see su-gutter
  159. /// @see $susy
  160. ///
  161. /// @param {list | number} $context [null] -
  162. /// Optional context for nested gutters,
  163. /// including shorthand for
  164. /// `columns`, `gutters`, and `container-spread`
  165. /// (additional shorthand will be ignored)
  166. ///
  167. /// @param {map} $config [()] -
  168. /// Optional map of Susy grid configuration settings.
  169. /// See `$susy` documentation for details.
  170. ///
  171. /// @return {length} -
  172. /// Width of a gutter as `%` of current context,
  173. /// or in the units defined by `column-width` when available
  174. ///
  175. /// @example scss - add gutters before or after an element
  176. /// .floats {
  177. /// float: left;
  178. /// width: span(3 of 6);
  179. /// margin-left: gutter(of 6);
  180. /// }
  181. ///
  182. /// @example scss - add gutters to padding
  183. /// .flexbox {
  184. /// flex: 1 1 span(3 wide of 6 wide);
  185. /// padding: gutter(of 6) / 2;
  186. /// }
  187. ///
  188. @function susy-gutter(
  189. $context: susy-get('columns'),
  190. $config: ()
  191. ) {
  192. $context: susy-compile($context, $config, 'context-only');
  193. @return su-call('su-gutter', $context);
  194. }
  195. // Susy Slice
  196. // ----------
  197. /// Working with asymmetrical grids (un-equal column widths)
  198. /// can be challenging – 
  199. /// expecially when they involve fluid/fractional elements.
  200. /// Describing a context `of (15em 6em 6em 6em 15em)` is a lot
  201. /// to put inside the span or gutter function shorthand.
  202. /// This slice function returns a sub-slice of asymmetrical columns to use
  203. /// for a nested context.
  204. /// `slice(3 at 2)` will give you a subset of the global grid,
  205. /// spanning 3 columns, starting with the second.
  206. ///
  207. /// - This is a thin syntax-sugar shell around
  208. /// the core-math `su-slice()` function.
  209. /// - The un-prefixed alias `slice()` is available by default.
  210. ///
  211. /// @group api
  212. /// @see su-slice
  213. /// @see $susy
  214. ///
  215. /// @param {list} $span -
  216. /// Shorthand expression to define the subset span, optionally containing:
  217. /// - `at $n`, `first`, or `last` location on asymmetrical grids;
  218. /// - `of $n <spread>` for available grid columns
  219. /// and spread of the container
  220. /// - Span-counts like `of 6` are only valid
  221. /// in the context of symmetrical grids
  222. /// - Valid spreads include `narrow`, `wide`, or `wider`
  223. ///
  224. /// @param {map} $config [()] -
  225. /// Optional map of Susy grid configuration settings.
  226. /// See `$susy` documentation for details.
  227. ///
  228. /// @return {list} -
  229. /// Subset list of columns for use for a nested context
  230. ///
  231. /// @example scss - Return a nested segment of asymmetrical grid
  232. /// $context: susy-slice(3 at 3 of (1 2 3 5 8));
  233. /// /* $context: #{$context}; */
  234. @function susy-slice(
  235. $span,
  236. $config: ()
  237. ) {
  238. $span: susy-compile($span, $config);
  239. @return su-call('su-slice', $span);
  240. }
  241. /// ## Building Grids
  242. /// The web has come a long way
  243. /// since the days of double-margin-hacks
  244. /// and inconsistent subpixel rounding.
  245. /// In addition to floats and tables,
  246. /// we can now use much more powerful tools,
  247. /// like flexbox and CSS grid,
  248. /// to build more interesting and responsive layouts.
  249. ///
  250. /// With Susy3, we hope you'll start moving in that direction.
  251. /// You can still build classic 12-column Grid Systems,
  252. /// and we'll help you get there,
  253. /// but Susy3 is primarily designed for a grid-math-on-demand
  254. /// approach to layout:
  255. /// applying our functions only where you really need grid math.
  256. /// Read the [intro article by OddBird][welcome] for more details.
  257. ///
  258. /// [welcome]: http://oddbird.net/2017/06/28/susy3/
  259. ///
  260. /// @group api
  261. /// @link http://oddbird.net/2017/06/28/susy3/ Article: Welcome to Susy3
  262. ///
  263. /// @example scss - floats
  264. /// .float {
  265. /// width: span(3);
  266. /// margin-right: gutter();
  267. /// }
  268. ///
  269. /// @example scss - flexbox
  270. /// .flexbox {
  271. /// flex: 1 1 span(3);
  272. /// // half a gutter on either side…
  273. /// padding: 0 gutter() / 2;
  274. /// }
  275. ///
  276. /// @example scss - pushing and pulling
  277. /// .push-3 {
  278. /// margin-left: span(3 wide);
  279. /// }
  280. ///
  281. /// .pull-3 {
  282. /// margin-left: 0 - span(3 wide);
  283. /// }
  284. ///
  285. /// @example scss - building an attribute system
  286. /// // markup example: <div data-span="last 3"></div>
  287. /// [data-span] {
  288. /// float: left;
  289. ///
  290. /// &:not([data-span*='last']) {
  291. /// margin-right: gutter();
  292. /// }
  293. /// }
  294. ///
  295. /// @for $span from 1 through length(susy-get('columns')) {
  296. /// [data-span*='#{$span}'] {
  297. /// width: span($span);
  298. /// }
  299. /// }