Source: breakpoints.styl

  1. /**
  2. * @namespace Breakpoints
  3. */
  4. $jig---auto-breakpoint = keys($jig---breakpoint-config)[0]
  5. /**
  6. * @namespace Breakpoints:get-auto-breakpoint
  7. */
  8. /**
  9. * Returns the current auto breakpoint value.
  10. *
  11. * @memberof Breakpoints:get-auto-breakpoint
  12. * @function
  13. * @name get-auto-breakpoint
  14. * @alias get-auto-breakpoint
  15. *
  16. * @returns {String} the name of the current named auto breakpoint
  17. *
  18. * @see set-auto-breakpoint
  19. * @see reset-auto-breakpoint
  20. *
  21. * @example
  22. * get-auto-breakpoint()
  23. * => 'medium'
  24. */
  25. get-auto-breakpoint()
  26. return $jig---auto-breakpoint
  27. /**
  28. * @namespace Breakpoints:set-auto-breakpoint
  29. */
  30. /**
  31. * Sets the auto breakpoint to a named breakpoint value.
  32. * Hint: in Stylus we have to do this manually, if we want to use auto breakpoint values,
  33. * since blocks are always evaluated _before_ the block mixin around the block, which results
  34. * in the block only knowing the breakpoint before the mixin.
  35. *
  36. * @memberof Breakpoints:set-auto-breakpoint
  37. * @function
  38. * @name set-auto-breakpoint
  39. * @alias set-auto-breakpoint
  40. *
  41. * @param {String} $breakpoint - a named breakpoint defined in the jig config
  42. * @throws error if breakpoint is unknown
  43. *
  44. * @see reset-auto-breakpoint
  45. * @example
  46. * set-auto-breakpoint(medium)
  47. * +breakpoint(medium)
  48. * ...
  49. */
  50. set-auto-breakpoint($breakpoint)
  51. $breakpoint = to-str($breakpoint)
  52. if $breakpoint in $jig---breakpoint-config
  53. define('$jig---auto-breakpoint', $breakpoint, true)
  54. else
  55. error('jig:set-current-breakpoint | unknown named breakpoint "'+$breakpoint+'"')
  56. /**
  57. * @namespace Breakpoints:reset-auto-breakpoint
  58. */
  59. /**
  60. * Resets the auto breakpoint to the first/smallest named breakpoint defined in the jig config.
  61. * Hint: although you may do this manually in Stylus, this is automatically called at the end of the
  62. * breakpoint mixin, so usually you should be fine with set-auto-breakpoint, without resetting, if you
  63. * use a breakpoint directly after the call.
  64. *
  65. * @memberof Breakpoints:reset-auto-breakpoint
  66. * @function
  67. * @name reset-auto-breakpoint
  68. * @alias reset-auto-breakpoint
  69. *
  70. * @see set-auto-breakpoint
  71. * @example
  72. * reset-auto-breakpoint()
  73. */
  74. reset-auto-breakpoint()
  75. define('$jig---auto-breakpoint', keys($jig---breakpoint-config)[0], true)
  76. /**
  77. * @namespace Breakpoints:is-named-breakpoint
  78. */
  79. /**
  80. * Returns if the given breakpoint is a registered named breakpoint to be found in the jig config.
  81. *
  82. * @memberof Breakpoints:is-named-breakpoint
  83. * @function
  84. * @name is-named-breakpoint
  85. * @alias is-named-breakpoint
  86. *
  87. * @param {String} $breakpoint - a named breakpoint defined in the jig config
  88. * @returns {Boolean} true if breakpoint is a registered named breakpoint name
  89. *
  90. * @example
  91. * is-named-breakpoint(medium)
  92. * => true
  93. */
  94. is-named-breakpoint($breakpoint)
  95. $breakpoint = to-str($breakpoint)
  96. return $breakpoint in $jig---breakpoint-config
  97. /**
  98. * @namespace Breakpoints:build-breakpoint-range
  99. */
  100. /**
  101. * Returns a string to be used in a media query, which defines the range/bounds of a breakpoint with
  102. * min and/or max value.
  103. *
  104. * @memberof Breakpoints:build-breakpoint-range
  105. * @function
  106. * @name build-breakpoint-range
  107. * @alias build-breakpoint-range
  108. *
  109. * @param {?Number} [$min=null] - the min width of the breakpoint
  110. * @param {?Number} [$max=null] - the max width of the breakpoint
  111. * @returns {String} the media query string for the breakpoint range
  112. *
  113. * @example
  114. * build-breakpoint-range(0, 767px)
  115. * => '(min-width: 0) and (max-width: 767px)'
  116. * build-breakpoint-range(null, 100rem)
  117. * => '(max-width: 100rem)'
  118. */
  119. build-breakpoint-range($min=null, $max=null)
  120. $min-query = ($min != null) ? '(min-width: '+$min+')' : null
  121. $max-query = ($max != null) ? '(max-width: '+$max+')' : null
  122. return str-join(($min-query $max-query), ' and ')
  123. /**
  124. * @namespace Breakpoints:build-breakpoint-query
  125. */
  126. /**
  127. * Constructs a query to be used in a media query, based on a breakpoint definition.
  128. * Also automatically converts values to rem.
  129. *
  130. * Directions in composite definitions may be "up", "down" or "only".
  131. *
  132. * You may also define the special breakpoints "landscape" or "portrait" to cover device orientations.
  133. *
  134. * @memberof Breakpoints:build-breakpoint-query
  135. * @function
  136. * @name build-breakpoint-query
  137. * @alias build-breakpoint-query
  138. *
  139. * @param {?Number|Literal|List<String>} [$breakpoint-definition=0] - either a simple number or a composite definition of width and direction, where the width may either be a number or a name defined in the named breakpoints
  140. * @returns {String} the media query string for the breakpoint definition
  141. * @throws error if named breakpoint is unknown
  142. * @throws error if an unnamed breakpoint has an "only" direction
  143. *
  144. * @example
  145. * build-breakpoint-query(200rem)
  146. * => '(min-width: 200rem)'
  147. * build-breakpoint-query(small down)
  148. * => '(max-width: 199rem)'
  149. * build-breakpoint-query(('large' 'only'))
  150. * => '(min-width: 200rem) and (max-width: 499rem)'
  151. * build-breakpoint-query(1024px only)
  152. * => '(min-width: 64rem) and (max-width: 64rem)'
  153. * build-breakpoint-query(landscape)
  154. * => '(orientation: landscape)'
  155. */
  156. build-breakpoint-query($breakpoint-definition=0)
  157. $breakpoint = $breakpoint-definition[0] ? to-str($breakpoint-definition[0], $only-ident:true) : 0
  158. $direction = $breakpoint-definition[1] ? to-str($breakpoint-definition[1]) : 'up'
  159. $breakpoint-name = null
  160. $next-breakpoint = null
  161. $min = null
  162. $max = null
  163. $query-em-conversion-base = 16px // this is always 16px, no matter what is defined on <html>
  164. if $breakpoint == 'overwrite'
  165. return '(min-width: 0)'
  166. else if ($breakpoint == 'landscape') or ($breakpoint == 'portrait')
  167. return '(orientation: '+$breakpoint+')'
  168. else if type($breakpoint) == 'string'
  169. if is-named-breakpoint($breakpoint)
  170. $breakpoint-name = $breakpoint
  171. $breakpoint = $jig---breakpoint-config[$breakpoint-name]
  172. $next-breakpoint = hash-next($jig---breakpoint-config, $breakpoint-name)
  173. else
  174. error('jig:build-breakpoint-query | "'+$breakpoint-definition+'" is not a defined breakpoint')
  175. if ($breakpoint-name == null) and ($direction == 'only')
  176. error('jig:build-breakpoint-query | only named media queries can have an "only" range')
  177. // we are building media queries with em instead of rem and px
  178. // why? => https://zellwk.com/blog/media-query-units/
  179. if ($direction == 'only') or ($direction == 'up')
  180. $min = to-em($breakpoint, $query-em-conversion-base)
  181. if ($direction == 'only') or ($direction == 'down')
  182. if $breakpoint-name == null
  183. $max = to-em($breakpoint, $query-em-conversion-base)
  184. else if $next-breakpoint-name != null
  185. $max = to-em($next-breakpoint, $query-em-conversion-base) - to-em(1px, $query-em-conversion-base)
  186. if ($min == 0) and ($max == null)
  187. $min = null
  188. return build-breakpoint-range($min, $max)
  189. /**
  190. * @namespace Breakpoints:breakpoint
  191. */
  192. /**
  193. * Renders media queries based one one or more breakpoint definitions.
  194. *
  195. * @memberof Breakpoints:breakpoint
  196. * @function
  197. * @name breakpoint
  198. * @alias breakpoint
  199. *
  200. * @param {Number|Literal|List<String>|List<Literal>|List<List<String>>} $breakpoint-definitions - a list of breakpoint definitions according to build-breakpoint-query
  201. *
  202. * @see set-auto-breakpoint
  203. *
  204. * @example
  205. * +breakpoint(small)
  206. * ...
  207. * +breakpoint(small down, large up)
  208. * ...
  209. */
  210. breakpoint($breakpoint-definitions...)
  211. for $breakpoint-definition in $breakpoint-definitions
  212. $query = build-breakpoint-query($breakpoint-definition)
  213. $breakpoint = $breakpoint-definition[0] ? to-str($breakpoint-definition[0], $only-ident:true) : 0
  214. $direction = $breakpoint-definition[1] ? to-str($breakpoint-definition[1]) : 'up'
  215. $breakpoint-index = index(keys($jig---breakpoint-config), $breakpoint)
  216. $print-breakpoint-index = index(keys($jig---breakpoint-config), $jig---print-breakpoint)
  217. // set current breakpoint var to mixin breakpoint value to allow for auto-evaluation inside
  218. if is-named-breakpoint($breakpoint)
  219. set-auto-breakpoint($breakpoint)
  220. if $query == ''
  221. {block}
  222. else
  223. if ($breakpoint-index != null) and (($breakpoint-index <= $print-breakpoint-index) or ($direction == 'down'))
  224. $media-query = s('print, screen and %s', unquote($query))
  225. @media $media-query
  226. {block}
  227. else
  228. $media-query = s('screen and %s', unquote($query))
  229. @media $media-query
  230. {block}
  231. // restore initial value after mixin has been rendered
  232. reset-auto-breakpoint()
  233. /**
  234. * @namespace Breakpoints:breakpoint-value
  235. */
  236. /**
  237. * Search for a value, defined for a breakpoint, in a given hash of values.
  238. * The function escalates in a mobile-first manner. So we take the value for the smallest breakpoint
  239. * and step up the breakpoints one by one until we reach the defined breakpoint. So, if we want the
  240. * according value for "large", but we only have a value for "medium", we'll get the "medium" value, which,
  241. * in mobile-first manner, escalates upwards and is the "large" value if nothing else is defined.
  242. *
  243. * @memberof Breakpoints:breakpoint-value
  244. * @function
  245. * @name breakpoint-value
  246. * @alias breakpoint-value
  247. *
  248. * @param {*|Hash} $value - a hash of breakpoint-keyed map of values, or a simple value
  249. * @param {Literal|String} $breakpoint - either "auto" (to use the current breakpoint) or one of the defined named breakpoints
  250. * @returns {*|null} the breakpoint value or null if nothing was found
  251. * @throws error if named breakpoint is unknown
  252. *
  253. * @example
  254. * breakpoint-value(
  255. * {
  256. * 'small' : 10px,
  257. * 'medium' : 20px
  258. * },
  259. * large
  260. * )
  261. * => 20px
  262. */
  263. breakpoint-value($value, $breakpoint='auto')
  264. $breakpoint = to-str($breakpoint)
  265. if ($breakpoint != 'auto') and !($breakpoint in $jig---breakpoint-config)
  266. error('jig:breakpoint-value | given breakpoint "'+$breakpoint+'" not defined')
  267. if type($value) == 'object'
  268. $res = null
  269. if $breakpoint == 'auto'
  270. $breakpoint = get-auto-breakpoint()
  271. for $breakpoint-name, $breakpoint-definition in $jig---breakpoint-config
  272. $breakpoint-value = $value[$breakpoint-name]
  273. if $breakpoint-value != null
  274. $res = $breakpoint-value
  275. if $breakpoint-name == $breakpoint
  276. return $res
  277. return null
  278. else
  279. return $value
  280. /**
  281. * @namespace Breakpoints:attributes-for-breakpoints
  282. */
  283. /**
  284. * Renders attribute values for given attributes for defined breakpoints.
  285. *
  286. * Definitions will be rendered together if possible, minimizing the amount of media queries.
  287. * However, each call of this mixin will, most likely, render multiple media queries, so keep a close eye
  288. * on your media query structure to avoid unnecessarily doubled definitions and keep media queries to a minimum.
  289. * If in doubt, it might be a better idea to write the queries manually, perhaps rather using `[]` or
  290. * `breakpoint-value` to automatically pull values from breakpoint value hashes.
  291. *
  292. * @memberof Breakpoints:attributes-for-breakpoints
  293. * @function
  294. * @name attributes-for-breakpoints
  295. * @alias attributes-for-breakpoints
  296. *
  297. * @see attribute-for-breakpoints
  298. *
  299. * @param {Hash} $attributes - keys are attribute names, while values are either plain values or hashes with breakpoint name keys, providing different values per breakpoint
  300. * @param {Number} [$factor=null] - if a float factor is provided all values will be multiplied with this factor
  301. *
  302. * @example
  303. * attributes-for-breakpoints(
  304. * {
  305. * 'font-size' : 12px,
  306. * 'line-height' : {
  307. * 'small' : 1,
  308. * 'large' : 1.25
  309. * },
  310. * 'margin-top' : {
  311. * 'small' : 10px,
  312. * 'medium' : 20px
  313. * }
  314. * },
  315. * 2.0
  316. * )
  317. */
  318. attributes-for-breakpoints($attributes, $factor=null)
  319. $attributes-for-breakpoints = {}
  320. for $attribute-name, $attribute-value in $attributes
  321. if type($attribute-value) != 'object'
  322. if $factor == null
  323. {$attribute-name} $attribute-value
  324. else
  325. {$attribute-name} ($factor * $attribute-value)
  326. else
  327. for $breakpoint-name, $breakpoint-definition in $jig---breakpoint-config
  328. $breakpoint-value = $attribute-value[$breakpoint-name]
  329. if ($breakpoint-value != null) or (type($breakpoint-value) == 'call')
  330. if !($breakpoint-name in $attributes-for-breakpoints)
  331. $attributes-for-breakpoints[$breakpoint-name] = {}
  332. $attributes-for-breakpoints[$breakpoint-name][$attribute-name] = $breakpoint-value;
  333. for $breakpoint-name, $breakpoint-definition in $jig---breakpoint-config
  334. $breakpoint-attributes = $attributes-for-breakpoints[$breakpoint-name]
  335. if ($breakpoint-attributes != null) and (length($breakpoint-attributes) > 0)
  336. +breakpoint($breakpoint-name)
  337. for $attribute-name, $attribute-value in $breakpoint-attributes
  338. if $factor == null
  339. {$attribute-name} $attribute-value
  340. else
  341. {$attribute-name} ($factor * $attribute-value)
  342. /**
  343. * @namespace Breakpoints:attribute-for-breakpoints
  344. */
  345. /**
  346. * Renders attribute values for given attribute for defined breakpoints.
  347. *
  348. * This is the single attribute version of `attributes-for-breakpoints`.
  349. * Since this version does not optimize the usage of media queries, please make sure to only use this mixin,
  350. * if you'll definitely only have one attribute to be defined in multiple breakpoints.
  351. *
  352. * @memberof Breakpoints:attribute-for-breakpoints
  353. * @function
  354. * @name attribute-for-breakpoints
  355. * @alias attribute-for-breakpoints
  356. *
  357. * @see attributes-for-breakpoints
  358. *
  359. * @param {String} $attribute - the name of the attribute you want to set
  360. * @param {*} $value - the value to set the attribute to
  361. * @param {Number} [$factor=null] - if a float factor is provided the value will be multiplied with this factor
  362. *
  363. * @example
  364. * attribute-for-breakpoints(
  365. * 'line-height',
  366. * {
  367. * 'small' : 1,
  368. * 'large' : 1.25
  369. * },
  370. * 1.0
  371. * )
  372. */
  373. attribute-for-breakpoints($attribute, $value, $factor=null)
  374. $attributes = {}
  375. $attributes[to-str($attribute)] = $value
  376. attributes-for-breakpoints($attributes, $factor)
  377. /**
  378. * @namespace Breakpoints:overwrite-breakpoint-for-attributes
  379. */
  380. /**
  381. * Use this, if you need to overwrite attribute values previously defined in (a) breakpoint(s).
  382. *
  383. * A use case might be, for example, to set a font-size to a static value in an element with a responsive,
  384. * breakpoint-based font-size definition.
  385. *
  386. * @memberof Breakpoints:overwrite-breakpoint-for-attributes
  387. * @function
  388. * @name overwrite-breakpoint-for-attributes
  389. * @alias overwrite-breakpoint-for-attributes
  390. *
  391. * @param {Hash} $attributes - keys are attribute names, while values are either plain values or hashes with breakpoint name keys, providing different values per breakpoint
  392. * @param {Number} [$factor=null] - if a float factor is provided all values will be multiplied with this factor
  393. *
  394. * @see overwrite-breakpoint-for-attribute
  395. *
  396. * @example
  397. * overwrite-breakpoint-for-attributes(
  398. * {
  399. * 'font-size' : 12px,
  400. * 'line-height' : 1.25
  401. * 'margin-top' : 20px
  402. * },
  403. * 2.0
  404. * )
  405. */
  406. overwrite-breakpoint-for-attributes($attributes, $factor=null)
  407. +breakpoint('overwrite')
  408. for $attribute-name, $attribute-value in $attributes
  409. if $factor == null
  410. {$attribute-name} $attribute-value
  411. else
  412. {$attribute-name} ($factor * $attribute-value)
  413. /**
  414. * @namespace Breakpoints:overwrite-breakpoint-for-attribute
  415. */
  416. /**
  417. * Use this, if you need to overwrite an attribut value previously defined in (a) breakpoint(s).
  418. *
  419. * A use case might be, for example, to set a font-size to a static value in an element with a responsive,
  420. * breakpoint-based font-size definition.
  421. *
  422. * @memberof Breakpoints:overwrite-breakpoint-for-attribute
  423. * @function
  424. * @name overwrite-breakpoint-for-attribute
  425. * @alias overwrite-breakpoint-for-attribute
  426. *
  427. * @see overwrite-breakpoint-for-attributes
  428. *
  429. * @param {String} $attribute - the name of the attribute you want to set
  430. * @param {*} $value - the value to set the attribute to
  431. * @param {Number} [$factor=null] - if a float factor is provided the value will be multiplied with this factor
  432. *
  433. * @example
  434. * overwrite-breakpoint-for-attribute(font-size, 12px, 2.0)
  435. */
  436. overwrite-breakpoint-for-attribute($attribute, $value, $factor=null)
  437. $attributes = {}
  438. $attributes[to-str($attribute)] = $value
  439. overwrite-breakpoint-for-attributes($attributes, $factor)
  440. /**
  441. * @namespace Breakpoints:overwrite-breakpoint
  442. */
  443. /**
  444. * Use this, if you need to overwrite something previously defined in (a) breakpoint(s).
  445. *
  446. * A use case might be, for example, to redefine something statically in an override situation, which has
  447. * been defined responsively before.
  448. *
  449. * @memberof Breakpoints:overwrite-breakpoint
  450. * @function
  451. * @name overwrite-breakpoint
  452. * @alias overwrite-breakpoint
  453. *
  454. * @example
  455. * +overwrite-breakpoint()
  456. * font-size 12xp
  457. * margin-top 20px
  458. */
  459. overwrite-breakpoint()
  460. +breakpoint('overwrite')
  461. {block}