Skip to content

Instantly share code, notes, and snippets.

@cimmanon
Last active February 11, 2016 02:51
Show Gist options
  • Save cimmanon/6b646b9b0ad8212da3c2 to your computer and use it in GitHub Desktop.
Save cimmanon/6b646b9b0ad8212da3c2 to your computer and use it in GitHub Desktop.
New Flexbox mixins (in progress)
// $flexbox-support values:
// standard: Draft #3
// modern: Draft #2 or newer
// legacy: Draft #1 only
// wrap: versions that support wrapping (includes feature query on the display property on the unprefixed standard value)
// all: all versions
$flexbox-support-threshold: $critical-usage-threshold !default;
$flexbox-support: modern !default;
$flexbox-warnings: true !default;
// @private
@function flexbox-capability-options($support: $flexbox-support) {
@if type-of($flexbox-support) == list { // this might need to be here for users who are expecting the older format for this variable
@warn "The $flexbox-support variable as a list has been deprecated, setting $flexbox-support to `modern`";
$flexbox-support: modern !global;
}
@if $support == wrap {
@return (), ((spec-versions: 2), ), ((spec-versions: 3, partial-support: false), (full-support: true));
} @else if $support == standard {
@return (), (), ((spec-versions: 3), (full-support: true));
} @else if $support == legacy {
@return (spec-versions: 1), (), ();
} @else if $support == modern {
@return (), ((spec-versions: 2), ), ((spec-versions: 3, partial-support: false), (full-support: true));
} @else { // all
@return (spec-versions: 1), ((spec-versions: 2), ), ((spec-versions: 3), (full-support: true));
}
}
// @private
@function flexbox-translate-value($value, $version: 1) {
$value: unquote($value);
@if $value == flex {
@return if($version == 1, box, flexbox);
} @else if $value == inline-flex {
@return if($version == 1, inline-box, inline-flexbox);
} @else if $value == flex-start {
@return start;
} @else if $value == flex-end {
@return end;
} @else if $value == space-between {
@return justify;
} @else if $value == space-around { // @box doesn't have a value equivalent to `space-around`
@return if($version == 1, justify, distribute);
}
@return $value;
}
// @private
@mixin flexbox($styles, $warnings: ()) {
// length($styles) == 3: v1, v2, v3
// length($styles) == 2: v1, v2 & v3
// length($styles) == 1: v3
$options: flexbox-capability-options($flexbox-support);
$versions: length($styles);
@if $versions == 1 {
$options: nth($options, 3);
} @else if $versions == 2 {
$options: nth($options, 1), join(nth($options, 2), nth($options, 3));
}
@for $i from 1 through $versions {
$current-options: nth($options, $i);
@if $flexbox-warnings and length($warnings) >= $i {
$warning-shown: false;
$prefixes: prefixes-for-capability(flexbox, $flexbox-support-threshold, nth($options, $i));
@each $browser, $min-ver in $prefixes {
@if not $warning-shown and ($min-ver or $i == $versions) and nth($warnings, $i) {
@warn nth($warnings, $i);
$warning-shown: true;
}
}
}
@include with-each-prefix(flexbox, $flexbox-support-threshold, $current-options) {
// length($current-options) == 0 when spitting out only v1 properties via `$flexbox-support: legacy`
// in order to show the unprefixed properties, it needs to be the most recent version *and* have something for $current-options
$show-unprefixed: $i == $versions and length($current-options) > 0;
@if $current-prefix or $show-unprefixed {
@each $prop, $value in nth($styles, $i) {
@if $prop == display {
@if $show-unprefixed and not $current-prefix {
@if $flexbox-support == wrap {
@supports (flex-wrap: wrap) { // hide Flexbox from versions of Firefox that do not support wrapping
display: $value;
}
} @else {
display: $value;
}
} @else {
display: prefix-identifier($value);
}
} @else {
@include prefix-prop($prop, $value);
}
}
}
}
}
}
// @public
@mixin flexbox-support($support: $flexbox-support) {
$previous-support: $flexbox-support !global;
$flexbox-support: $support !global;
@content;
$flexbox-support: $previous-support !global;
}
// @flex container properties
@mixin display-flex($value: flex) {
@include flexbox(
( (display: flexbox-translate-value($value, 1))
, (display: flexbox-translate-value($value, 2))
, (display: $value)
));
}
@mixin flex-direction($value: row) {
@include flexbox(
( ( box-orient: if($value == row or $value == row-reverse, horizontal, vertical)
, box-direction: if($value == row or $value == column, normal, reverse)
)
, (flex-direction: $value)
));
}
@mixin flex-wrap($value: nowrap) {
$warnings:
( "Flexbox v1 has properties for wrapping but no browser has implemented them, change your flexbox-support to `wrap` to hide Flexbox from them"
, "Firefox versions 22-28 do not support wrapping for Flexbox v3, change your flexbox-support to `wrap` to hide Flexbox from them"
);
@include flexbox(
( (box-lines: if($value == nowrap, single, multiple))
, (flex-wrap: $value)
), if($flexbox-support != wrap and $value != nowrap, $warnings, ()));
}
@mixin flex-flow($value: row nowrap) {
$warnings:
( "Flexbox v1 has properties for wrapping but no browser has implemented them, change your flexbox-support to `wrap` to hide Flexbox from them"
, "Firefox versions 22-28 do not support wrapping for Flexbox v3, change your flexbox-support to `wrap` to hide Flexbox from them"
);
$direction: null;
$wrap: null;
@if length($value) == 2 {
$direction: nth($value, 1);
$wrap: nth($value, 2);
} @else {
@if $value == nowrap or $value == wrap or $value == wrap-reverse {
$wrap: $value;
} @else {
$direction: $value;
}
}
@include flexbox(
( ( box-orient: if($direction == row or $direction == row-reverse, horizontal, vertical)
, box-direction: if($direction == row or $direction == column, normal, reverse)
, box-lines: if($wrap == nowrap, single, multiple)
)
, (flex-flow: $value)
), if($flexbox-support != wrap and ($wrap == wrap or $wrap == wrap-reverse), $warnings, ()));
}
@mixin justify-content($value: stretch) {
@include flexbox(
( (box-pack: flexbox-translate-value($value, 1))
, (flex-pack: flexbox-translate-value($value, 2))
, (justify-content: $value)
));
}
@mixin align-content($value: stretch) {
$warnings:
( "Flexbox v1 does not have an align-content property"
, null
, null
);
@include flexbox(
( null
, (flex-line-pack: flexbox-translate-value($value, 2))
, (align-content: $value)
), $warnings);
}
@mixin align-items($value: stretch) {
@include flexbox(
( (box-align: flexbox-translate-value($value, 1))
, (flex-align: flexbox-translate-value($value, 2))
, (align-items: $value)
));
}
// @flex item properties
@mixin align-self($value: stretch) {
$warnings:
( "Flexbox v1 does not have an align-self property, only align-content"
, null
, null
);
@include flexbox(
( ()
, (flex-item-align: flexbox-translate-value($value, 2))
, (align-self: $value)
), $warnings);
}
@mixin flex($value: 1 0 auto) {
// TODO: determine what kind of warning makes sense here
// Flexbox v1 doesn't let you control flex-grow and flex-shrink values independently
// (minor issue), nor does it have a concept of flex-basis (moderate issue).
// `box-flex: 1` is equivalent to `flex: 1 1`. There's no way to recreate `flex: 1 0`
// or `flex: 0 1`, though there are few instances where this is actually a problem
// see: http://stackoverflow.com/questions/16130399/flexbox-in-safari-grow-and-shrink
$warnings:
( "Flexbox v1 does not support flex-basis for the `flex` property at all"
, null
, null
);
@include flexbox(
( (box-flex: nth($value, 1))
, (flex: $value)
, (flex: $value)
), if(length($value) > 2 or not unitless(nth($value, length($value))), $warnings, ()));
}
@mixin flex-grow($value: auto) {
$warnings:
( "Flexbox v1 does not have a flex-grow property, try using the `flex` property instead"
, "Flexbox v2 does not have a flex-grow property, set it via the `flex` property instead"
, null
);
@include flexbox(
( ()
, ()
, (flex-grow: $value)
), $warnings);
}
@mixin flex-shrink($value: auto) {
$warnings:
( "Flexbox v1 does not have a flex-shrink property"
, "Flexbox v2 does not have a flex-shrink property, set it via the `flex` property instead"
, null
);
@include flexbox(
( ()
, ()
, (flex-shrink: $value)
), $warnings);
}
@mixin flex-basis($value: auto) {
$warnings:
( "Flexbox v1 does not have a flex-basis property"
, "Flexbox v2 does not have a flex-basis property, set it via the `flex` property instead"
, null
);
@include flexbox(
( ()
, ()
, (flex-basis: $value)
), $warnings);
}
@mixin order($value: 0) {
$warnings:
( "Flexbox v1 does not support negative ordering, try increasing the order of the sibling elements instead"
, null
, null
);
@include flexbox(
( (box-ordinal-group: $value + 1)
, (flex-order: $value)
, (order: $value)
), if($value < 0, $warnings, ()));
}
@import "translucencss";
//$debug-browser-support: true;
// ====================================================================================================
// | Modern (default)
// ====================================================================================================
.modern {
&.container {
@include display-flex;
@include flex-direction(column);
@include align-items(flex-start);
.item {
@include flex(1);
@include align-self(flex-end);
@include order(1);
}
}
}
// ====================================================================================================
// | Wrap
// ====================================================================================================
.wrap {
@include flexbox-support(wrap) {
&.container {
@include display-flex;
@include flex-wrap(wrap);
@include justify-content(space-between);
}
}
}
// ====================================================================================================
// | Standard
// ====================================================================================================
.standard {
@include flexbox-support(standard) {
&.container {
@include display-flex;
.item {
@include flex-grow(1);
}
}
}
}
// ====================================================================================================
// | Legacy
// ====================================================================================================
.legacy {
@include flexbox-support(legacy) {
&.container {
@include display-flex;
@include flex-direction(column);
@include justify-content(center);
@include align-items(center);
}
}
}
// ====================================================================================================
// | All
// ====================================================================================================
.all {
@include flexbox-support(all) {
&.container {
@include display-flex;
@include align-items(flex-start);
.item {
@include order(2);
&:nth-child(3n+2) {
@include order(2);
}
&:nth-child(3n+3) {
@include order(3);
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment