Skip to content

Instantly share code, notes, and snippets.

@nicolas-cusan
Last active April 9, 2018 16:48
Show Gist options
  • Select an option

  • Save nicolas-cusan/8fc0cef0f466f6ca2ebc to your computer and use it in GitHub Desktop.

Select an option

Save nicolas-cusan/8fc0cef0f466f6ca2ebc to your computer and use it in GitHub Desktop.
Sass position mixin to generate position properties in shorthand form.
//============================================
// Position Mixin
//============================================
// Generate position properties in shorthand form.
//
// @param {List} $values - List of numbers or `auto`
// @param {List} $sides - List of sides (`top`, `left`, `bottom`, `right` or `all`)
// @param {String} $pos - Position keyword or `none`
// @param {Bool} $auto-overwrite - If `true` all non specified $sides will be set to `auto`
//
// NOTE: `$values` get mapped to `$sides` in the order they are declared, see usage below
//
// https://gist.github.com/nicolas-cusan/8fc0cef0f466f6ca2ebc
@mixin position($values, $sides, $pos: absolute, $auto-overwrite: false) {
// Vars
$positions: absolute, relative, fixed, static;
$map: (top: null, left: null, right: null, bottom: null);
// Set everything to auto to overwrite other styles.
// Edge case but can be useful.
@if $auto-overwrite {
$map: ( top: auto, left: auto, right: auto, bottom: auto);
}
// Validate `$values` & `$sides` input and warn (input gets rendered though)
@each $value in $values {
@if type-of($value) == number or $value == auto {} @else {
@warn "Invalid amount: #{$value}";
}
}
@each $side in $sides {
@if index(map-keys($map), $side) or $side == all {} @else {
@warn "Invalid side: #{$side}";
}
}
// Render & Validate `$pos`
@if index($positions, $pos) {
position: $pos;
} @else if $pos != none {
@warn "The $pos argument is invalid, use `absolute`, `fixed`, `relative`, `static`, or `none` (invalid value: #{$pos})";
}
// Populate the map with `$sides`
@if $sides == all and length($values) == 1 {
top: $values; left: $values; right: $values; bottom: $values;
} @else if length($sides) == length($values) {
@for $i from 1 through length($sides) {
$map: map-merge($map, (nth($sides, $i):nth($values, $i)));
}
} @else if length($values) == 1 {
@for $i from 1 through length($sides) {
$map: map-merge($map, (nth($sides, $i):$values));
}
} @else {
@warn "The number of $values has to match the $sides or be a single value";
}
// Render (properties with value `null` don't get rendered)
@each $key, $val in $map {
#{$key}: #{$val};
}
}
// Alias
@mixin pos($values, $sides, $pos: absolute, $auto-overwrite: false) {
@include position($values, $sides, $pos, $auto-overwrite);
}
//============================================
// Usage
//============================================
// Same value for sides.
.my-class {
@include pos(0, top left);
}
// -> Output
// .my-class {
// position: absolute;
// top: 0;
// left: 0;
// }
// Same value for `all` sides,
// `all` only works if all sides have the same value.
.my-class {
@include pos(0, all, fixed);
}
// -> Output
// .my-class {
// position: fixed;
// top: 0;
// left: 0;
// right: 0;
// bottom: 0;
// }
// Different values for sides.
.my-class {
@include pos(auto 200px 3em, top left right);
}
// -> Output
// .my-class {
// position: absolute;
// top: auto;
// left: 200px;
// right: 3em;
// }
// No positioning using `none`.
// It will probably be better to not use the a mixin for this
// but it can be useful if you use the mixin in a loop.
.my-class {
@include pos(0 3px, left top, none);
}
// -> Output
// .my-class {
// top: 3px;
// left: 0;
// }
// Overwrite not specified sides with `auto` to overwrite inherited rules.
// It's dirty but useful at times.
.my-class {
@include pos(0 200px, top left, $auto-overwrite: true);
}
// -> Output
// .my-class {
// position: absolute;
// top: 0;
// left: 200px;
// right: auto;
// bottom: auto;
// }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment